# PR 合并后自动关闭关联的 Issue # 当 PR 从 ai_fix/N_xxx 分支合并到 main 时,关闭 #N 对应的 Issue(若 PR 描述中未含 Closes #N 则通过分支名解析) name: Close issue on PR merge on: pull_request: types: [closed] branches: [main] jobs: close-issue: if: github.event.pull_request.merged == true runs-on: ubuntu-latest permissions: issues: write pull-requests: read steps: - name: Get PR info id: pr run: | # 从 PR body 查找 Closes #N / Fixes #N(若已有则 GitHub 已自动关 issue,本 step 仅做解析) BODY="${{ github.event.pull_request.body }}" HEAD_REF="${{ github.event.pull_request.head.ref }}" # 优先从 PR 描述解析 ISSUE_NUM=$(echo "$BODY" | grep -oE '(Closes|Fixes|Resolves) #([0-9]+)' | head -1 | grep -oE '[0-9]+') if [ -z "$ISSUE_NUM" ]; then # 从分支名解析 ai_fix/N_xxx ISSUE_NUM=$(echo "$HEAD_REF" | sed -n 's|^ai_fix/\([0-9]*\)_.*|\1|p') fi if [ -z "$ISSUE_NUM" ]; then echo "ISSUE_NUMBER=" >> $GITHUB_OUTPUT echo "skip=true" >> $GITHUB_OUTPUT echo "未从 PR 描述或分支名解析到 Issue 编号,跳过关闭" exit 0 fi echo "ISSUE_NUMBER=$ISSUE_NUM" >> $GITHUB_OUTPUT echo "skip=false" >> $GITHUB_OUTPUT echo "解析到 Issue #$ISSUE_NUM" - name: Close issue if: steps.pr.outputs.skip != 'true' uses: actions/github-script@v7 with: script: | const issueNumber = parseInt('${{ steps.pr.outputs.ISSUE_NUMBER }}', 10); if (!issueNumber || isNaN(issueNumber)) { console.log('No valid issue number, skip'); return; } const { data: issue } = await github.rest.issues.get({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber }); if (issue.state === 'open') { await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, state: 'closed' }); console.log(`Issue #${issueNumber} closed.`); } else { console.log(`Issue #${issueNumber} already closed.`); }