Monorepo中基于特定路径变更的GitHub Workflow触发条件配置
针对Monorepo语义化发布的路径触发优化方案
核心思路
不用在Workflow里写复杂的git diff临时逻辑,而是通过绑定子包与独立语义化版本、复用成熟Monorepo工具实现精准触发,同时统一分支提交和Tag发布的部署逻辑。
1. 给子包分配独立的语义化Tag
放弃仓库级统一Tag,给每个app生成带前缀的专属Tag(比如app1/v1.2.3或app1-v0.4.1),从Tag名称直接定位要部署的app,完全省去变更路径检测步骤。
实现步骤:
- 调整语义化发布工具:用
changesets或带Monorepo插件的semantic-release,配置为仅给有变更的子包生成对应Tag。- 比如
changesets会自动跟踪每个app目录下的变更记录,发布时生成@your-org/app1@1.2.3这类包版本Tag,或者自定义格式为app1-v1.2.3。
- 比如
- 配置Tag触发的Workflow:
on: push: tags: - 'app*/*' # 匹配app1/v1.2.3格式 - 'app*-v*' # 匹配app1-v1.2.3格式 - 在Job中提取app名称并部署:
jobs: deploy: runs-on: ubuntu-latest steps: - name: 提取app名称 id: extract-app run: | TAG="${GITHUB_REF#refs/tags/}" if [[ $TAG == app*/v* ]]; then APP_NAME="${TAG%%/*}" elif [[ $TAG == app*-v* ]]; then APP_NAME="${TAG%-v*}" fi echo "app_name=$APP_NAME" >> $GITHUB_OUTPUT - name: 部署${{ steps.extract-app.outputs.app_name }} run: ./apps/${{ steps.extract-app.outputs.app_name }}/deploy.sh
2. 用Changesets自动关联变更与部署
changesets是Monorepo场景下的首选工具之一,它能自动跟踪每个子包的变更,发布时仅更新有变更的app版本。你可以利用它的输出直接传递变更列表给部署Workflow。
实现步骤:
- 在语义化发布Workflow中,导出变更的app列表:
# 生成变更app的JSON文件 npx changeset list --since=HEAD~1 --json > changed-apps.json # 上传为artifact供部署Workflow使用 uses: actions/upload-artifact@v4 with: name: changed-apps path: changed-apps.json - 部署Workflow读取列表并批量部署:
jobs: deploy-changed: runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4 with: name: changed-apps - name: 批量部署变更app run: | # 用jq解析JSON,提取app名称(假设包名是@your-org/app1,对应目录apps/app1) CHANGED_APPS=$(cat changed-apps.json | jq -r '.[].name | sub("@your-org/"; "")') for APP in $CHANGED_APPS; do ./apps/$APP/deploy.sh done
3. 统一分支提交与Tag触发的部署逻辑
把部署单个app的逻辑封装成可复用的Workflow模板,不管是main分支的路径变更触发,还是Tag触发,都调用同一个模板,减少重复代码。
示例:
- 创建模板文件
.github/workflows/templates/deploy-app.yml:name: 部署单个App on: workflow_call: inputs: app-name: type: string required: true jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 部署${{ inputs.app-name }} run: ./apps/${{ inputs.app-name }}/deploy.sh - main分支的Workflow用Paths-Filter检测变更,调用模板:
name: Main分支变更部署 on: push: branches: [main] jobs: detect-changes: runs-on: ubuntu-latest outputs: app1: ${{ steps.filter.outputs.app1 }} app5: ${{ steps.filter.outputs.app5 }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: filters: | app1: - 'apps/app1/**' app5: - 'apps/app5/**' deploy-app1: needs: detect-changes if: needs.detect-changes.outputs.app1 == 'true' uses: ./.github/workflows/templates/deploy-app.yml with: app-name: app1 deploy-app5: needs: detect-changes if: needs.detect-changes.outputs.app5 == 'true' uses: ./.github/workflows/templates/deploy-app.yml with: app-name: app5 - Tag触发的Workflow提取app名称后调用模板:
name: Tag触发部署 on: push: tags: - 'app*/*' jobs: extract-app: runs-on: ubuntu-latest outputs: app-name: ${{ steps.extract.outputs.app_name }} steps: - name: 提取app名称 id: extract run: | TAG="${GITHUB_REF#refs/tags/}" APP_NAME="${TAG%%/*}" echo "app_name=$APP_NAME" >> $GITHUB_OUTPUT deploy: needs: extract-app uses: ./.github/workflows/templates/deploy-app.yml with: app-name: ${{ needs.extract-app.outputs.app-name }}
关键注意事项
- 避免在Workflow中写复杂的
git diff逻辑,依赖成熟工具跟踪变更更可靠。 - 保持Tag与子包的一一对应关系,让Tag本身携带部署目标信息,简化触发逻辑。
- 复用Workflow模板减少重复配置,让整个CI/CD流程更易于维护。
内容的提问来源于stack exchange,提问作者MadaraUchiha
相关产品推荐
相关产品推荐

