CircleCI 2.0:SSH部署(scp/rsync)构建目录及作业关系咨询
我来帮你理清CircleCI 2.0里独立作业(jobs)的核心逻辑,这也是很多刚接触CircleCI的开发者容易踩的坑!
为什么独立作业找不到构建目录?
CircleCI 2.0里的每个作业(job)都是完全独立的运行环境——不管是build还是deploy,它们各自跑在单独的容器或虚拟机里,默认情况下,一个作业生成的文件不会自动传递到另一个作业。
你之前尝试设置working_directory、CIRCLE_WORKING_DIRECTORY都无效,就是因为这些变量只作用于当前作业的环境。比如build作业的~/repo_name是build容器里的路径,deploy作业里的~/repo_name是deploy容器里的全新空目录,两者完全没关系。
正确的解决方案:用工作区(Workspaces)共享文件
CircleCI提供了**工作区(Workspaces)**机制,专门用来在不同作业之间传递文件。针对你的circleci-demo-php-laravel场景,具体配置如下:
1. 在Build作业中保存文件到工作区
在build作业的构建步骤完成后,添加persist_to_workspace步骤,把需要部署的文件(比如编译后的代码、依赖包等)保存到工作区:
jobs: build: working_directory: ~/laravel steps: # 你的构建步骤:checkout、composer install、npm run prod等 - run: composer install - run: npm run prod # 把需要部署的文件保存到工作区 - persist_to_workspace: root: ~/laravel # 要共享的文件根目录,对应build的working_directory paths: - . # 共享整个目录,或者指定具体路径比如public/、vendor/、.env等
2. 在Deploy作业中挂载工作区
在deploy作业的开头,添加attach_workspace步骤,把build作业保存的工作区文件拉取到当前作业的环境中:
jobs: deploy: working_directory: ~/laravel steps: # 先挂载工作区,把build的文件拉到当前作业的working_directory - attach_workspace: at: ~/laravel # 要挂载的目标路径,和build的root对应 # 现在就可以用scp/rsync部署了,路径就是当前作业的working_directory下的文件 - run: scp -r ~/laravel/public user@your-server:/var/www/html/
这样一来,deploy作业里就能访问到build阶段生成的所有文件,scp的路径自然就正确了。
补充:Working Directory的作用误区
working_directory只是单个作业内部的默认工作路径,它不会跨作业共享。比如你把build和deploy的working_directory都设为~/laravel,build作业里的~/laravel是有构建文件的,但deploy作业里的~/laravel初始是空的,必须通过attach_workspace把build的文件拉过来才会有内容。
为什么合并阶段能解决问题?
当你把build和deploy合并到同一个作业时,所有步骤都在同一个运行环境里执行,构建生成的文件自然保留在当前目录中,所以scp能直接找到正确的路径。但分开作业的话,就必须用工作区来完成文件传递。
其他可选方案
如果只是共享依赖包这类不需要每次更新的文件,也可以用CircleCI的**缓存(Caching)**机制,但缓存更适合复用依赖,部署用的构建产物还是用工作区更可靠,因为工作区会保存每次build后的最新文件,不会有缓存过期或旧版本的问题。
内容的提问来源于stack exchange,提问作者dmgig

