Skip to content

Commit e1ea1c5

Browse files
claude[bot]claude
authored andcommitted
chore(repo): improve publish workflow slack notifications for reviewers and threaded status updates (#36502)
&lt;!-- ccr-slack-attribution --&gt; _Requested by **Jason Jean, Craigory Coppola, Jack Hsu** · [Slack thread](https://nrwl.slack.com/archives/C024JCL7TST/p1785288124781459?thread_ts=1785288124.781459&cid=C024JCL7TST)_ &lt;!-- Please make sure you have read the submission guidelines before posting an PR --&gt; &lt;!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --&gt; ## Current Behavior `report-pending-publish` always mentions Jason (`U9NPA6C90`) in the "manual review is required" Slack message, even when Jason is the one who triggered the release himself. It also uses `ravsamhq/notify-slack-action` (an incoming webhook), which cannot return a message timestamp, so there is no way for the workflow to later reply in that same Slack thread once the release is approved and published. ## Expected Behavior **1. Reviewer mentions (bystander effect / self-ping avoidance)** A new `reviewers` step compares `github.triggering_actor` against Jason's GitHub login and mentions Craigory (`U020RK8EMRR`) + Jack (`UD688H84E`) instead of Jason when Jason is the one who kicked off the run — pinging the trigger is pointless noise, and he already knows he's publishing. In every other case, the mention stays exactly as before (Jason). We deliberately avoid a blanket group/`@here`-style tag, since spreading the ping across a group invites the bystander effect where everyone assumes someone else will do the review. Jason Jean's GitHub login is `FrozenPandaz` — confirmed by fetching his GitHub profile (`github.com/FrozenPandaz`), which displays "Jason Jean" as the account's real name, and cross-checked against his extensive merged-PR history on `nrwl/nx`. **2. Threaded status updates** Per Jason's request in the linked Slack thread ("is there a way we can get the workflow to also respond to this slack thread once it has been approved and also once the release has been successfully published?"), the workflow now: - Posts the initial pending-review message via `slackapi/slack-github-action` (`chat.postMessage`) instead of the incoming-webhook action, since only a bot-token-based post returns a `ts` that can be threaded against. The job now exposes `outputs.slack_thread_ts`. - Has `publish` depend on `report-pending-publish` (so it can read that `ts`) and, right after checkout, post a threaded "✅ Approved — publishing now." reply once the manual-review environment gate has let the job start. Note this means `publish` now starts slightly later, after the initial Slack post completes — an intentional, acceptable tradeoff. - Adds a new `report-published` job that runs after `publish` succeeds and posts a threaded "🎉 Version {version} was published to NPM successfully." reply, with a link back to the run. The message text for the initial post is now assembled in a plain shell step (`id: message`) from `needs.resolve-required-data.outputs.*` and the new `reviewers` output, rather than as nested GitHub Actions expressions inside the YAML `payload:` block, to keep it readable and avoid escaping pitfalls. **⚠️ Requires a new repo secret: `SLACK_BOT_TOKEN`** This change depends on a **new repository secret, `SLACK_BOT_TOKEN`**, being added — a bot token from a Slack app with the `chat:write` and `chat:write.public` scopes (the existing `ACTION_MONITORING_SLACK` incoming-webhook secret architecturally cannot support threaded replies or return a `ts`). **Until an admin adds this secret**, the `chat.postMessage` steps (initial notification, approval reply, and success reply) will fail; they are all `continue-on-error: true` (matching the existing job-level pattern already used for `report-pending-publish`), so they will silently no-op and **will not block or affect the actual npm publish** in any way. Once the secret is added, all three notifications — pending review, approved, and published — will start working automatically with no further code changes. ## Related Issue(s) N/A — requested directly in Slack by Jason Jean, Craigory Coppola, and Jack Hsu (thread linked above). Fixes # --- _Generated by [Claude Code](https://claude.ai/code/session_01FFLmji2EynJs1nSK1Q8i2W)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent aacc429 commit e1ea1c5

1 file changed

Lines changed: 179 additions & 17 deletions

File tree

.github/workflows/publish.yml

Lines changed: 179 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ jobs:
573573
- resolve-required-data
574574
- build-freebsd
575575
- build
576+
- report-pending-publish
576577
env:
577578
GH_TOKEN: ${{ github.token }}
578579
steps:
@@ -581,6 +582,46 @@ jobs:
581582
repository: ${{ needs.resolve-required-data.outputs.repo || github.repository }}
582583
ref: ${{ needs.resolve-required-data.outputs.ref || github.ref }}
583584

585+
# Built here (rather than inline in the payload below) to keep the Block Kit
586+
# construction consistent with the other two Slack-posting jobs.
587+
- name: Build Slack message payload
588+
id: approved-message
589+
if: ${{ needs.report-pending-publish.outputs.slack_thread_ts }}
590+
env:
591+
THREAD_TS: ${{ needs.report-pending-publish.outputs.slack_thread_ts }}
592+
run: |
593+
PAYLOAD=$(jq -nc --arg ts "$THREAD_TS" '{
594+
channel: "C024JCL7TST",
595+
text: "✅ Publish Approved",
596+
thread_ts: $ts,
597+
attachments: [
598+
{
599+
color: "good",
600+
blocks: [
601+
{
602+
type: "section",
603+
text: { type: "mrkdwn", text: "*Approved* — publishing now." }
604+
}
605+
]
606+
}
607+
]
608+
}')
609+
echo "payload=$PAYLOAD" >> "$GITHUB_OUTPUT"
610+
611+
# Best-effort threaded confirmation that the manual review gate has been passed and the
612+
# publish is proceeding. Requires the SLACK_BOT_TOKEN secret and a valid thread to reply to;
613+
# if either is missing this step no-ops without affecting the actual publish below.
614+
- name: Notify Slack thread that publish was approved
615+
id: notify-approved
616+
if: ${{ needs.report-pending-publish.outputs.slack_thread_ts }}
617+
continue-on-error: true
618+
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
619+
with:
620+
method: chat.postMessage
621+
token: ${{ secrets.SLACK_BOT_TOKEN }}
622+
errors: true
623+
payload: ${{ steps.approved-message.outputs.payload }}
624+
584625
- name: Set verbose logging from debug mode
585626
if: runner.debug == '1'
586627
run: echo "NX_VERBOSE_LOGGING=true" >> "$GITHUB_ENV"
@@ -664,27 +705,148 @@ jobs:
664705
runs-on: ubuntu-latest
665706
timeout-minutes: 10
666707
continue-on-error: true # Don't fail the workflow if notification fails
708+
outputs:
709+
slack_thread_ts: ${{ steps.notify.outputs.ts }}
667710
steps:
711+
# Decide who to mention: pinging the person who triggered the run themselves is
712+
# pointless noise (they already know they're publishing), and mentioning a whole
713+
# group invites the bystander effect where everyone assumes someone else will
714+
# review it. So we mention Jason by default, unless *he* is the triggering actor,
715+
# in which case we mention Craigory and Jack instead.
716+
#
717+
# Jason Jean's GitHub login is `FrozenPandaz` - confirmed via his GitHub profile
718+
# (github.com/FrozenPandaz, which displays "Jason Jean" as the account's real
719+
# name) and cross-checked against his extensive merged-PR history on nrwl/nx.
720+
- name: Determine which reviewers to mention
721+
id: reviewers
722+
env:
723+
TRIGGERING_ACTOR: ${{ github.triggering_actor }}
724+
run: |
725+
if [ "$TRIGGERING_ACTOR" = "FrozenPandaz" ]; then
726+
echo "mentions=<@U020RK8EMRR> <@UD688H84E>" >> "$GITHUB_OUTPUT" # Craigory Coppola + Jack Hsu
727+
else
728+
echo "mentions=<@U9NPA6C90>" >> "$GITHUB_OUTPUT" # Jason Jean
729+
fi
730+
731+
# Built here (rather than inline in the payload below) to avoid fragile nested
732+
# GitHub Actions expressions inside a YAML block, and so the conditional PR/non-PR
733+
# wording stays readable.
734+
- name: Build Slack message payload
735+
id: message
736+
env:
737+
VERSION: ${{ needs.resolve-required-data.outputs.version }}
738+
PR_NUMBER: ${{ needs.resolve-required-data.outputs.pr_number }}
739+
PR_AUTHOR: ${{ needs.resolve-required-data.outputs.pr_author }}
740+
MENTIONS: ${{ steps.reviewers.outputs.mentions }}
741+
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
742+
run: |
743+
if [ -n "$PR_NUMBER" ]; then
744+
TITLE_TEXT="📦 PR #${PR_NUMBER} Publish Pending Review"
745+
MAIN_TEXT="*Version ${VERSION}* from PR #${PR_NUMBER} by @${PR_AUTHOR} is being published to NPM - manual review is required ${MENTIONS}"
746+
else
747+
TITLE_TEXT="📦 Publish Pending Review"
748+
MAIN_TEXT="*Version ${VERSION}* is being published to NPM - manual review is required ${MENTIONS}"
749+
fi
750+
PAYLOAD=$(jq -nc \
751+
--arg title "$TITLE_TEXT" \
752+
--arg main "$MAIN_TEXT" \
753+
--arg run_url "$RUN_URL" \
754+
'{
755+
channel: "C024JCL7TST",
756+
text: $title,
757+
attachments: [
758+
{
759+
color: "good",
760+
blocks: [
761+
{
762+
type: "section",
763+
text: { type: "mrkdwn", text: $main }
764+
},
765+
{
766+
type: "context",
767+
elements: [
768+
{ type: "mrkdwn", text: ("<" + $run_url + "|View Workflow Run>") }
769+
]
770+
}
771+
]
772+
}
773+
]
774+
}')
775+
echo "payload=$PAYLOAD" >> "$GITHUB_OUTPUT"
776+
777+
# Uses the bot-token based slack-github-action (rather than the incoming-webhook
778+
# based ravsamhq/notify-slack-action used previously) because only a bot token can
779+
# return a message `ts`, which downstream jobs need in order to post threaded
780+
# replies once the publish is approved and once it completes. Requires the
781+
# SLACK_BOT_TOKEN repo secret (a Slack bot token with chat:write + chat:write.public
782+
# scopes); until that secret exists this step - and therefore the whole job, which
783+
# is continue-on-error - fails harmlessly without blocking the publish.
668784
- name: Send Slack notification
669-
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
785+
id: notify
786+
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
670787
with:
671-
status: ${{ job.status }}
672-
notification_title: >-
673-
${{ needs.resolve-required-data.outputs.pr_number &&
674-
format('📦 PR #{0} Publish Pending Review', needs.resolve-required-data.outputs.pr_number) ||
675-
'📦 Publish Pending Review' }}
676-
message_format: >-
677-
${{ needs.resolve-required-data.outputs.pr_number &&
678-
format('Version {0} from PR #{1} by @{2} is being published to NPM - manual review is required',
679-
needs.resolve-required-data.outputs.version,
680-
needs.resolve-required-data.outputs.pr_number,
681-
needs.resolve-required-data.outputs.pr_author) ||
682-
format('Version {0} is being published to NPM - manual review is required',
683-
needs.resolve-required-data.outputs.version) }}
684-
footer: '<{run_url}|View Workflow Run>'
685-
mention_users: 'U9NPA6C90' # Jason
788+
method: chat.postMessage
789+
token: ${{ secrets.SLACK_BOT_TOKEN }}
790+
errors: true
791+
payload: ${{ steps.message.outputs.payload }}
792+
793+
report-published:
794+
name: Report Successful Publish to Slack
795+
if: ${{ github.repository_owner == 'nrwl' }}
796+
needs:
797+
- resolve-required-data
798+
- publish
799+
- report-pending-publish
800+
runs-on: ubuntu-latest
801+
timeout-minutes: 10
802+
continue-on-error: true # Don't fail the workflow if notification fails
803+
steps:
804+
# Only fires once `publish` has actually succeeded - if `publish` fails, GitHub
805+
# skips this job by default since it's a listed `needs` dependency that didn't succeed.
806+
- name: Build Slack message payload
807+
id: message
686808
env:
687-
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
809+
VERSION: ${{ needs.resolve-required-data.outputs.version }}
810+
THREAD_TS: ${{ needs.report-pending-publish.outputs.slack_thread_ts }}
811+
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
812+
run: |
813+
MAIN_TEXT="*Version ${VERSION}* was published to NPM successfully."
814+
PAYLOAD=$(jq -nc \
815+
--arg main "$MAIN_TEXT" \
816+
--arg ts "$THREAD_TS" \
817+
--arg run_url "$RUN_URL" \
818+
'{
819+
channel: "C024JCL7TST",
820+
text: "🎉 Published Successfully",
821+
thread_ts: $ts,
822+
attachments: [
823+
{
824+
color: "good",
825+
blocks: [
826+
{
827+
type: "section",
828+
text: { type: "mrkdwn", text: $main }
829+
},
830+
{
831+
type: "context",
832+
elements: [
833+
{ type: "mrkdwn", text: ("<" + $run_url + "|View Workflow Run>") }
834+
]
835+
}
836+
]
837+
}
838+
]
839+
}')
840+
echo "payload=$PAYLOAD" >> "$GITHUB_OUTPUT"
841+
842+
- name: Send Slack notification
843+
if: ${{ needs.report-pending-publish.outputs.slack_thread_ts }}
844+
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
845+
with:
846+
method: chat.postMessage
847+
token: ${{ secrets.SLACK_BOT_TOKEN }}
848+
errors: true
849+
payload: ${{ steps.message.outputs.payload }}
688850

689851
pr_failure_comment:
690852
# Run this job if it is a PR release, running on the nrwl origin, and any of the required jobs failed

0 commit comments

Comments
 (0)