GitHub Actions一直在使用develop分支的最新提交,而不是main分支的提交

后端开发 2026-07-09

使用这个简单的GitHub Actions工作流:

name: Deploy to Production

on:
    workflow_run:
        workflows: [ "CI - Tests & Quality" ]
        types: [ completed ]
        branches: [ main ]
    workflow_dispatch:
        inputs:
            skip_tests:
                description: 'Skip test requirement (emergency only)'
                required: false
                type: boolean
                default: false

env:
    DEPLOY_PATH: ${{ vars.PRODUCTION_PATH }}

jobs:
    pre-deploy-checks:
        name: Pre-deployment Checks
        runs-on: ubuntu-latest
        if: |
            github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch'
        outputs:
            deployment-id: ${{ steps.prepare.outputs.deployment_id }}

        steps:
            -   name: Prepare deployment with branch validation
                id: prepare
                run: |
                    if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
                        COMMIT_SHA="${{ github.sha }}"
                        BRANCH="main"
                    else
                        WORKFLOW_BRANCH="${{ github.event.workflow_run.head_branch }}"

                        if [ "$WORKFLOW_BRANCH" != "main" ]; then
                            echo "❌ Deployment cancelled: CI workflow ran on branch '${WORKFLOW_BRANCH}', not 'main'"
                            exit 1
                        fi

                        COMMIT_SHA="${{ github.event.workflow_run.head_sha }}"
                        BRANCH="$WORKFLOW_BRANCH"
                    fi

                    DEPLOYMENT_ID="deploy-$(date +%Y%m%d-%H%M%S)-${COMMIT_SHA::7}"
                    echo "deployment_id=${DEPLOYMENT_ID}" >> $GITHUB_OUTPUT
                    echo "commit_sha=${COMMIT_SHA}" >> $GITHUB_OUTPUT
                    echo "branch=${BRANCH}" >> $GITHUB_OUTPUT

                    echo "🚀 Starting deployment: ${DEPLOYMENT_ID}"
                    echo "📦 Branch: ${BRANCH}"
                    echo "📦 Commit: ${COMMIT_SHA}"

    deploy:
        name: Deploy to Production Server
        needs: pre-deploy-checks
        runs-on: self-hosted
        timeout-minutes: 10

        steps:
            -   name: Set deployment variables
                run: |
                    echo "DEPLOYMENT_ID=${{ needs.pre-deploy-checks.outputs.deployment-id }}" >> $GITHUB_ENV
                    echo "TIMESTAMP=$(date +%Y%m%d_%H%M%S)" >> $GITHUB_ENV
                    echo "CURRENT_USER=$(whoami)" >> $GITHUB_ENV

它是由其他工作流触发的:

name: CI - Tests & Quality

on:
    push:
        branches: [ main, develop ]
    pull_request:
        branches: [ main, develop ]
    workflow_run:
        workflows: [ "Build Docker Image" ]
        types: [ completed ]
    workflow_dispatch:

concurrency:
    group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
    cancel-in-progress: true

部署到生产环境时仍然使用我develop分支上最后一次提交的提交哈希,而不是main分支的提交。

如何才能确认它使用的是正确的分支?

解决方案

我认为生产工作流并不总是会选用最新的main提交,因为它是通过workflow_run触发的。CI工作流可以来自多种来源,比如main、develop、PRs,以及在Docker构建工作流之后触发。因此,即使生产工作流配置为针对main,它仍可能接收到来自另一个分支或较旧SHA的前一个工作流上下文。

为了确保安全,不应在部署工作流中依赖默认的github.sha。相反,应明确部署通过前一个工作流的确切提交,使用:

github.event.workflow_run.head_sha

修复步骤:

步骤1:在生产工作流中添加调试日志。

- name: Debug workflow
  run: |
    echo "event_name=${{ github.event_name }}"
    echo "head_branch=${{ github.event.workflow_run.head_branch }}"
    echo "head_sha=${{ github.event.workflow_run.head_sha }}"
    echo "github_ref=${{ github.ref }}"
    echo "github_sha=${{ github.sha }}"

步骤2:在部署前添加分支检查 确保只有当完成的CI工作流来自main分支时,生产才会运行。

if: >
  github.event.workflow_run.conclusion == 'success' &&
  github.event.workflow_run.head_branch == 'main'

步骤3:检出通过CI的确切提交 不要让检出使用默认的SHA,而要显式检出经过测试的提交。

- name: Checkout exact tested commit
  uses: actions/checkout@v4
  with:
    ref: ${{ github.event.workflow_run.head_sha }}

步骤4:同样限制上游工作流 如果CI工作流是由像Docker构建这样的其他工作流触发的,那么该触发也应限制为main。

on:
  workflow_run:
    workflows: ["Build Docker Image"]
    types: [completed]
    branches: [main]
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章