name: PR Slash Commands — Merge-Gate Status description: >- Sets the initial pending commit status on the PR head SHA at open time and forces it back to pending on push (new SHA, approval invalidated). Never sets success — only the main slash-commands action's auth-gated /lgtm handler may do that, so a manually-added approved label cannot bypass the merge gate. Sets failure if the hold label is present. inputs: github-token: description: >- Token for the commit-status API call. The caller workflow must grant this token `statuses: write`. required: false default: ${{ github.token }} hold-label: description: Label that blocks merging (set by /hold) required: false default: do-not-merge/hold status-context: description: >- The commit-status context name. This is what appears in the PR merge box and what you mark as a required status check in branch protection. required: false default: slash-commands/approval invalidate-on-push: description: >- When 'true', a push (synchronize event) forces the status to pending regardless of labels. Must match the main slash-commands action's invalidate-on-push setting. required: false default: 'true' outputs: state: description: The commit status state that was set (pending or failure) value: ${{ steps.set.outputs.state }} runs: using: composite steps: - name: Set commit status id: set uses: actions/github-script@v8 env: HOLD_LABEL: ${{ inputs.hold-label }} STATUS_CONTEXT: ${{ inputs.status-context }} INVALIDATE_ON_PUSH: ${{ inputs.invalidate-on-push }} with: github-token: ${{ inputs.github-token }} script: | const { owner, repo } = context.repo; const pr = context.payload.pull_request; if (!pr) { core.setFailed('slash-commands/status must run on a pull_request(_target) event'); return; } const sha = pr.head.sha; const holdLabel = process.env.HOLD_LABEL; const statusContext = process.env.STATUS_CONTEXT; const invalidateOnPush = process.env.INVALIDATE_ON_PUSH === 'true'; // Never set success here. The only success writer is the main // action's /lgtm handler, which is auth-gated. Reading the approved // label would let anyone with triage+ perms bypass auth by labeling // manually. This sub-action's job is: pending on open, pending on // push (new SHA needs fresh approval), failure on hold. let state, description; if (invalidateOnPush && context.payload.action === 'synchronize') { state = 'pending'; description = `New commits pushed — awaiting re-approval via /lgtm`; } else if (pr.labels.some(l => l.name === holdLabel)) { state = 'failure'; description = `Blocked by ${holdLabel} — comment /unhold to clear`; } else { state = 'pending'; description = `Awaiting /lgtm from a maintainer or CODEOWNER`; } await github.rest.repos.createCommitStatus({ owner, repo, sha, state, description, context: statusContext, }); core.setOutput('state', state); core.info(`Set status ${state} on ${sha.slice(0,7)}: ${description}`);