You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitHub Action技术问题:修改PR目标分支后如何获取最新分支名

解决GitHub Workflow PR目标分支修改后变量不更新的问题

问题描述

我编写了一个GitHub Workflow,用于禁止非Release分支合并到main分支,原本运行正常。但当用户创建普通分支到main的PR后,若修改PR的目标分支为其他分支,重新运行Workflow时,它仍会将原main分支识别为目标分支。排查确认是Workflow的上下文变量在PR创建时生成,重启后不会更新导致的。

原因分析

GitHub Actions中,PR创建时触发的Workflow run会缓存当时的上下文变量(如github.base_ref、github.event.pull_request.base.ref)。即使后续修改了PR的目标分支,重新运行该旧Workflow run时,这些缓存的变量不会同步更新,导致判断逻辑基于旧的分支信息。

解决方案

通过GitHub API实时拉取PR的最新信息,替代缓存的上下文变量。修改can-merge-pr任务中的分支判断逻辑,直接从API获取当前PR的源分支和目标分支:

修改后的完整Workflow代码

name: CI

on:
  push:
    branches-ignore:
      - 'skip-ci-*'
  pull_request:
    branches-ignore:
      - 'skip-ci-*'
    
permissions:
  contents: write
  pull-requests: read  # 添加PR读取权限,确保API调用正常
    
env:
    REPOSITORY_MIRROR: "my-repo.git"

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Fetch repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Build
        run: |
          make
          if [ $? -ne 0 ]; then
            echo "Build failed"
            exit 1
          fi

  tests:
    needs: build
    runs-on: ubuntu-latest

    steps:
      - name: Fetch repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name : run_tests
        run: |
          make tests_run
              
  # push:
  #   needs: tests
  #   runs-on: ubuntu-latest


  #   if: ${{ github.event_name == 'push' }}

  #   steps:
  #     - name: checkout
  #       uses: actions/checkout@v4
  #       with:
  #         fetch-depth: 0
  #         target_repo_url: ${{ env.REPOSITORY_MIRROR }}
  #         ssh_private_key: ${{ secrets.GIT_SSH_PRIVATE_KEY }}
      
  #     - name: Push changes
  #       uses: pixta-dev/repository-mirroring-action@v1
  #       with: 
  #           fetch-depth: 0
  #           target_repo_url: ${{ env.REPOSITORY_MIRROR }}
  #           ssh_private_key: ${{ secrets.GIT_SSH_PRIVATE_KEY }}


  can-merge-pr:
    if: ${{ github.event_name == 'pull_request' }}
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Install jq (JSON解析工具)
        run: sudo apt-get update && sudo apt-get install -y jq

      - name: Check branch names (实时获取PR最新分支信息)
        run: |
          # 调用GitHub API获取当前PR的最新数据
          PR_INFO=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
            "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}")
          
          # 解析出源分支和目标分支
          source=$(echo "$PR_INFO" | jq -r '.head.ref')
          target=$(echo "$PR_INFO" | jq -r '.base.ref')
          
          if [ "$source" == "$target" ]; then
            echo "Branches are the same"
            exit 1
          fi
          if [ "$target" == "main" ] && [[ "$source" != "Release"* ]]; then
            echo "You can't merge into main from a branch that is not a release branch"
            exit 1
          fi

  create_release:
    if: ${{ github.event_name == 'pull_request' && startsWith(github.event.pull_request.head.ref, 'Release') == true }}
    needs: can-merge-pr 
    runs-on: ubuntu-latest
    steps:
      - name: Delete Existing Release (if any)
        run: |
          if [[ ${{ startsWith(github.event.pull_request.head.ref, 'Release') }} == true ]]; then
            echo "Condition met. Proceeding."
          else
            echo "Condition not met. Skipping."
          fi
          release_id=$(curl -s \
            -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
            -H "Accept: application/vnd.github.v3+json" \
            https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.event.pull_request.head.ref }} \
            | jq -r '.id')
          
          if [ "$release_id" != "null" ]; then
            curl -X DELETE \
              -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
              -H "Accept: application/vnd.github.v3+json" \
              https://api.github.com/repos/${{ github.repository }}/releases/$release_id
          fi

      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.event.pull_request.head.ref }}
          release_name: ${{ github.event.pull_request.head.ref }}
          body: |
            ${{ github.event.pull_request.body}}
          draft: false
          prerelease: false

      - name: Upload Binary to Release
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./
          asset_name: test.sh
          asset_content_type: application/octet-stream

关键修改说明

  1. 添加权限:在permissions中增加pull-requests: read,确保GITHUB_TOKEN有权限调用PR相关的API接口。
  2. 安装jq工具:新增步骤安装jq,用于解析API返回的JSON数据。
  3. 实时获取分支信息:通过GitHub API拉取当前PR的最新数据,从中提取源分支(head.ref)和目标分支(base.ref),替代原有的缓存变量。

这样修改后,无论PR的目标分支何时修改,重新运行Workflow时都会获取最新的分支状态,确保判断逻辑准确。

内容的提问来源于stack exchange,提问作者Yume no hochi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:12:04