Skip to content

feat: add notify-deploy-authors action [CPONETOPS-1176] - #328

Draft
jariwiklund wants to merge 2 commits into
mainfrom
feat/CPONETOPS-1176/notify-deploy-authors
Draft

feat: add notify-deploy-authors action [CPONETOPS-1176]#328
jariwiklund wants to merge 2 commits into
mainfrom
feat/CPONETOPS-1176/notify-deploy-authors

Conversation

@jariwiklund

@jariwiklund jariwiklund commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

From this thread: make post-deploy monitoring as easy as possible, so a deploy is less likely to go out unmonitored as deploy frequency goes up.

DMs everyone whose commits are in a deploy, telling them their change is live and pointing them at the dashboard to watch:

🚀 Your changes are live - Monta PHP Monolith 2026-08-20-05-39 is now deployed to Production.
Please keep an eye out for errors over the next 30 minutes:
• Server Error Dashboard

A channel announcement is easy for everyone to scroll past; a DM lands as a personal to-do.

Where it sits in the pipeline

The job depends on deploy alone and is gated on needs.deploy.result == 'success'. There is nothing to monitor until the rollout has finished, and anything running earlier could only promise a change is on its way — which is not a useful cue to go and watch a dashboard.

Keeping it a separate job also means it can never hold up or affect the deploy itself, and it stays skipped entirely unless a dashboard is configured.

Dashboard per Jan's point in the thread: the Server Error Dashboard, not the older state-of-the-union one.

What's here

  • .github/actions/notify-deploy-authors/ — composite action (script + README + test-local.sh), following the argocd-wait-sync layout.
  • deploy-kotlin.yml and deploy-kotlin-v2.yml — a notify-deploy-authors job, opt-in via three new inputs. Both, for v1/v2 parity.
  • docs/workflow-guide.md and CLAUDE.md updated per the existing convention.

Enable it by setting one input:

notify-deploy-authors-dashboard-url: "https://montaapp.grafana.net/d/ja52q4d/server-error-dashboard?from=now-30m&to=now"
notify-deploy-authors-dashboard-label: "Server Error Dashboard"
notify-deploy-authors-identity-api-url: "https://project-tracker.vpn.internal.monta.app"

Reaching the author in Slack

The hard part, and GitHub data alone does not do it. Measured on monta-app/server:

Signal Reality
Public GitHub profile email Set on 4 of 17 sampled org members
…and wrong when it is set Casperhr is cr@monta.app on GitHub but cr@monta.com in Slack — lookup fails
Commit author email (last 300) 43% users.noreply.github.com, 24% @monta.com, 18% @monta.app, 13% personal

identity-api-url points at project-tracker's resolver, which holds each person's work email. On a real deploy range the difference is stark:

resolver ON   → Arash Vojdani (arvo@monta.com), Casper Rasmussen (cr@monta.com)   2 of 2 reachable
resolver OFF  → Casperhr (cr@monta.app) → fails; author "838" unreachable          0 of 2 reachable

Resolution order per person: resolver's Slack id → resolver's work email → Co-authored-by: trailer email → public GitHub profile email, each via users.lookupByEmail. Note the resolver's slackUserId is null for everyone today (that sync isn't populated), so the working path is login → work email; the action prefers the Slack id when it appears, so it improves for free later.

⚠️ The resolver is VPN-only, so the ubuntu-latest job can't reach it. The established pattern is tailscale/github-action + TAILSCALE_AUTHKEY (as service-feature/check-owner-teams.yml does), or a self-hosted runner. Without it the action still runs and names everyone it couldn't reach — I left the tailnet step out of this PR since it needs the secret plumbed into these reusable workflows, which is a decision worth making explicitly.

Safety, since this runs in the deploy path and messages people

  • Never fails a deploy. Every runtime problem is a ::warning:: and a zero exit. strict: true for testing.
  • Refuses to mass-DM. More than max-authors (default 15) in the range is treated as wrong refs, not a busy deploy — nothing is sent and the count is logged. A 3-day monolith range resolves to 34 authors, and I verified it refuses.
  • Bots and leavers skipped; one DM per person even when they appear as both author and co-author.

Testing

actionlint clean across all workflows; both edited workflows and the new action.yml parse. The script was exercised against real ref ranges with dry-run, covering: resolver on/off, nonexistent ref, identical refs, missing input, strict on/off, and the author cap.

Two bugs found and fixed while testing, both worth knowing about if you review the bash: tab as a field separator silently shifted fields (tab is IFS whitespace, so read collapses runs of empty fields — it would have posted to a nonexistent channel), and an ERR trap without set -e fires on ordinary grep-found-nothing cases and aborted the run.

Not exercised live: the actual DM send — that messages real people. Worth one test-local.sh --send against yourself before merge.

Follow-up

monta-app/server has its own deploy.yml rather than these reusable workflows, so the monolith needs its own step. Happy to open that once this lands — and it's a good place to revisit the commented-out ArgoCD wait, since that is what would give the monolith a real "rollout finished" signal to hang this off.

🤖 Generated with Claude Code

From https://monta-app01.slack.com/archives/C03CWQT78AD/p1787130836840529 - make
post-deploy monitoring as easy as possible, so a deploy is less likely to go out
unmonitored as deploy frequency goes up.

DMs everyone whose commits are in a deploy, telling them their change is live
and pointing them at the dashboard to watch. A channel announcement is easy for
everyone to scroll past; a DM lands as a personal to-do.

The job depends on `deploy` alone and is gated on it succeeding: there is
nothing to monitor until the rollout has finished, and the notification must
never hold up or affect the deploy itself. Anything running earlier could only
promise a change is on its way, which is not a useful cue to go and watch a
dashboard.

Reaching an author in Slack is the hard part and GitHub data alone does not do
it: public profile emails are set on a small minority of the org and can be the
wrong domain (cr@monta.app on GitHub vs cr@monta.com in Slack), while commit
emails are usually users.noreply.github.com or personal addresses. Setting
notify-deploy-authors-identity-api-url points the action at project-tracker's
resolver, which holds each person's work email. On one real deploy range that
was the difference between 2 of 2 authors reachable and 0 of 2.

Safety properties, since this runs in the deploy path and messages people:
never fails a deploy (every runtime problem is a warning and a zero exit,
unless strict is set); refuses to send anything when the ref range holds more
than max-authors people, since that means the refs are wrong rather than that
the deploy was busy; skips bots and leavers; and sends one DM per person even
when they appear both as a commit author and in a Co-authored-by trailer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jariwiklund
jariwiklund force-pushed the feat/CPONETOPS-1176/notify-deploy-authors branch from 950b8b0 to 663a9cc Compare August 20, 2026 07:25
Repo, service and dashboard are per-caller configuration, not something this
action has an opinion on - baking monta-app/server-specific values into a
checked-in example file misrepresented that. test-local.sh already loads a
local .env if one exists; the README now shows exporting the variables
directly (or dropping them in your own gitignored .env) instead of pointing
at a removed example.
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.

1 participant