Skip to content

feat(ci): name excluded approvers in the release approval Slack message - #82

Merged
ioannisj merged 2 commits into
mainfrom
ci/release-approval-slack-exclusions
Oct 23, 2026
Merged

ioannisj merged 2 commits into
mainfrom
ci/release-approval-slack-exclusions

Conversation

@ioannisj

@ioannisj ioannisj commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Release workflows gate publishing behind the NPM Release environment. With the merge queue the push actor is github-merge-queue[bot], so GitHub's "Prevent self-review" never excludes the PR author or whoever queued it. The release-approval-guard action catches that after the fact and fails the job, but the Slack approval request gives approvers no hint that they're excluded. In posthog-js run 39750702665 I queued #5273, approved the release myself, the guard failed, and a teammate had to re-run and approve.

The guard's error text and README also said a re-run would still see the old approval and fail again. That run showed the opposite: the re-run asked for a fresh approval and passed.

Changes

Adds a mode: report to release-approval-guard that lists the PRs in the push and who can't approve them, without failing and without needing an approval to exist yet. Both modes now write outputs (blocked_logins, blocked_mrkdwn, violations_mrkdwn, prs_mrkdwn, prs) so callers can post them to Slack. Bots are dropped from the blocked list, per-commit PR lookups run in parallel, and the re-run guidance is fixed.

notify-approval-needed.yml runs the guard in report mode on push events, pinned to a full SHA like every other action in the file, and builds the Slack payload with jq so it can add a "Cannot approve this release" section and an "Includes" field with the PRs. The Includes field sets verbatim: true so a PR title can't trigger Slack's @channel parsing. The pin points at 71adbfe for now because mode: report doesn't exist on main yet, worth a follow-up to bump it to the merge SHA. Callers that grant the notify job contents: read and pull-requests: read get the new blocks. Everyone else gets the message unchanged.

posthog-js follow-up: bump both pins, add the permission, and reply in the Slack thread when the guard rejects an approval.

Testing

  • node --test .github/actions/release-approval-guard/guard.test.mjs: 26 pass.
  • actionlint is clean on notify-approval-needed.yml.
  • I ran the payload builder locally with and without blocked approvers and checked the output with jq.
  • Not exercised in a real run yet. The posthog-js PR will do that on its next release push.

DRI: @ioannisj
Autonomy: Human-driven (agent-assisted)

@ioannisj ioannisj self-assigned this Oct 22, 2026
@ioannisj
ioannisj marked this pull request as ready for review October 22, 2026 10:33
@ioannisj
ioannisj requested a review from a team as a code owner October 22, 2026 10:33
@ioannisj
ioannisj requested a review from a team October 22, 2026 10:33
@veria-ai

veria-ai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

@Piccirello Piccirello left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security review agent — findings inline.

description: "Ref of PostHog/.github to fetch the release approval guard from. Point at a branch while iterating; callers may pin a SHA."
required: false
type: string
default: "main"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low · supply chain · confidence 5/5

guard_ref defaults to main, so a caller's SHA pin no longer fixes the guard code that runs in its release workflow.

Callers pin notify-approval-needed.yml@<sha>. A caller that bumps that pin and does not pass guard_ref checks out the guard from the current main of PostHog/.github and runs it in the job that the default-branch push triggers. That step shares the runner with the later slackapi/slack-github-action step, which receives slack_bot_token. Code from main can change that action's files on disk before it runs. The input description also suggests pointing guard_ref at a branch, and feature branches here have no protection.

script-ref in changeset-hygiene.yml is a different case: it runs on pull_request, gets no release-path secrets, and says "Pin only for testing".

Impact — A change on main reaches every caller's release workflow on its next release push (about 20 SDK repos), instead of after each caller reviews a pin bump. A caller that sets guard_ref to a branch lets anyone with write access to this repo run code in its release job.

Fix — Pin the action in this workflow and remove the checkout step:

- name: List who cannot approve
  id: guard
  if: github.event_name == 'push'
  continue-on-error: true
  uses: PostHog/.github/.github/actions/release-approval-guard@<sha>
  with:
    mode: report

A guard change then needs a second PR to bump this pin. If you want to keep guard_ref, default it to '', skip the guard steps when it is empty, and reject a value that is not a 40-character SHA. github.workflow_sha does not help here, because in a called workflow it is the caller's SHA.

From a security review agent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 An AI agent wrote this on behalf of @ioannisj.

Fixed in ab96ac5. Dropped guard_ref and the checkout step, the guard now runs as PostHog/.github/.github/actions/release-approval-guard pinned to a full SHA like the rest of the file. So a change on main here only reaches a caller's release job after a pin bump in this workflow plus the caller's own bump, and there's no input left to point at a branch.

The pin is 71adbfe for now because mode: report doesn't exist on main yet. If this squash-merges I'll bump it to the merge SHA in a follow-up so the pinned commit is actually on main.

@ioannisj
ioannisj merged commit f043148 into main Oct 23, 2026
16 checks passed
@ioannisj
ioannisj deleted the ci/release-approval-slack-exclusions branch October 23, 2026 07:27
praxstack pushed a commit to praxstack/posthog-js that referenced this pull request Oct 23, 2026
…ostHog#5379)

* ci(release): name excluded approvers in the Slack approval request

* ci(release): pin the approval notify workflow and guard to the merged PostHog/.github#82

* ci(release): only call an approval rejected when the guard reported one
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants