From b387e57610cdb9cb1bb0605c673ec6ded67c2625 Mon Sep 17 00:00:00 2001 From: Mona Date: Mon, 31 Aug 2026 13:26:47 -0700 Subject: [PATCH 1/2] ci: stop double Slack announcement of schema-sync PRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit slack-pr-notify.yml assumed bot-opened PRs cannot trigger pull_request workflows (anti-recursion). In practice GitHub creates those runs parked at action_required, and they execute when a human hits 'Approve and run workflows' — so every automation PR was announced twice (observed on PR #37, 2026-08-31). Guard the notify job on PR author != github-actions[bot]; schema-sync's inline step remains the single announcement. Also (DS-1133, parity with cvr-analyst and c3d-cognitive3dpy): the inline message now names the actual unblock action (Checks -> Approve and run workflows), fires on refresh too (a force-push re-parks the checks), and a failure() step reports SLICER_READ_TOKEN-style sync failures that cortex's dispatch leg cannot see. --- .github/workflows/schema-sync.yml | 33 +++++++++++++++++++++++---- .github/workflows/slack-pr-notify.yml | 14 ++++++++---- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/.github/workflows/schema-sync.yml b/.github/workflows/schema-sync.yml index 5bf6069..7a011a8 100644 --- a/.github/workflows/schema-sync.yml +++ b/.github/workflows/schema-sync.yml @@ -82,6 +82,7 @@ jobs: git push -f origin schema-sync-auto if gh pr list --head schema-sync-auto --state open --json number -q '.[0].number' | grep -q .; then echo "::notice::Schema sync PR already open — branch refreshed." + echo "pr_refreshed=true" >> "$GITHUB_OUTPUT" else gh pr create --base main --head schema-sync-auto \ --title "chore: auto-sync schema from cvr-cortex registry" \ @@ -94,19 +95,41 @@ jobs: env: GH_TOKEN: ${{ github.token }} - # PRs opened above use the default GITHUB_TOKEN, which cannot trigger - # the slack-pr-notify.yml pull_request workflow (GitHub anti-recursion - # rule) — so announce the PR to Slack from here instead. + # Announce the PR from here: slack-pr-notify.yml skips bot-opened PRs + # (their pull_request runs park at action_required and would announce + # a second time on approval — observed on PR #37, 2026-08-31). A + # refresh (force-push to an open PR) re-parks the checks, so it + # notifies too (DS-1133). - name: Notify Slack of schema sync PR - if: steps.sync.outputs.pr_created == 'true' + if: steps.sync.outputs.pr_created == 'true' || steps.sync.outputs.pr_refreshed == 'true' env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} GH_TOKEN: ${{ github.token }} + REFRESHED: ${{ steps.sync.outputs.pr_refreshed }} run: | pr_url=$(gh pr list --head schema-sync-auto --state open \ --json url -q '.[0].url') + verb="opened" + if [ "$REFRESHED" = "true" ]; then verb="refreshed"; fi payload=$(jq -n \ - --arg text "New PR in ${GITHUB_REPOSITORY}: <${pr_url}|chore: auto-sync schema from cvr-cortex registry> by schema-sync automation (schema-sync-auto → main)" \ + --arg text ":arrows_counterclockwise: Schema sync PR ${verb} in ${GITHUB_REPOSITORY}: <${pr_url}|chore: auto-sync schema from cvr-cortex registry>. Its checks are parked at *action_required* — open the PR, hit *Approve and run workflows* under Checks, then merge. <@U0820C4GQ9E> <@U0574KJ4USH>" \ + '{text: $text}') + curl -sf -X POST -H 'Content-type: application/json' \ + --data "$payload" "$SLACK_WEBHOOK_URL" + + # Cortex's dispatch leg only sees "queued" (204) — a failure here, + # e.g. an expired SLICER_READ_TOKEN, is invisible from cortex. + - name: Notify Slack of sync failure + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + run: | + if [ -z "$SLACK_WEBHOOK_URL" ]; then + echo "::warning::SLACK_WEBHOOK_URL not set — skipping Slack notification." + exit 0 + fi + payload=$(jq -n \ + --arg text ":x: Schema sync failed in ${GITHUB_REPOSITORY} — could not regenerate from the cortex registry. Usual cause: SLICER_READ_TOKEN expired. ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID} <@U0820C4GQ9E> <@U0574KJ4USH>" \ '{text: $text}') curl -sf -X POST -H 'Content-type: application/json' \ --data "$payload" "$SLACK_WEBHOOK_URL" diff --git a/.github/workflows/slack-pr-notify.yml b/.github/workflows/slack-pr-notify.yml index 8c27196..4540f88 100644 --- a/.github/workflows/slack-pr-notify.yml +++ b/.github/workflows/slack-pr-notify.yml @@ -3,9 +3,13 @@ name: Slack PR notify # Posts to Slack when a PR opens against main. Complements the org-wide # GitHub Slack app subscription with an explicit, repo-specific message. # -# Covers human PRs only: PRs opened by schema-sync.yml with the default -# GITHUB_TOKEN cannot trigger pull_request workflows (GitHub anti-recursion -# rule), so schema-sync.yml posts its own notification after `gh pr create`. +# Covers human PRs only. PRs opened by schema-sync.yml (github-actions[bot]) +# are excluded explicitly: GitHub does NOT suppress pull_request runs for +# bot-opened PRs — it creates them parked at action_required, and they +# execute the moment a human hits "Approve and run workflows". Without the +# author guard that meant a second Slack message for the same PR (observed +# on PR #37, 2026-08-31); schema-sync.yml already announces its own PRs +# after `gh pr create`. # Dependabot PRs are skipped — dependabot-triggered runs read from the # Dependabot secret store where SLACK_WEBHOOK_URL is not defined, and the # GitHub Slack app already announces them. @@ -21,7 +25,7 @@ on: jobs: notify: - if: github.actor != 'dependabot[bot]' && !github.event.pull_request.draft + if: github.actor != 'dependabot[bot]' && github.event.pull_request.user.login != 'github-actions[bot]' && !github.event.pull_request.draft runs-on: ubuntu-latest steps: - name: Post to Slack @@ -35,7 +39,7 @@ jobs: PR_BASE: ${{ github.event.pull_request.base.ref }} run: | payload=$(jq -n \ - --arg text "New PR in ${GITHUB_REPOSITORY}: <${PR_URL}|#${PR_NUMBER} ${PR_TITLE}> by ${PR_AUTHOR} (${PR_HEAD} → ${PR_BASE})" \ + --arg text "New PR in ${GITHUB_REPOSITORY}: <${PR_URL}|#${PR_NUMBER} ${PR_TITLE}> by ${PR_AUTHOR} (${PR_HEAD} → ${PR_BASE}) <@U0820C4GQ9E> <@U0574KJ4USH>" \ '{text: $text}') curl -sf -X POST -H 'Content-type: application/json' \ --data "$payload" "$SLACK_WEBHOOK_URL" From dfd7230590842ad03fdb92eb716690e2f3055190 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 31 Aug 2026 20:28:16 +0000 Subject: [PATCH 2/2] chore: auto-sync schema from slicer_fields.yaml [skip ci] --- src/cognitive3dpy/_schema_generated.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cognitive3dpy/_schema_generated.py b/src/cognitive3dpy/_schema_generated.py index bedeb58..f2c2459 100644 --- a/src/cognitive3dpy/_schema_generated.py +++ b/src/cognitive3dpy/_schema_generated.py @@ -3,7 +3,7 @@ DO NOT EDIT MANUALLY. Regenerate with: uv run python scripts/sync_schema.py -Source: slicer_fields.yaml (sha256:ff76761d1595) +Source: slicer_fields.yaml (sha256:4901ca640e47) """ from __future__ import annotations