feat: add notify-on-release email pipeline to typescript-service-release - #76
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughClassifies semantic-version bumps (major/minor/patch) against the last stable release, exposes that type through release-info outputs, and adds a conditional ChangesRelease Notification with Type Classification
Sequence DiagramssequenceDiagram
participant ParseVersion as Parse Version
participant ClassifyBump as Classify Bump
participant Output as release-type output
ParseVersion->>ClassifyBump: previous-version, next-version
ClassifyBump->>ClassifyBump: strip pre-release suffixes
ClassifyBump->>ClassifyBump: compare major/minor/patch
ClassifyBump->>Output: kind (major | minor | patch)
sequenceDiagram
participant ReleaseInfo as release-info job
participant Notify as notify job
participant Tailscale as Tailscale Network
participant EmailMonkey as email-monkey service
ReleaseInfo->>Notify: outputs release_type, version, artifacts
Notify->>Notify: evaluate if notify-on-release and release_type in major|minor|patch
Notify->>Tailscale: join (TS_OAUTH_CLIENT_ID/TS_OAUTH_SECRET, tag:infra)
Notify->>EmailMonkey: POST JSON payload (jq -> curl)
EmailMonkey-->>Notify: HTTP response (status check)
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
📄 README may need an updateThis PR introduces changes that might not be reflected in Reason: README.md does not fully match the current public release workflow API because
|
📚 Skills documentation may need an updateThis PR introduces changes that might not be reflected in the skills documentation. Reason:
|
e585d60 to
bf5470a
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/blocks/determine-publish-version/action.yaml:
- Around line 109-135: The current Classify Bump logic strips prerelease
suffixes (prev_core/next_core) and recomputes kind, causing -rc → GA transitions
(e.g. 2.0.0-rc.3 → 2.0.0) to be misclassified as patch; change the step so it
either (A) compares NEXT against the last non-prerelease release (use a outputs
value that contains the last stable release instead of PREV with prerelease)
when computing kind, or (B) simply carry/propagate the original bump kind from
the prerelease flow instead of recomputing (read and forward the original kind
output from the earlier step into this job). Update references to PREV/NEXT,
prev_core/next_core and the produced kind variable so the classification
reflects the true bump rather than stripped cores.
In @.github/workflows/typescript-service-release.yaml:
- Around line 65-69: The notify job's gate currently only allows "major"
releases but the workflow input notify-on-release and docs promise notifications
for both major and minor bumps; update the notify job's conditional (the job
"notify" / its if-condition that currently checks for release == "major") to
also allow "minor" (e.g., change the equality check to a membership test for
["major","minor"] or alternatively change the logic to exclude only "patch"),
ensuring the notify-on-release input is still honored.
- Around line 221-227: The workflow step named "Join Tailnet" currently uses the
mutable reference tailscale/github-action@v3; update the uses field to pin the
action to a full commit SHA (e.g., tailscale/github-action@<full-commit-sha>) so
the executed code is immutable, keeping the existing inputs (oauth-client-id,
oauth-secret, tags, version) unchanged; locate the step by the "Join Tailnet"
name or the uses value tailscale/github-action@v3 and replace the tag with the
specific commit SHA.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f7473ac5-ae6c-4d59-a4a6-443ce347be76
📒 Files selected for processing (3)
.github/blocks/determine-publish-version/action.yaml.github/blocks/generate-release-info/action.yaml.github/workflows/typescript-service-release.yaml
📜 Review details
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-04-05T00:07:12.194Z
Learnt from: qwerzl
Repo: photon-hq/buildspace PR: 62
File: .github/workflows/update-docs.yaml:164-167
Timestamp: 2026-04-05T00:07:12.194Z
Learning: In this repo (photon-hq/buildspace), reusable workflow blocks referenced under photon-hq/buildspace (e.g., `photon-hq/buildspace/.github/blocks/<block>main`) are intentionally pinned to `main` because the blocks and workflows ship together and are kept in sync. During review, do not flag these references as version-pinning/supply-chain issues just because they use `main`; only require pinning to a release tag if there’s a separate reason (e.g., referencing an external repo or a non-controlled branch).
Applied to files:
.github/workflows/typescript-service-release.yaml
📚 Learning: 2026-04-27T01:30:22.893Z
Learnt from: yanxue06
Repo: photon-hq/buildspace PR: 73
File: .github/workflows/check-readme.yaml:18-18
Timestamp: 2026-04-27T01:30:22.893Z
Learning: When reviewing this repo’s GitHub Actions workflows, treat Blacksmith runner labels like `blacksmith-4vcpu-ubuntu-2404` and other `blacksmith-*vcpu-ubuntu-*` values as valid/intentional third-party runner labels (Blacksmith: blacksmith.sh). Do not flag them as unknown or non-standard runner labels—these are an intentional drop-in replacement for GitHub-hosted runners.
Applied to files:
.github/workflows/typescript-service-release.yaml
📚 Learning: 2026-04-27T01:30:22.893Z
Learnt from: yanxue06
Repo: photon-hq/buildspace PR: 73
File: .github/workflows/check-readme.yaml:18-18
Timestamp: 2026-04-27T01:30:22.893Z
Learning: In photon-hq/buildspace GitHub workflow YAML files, runner labels that match `blacksmith-*vcpu-ubuntu-*` (e.g., `blacksmith-4vcpu-ubuntu-2404`) are intentionally managed by the Blacksmith CI service (blacksmith.sh) and serve as drop-in replacements for GitHub-hosted ephemeral microVM runners. Do not flag these labels as unknown/non-standard, supply-chain concerns, or “unrecognized runner” issues; any linter/actionlint warnings about these specific labels are expected false positives.
Applied to files:
.github/workflows/typescript-service-release.yaml
🪛 zizmor (1.25.2)
.github/workflows/typescript-service-release.yaml
[error] 222-222: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (1)
.github/blocks/generate-release-info/action.yaml (1)
23-25: LGTM!
bf5470a to
448c0c1
Compare
448c0c1 to
064183e
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/typescript-service-release.yaml:
- Around line 205-213: The notify job's gate currently checks
contains(fromJSON('["major","minor","patch"]'),
needs.release-info.outputs.release_type) which allows patch releases,
contradicting the PR objective; update that expression in the workflow 'if' to
restrict allowed types (e.g., change the array to only ["major"] to follow the
learnings or to ["major","minor"] if you want to exclude patch but keep minor),
ensuring the rest of the 'if' (inputs.notify-on-release and other needs checks)
remains unchanged and referencing the existing contains(fromJSON(...),
needs.release-info.outputs.release_type) expression to locate and modify the
code.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d57b75a6-7d07-4e9f-a346-a128f05ddef5
📒 Files selected for processing (3)
.github/blocks/determine-publish-version/action.yaml.github/blocks/generate-release-info/action.yaml.github/workflows/typescript-service-release.yaml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: check-skills / check-skills
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2026-04-05T00:07:12.194Z
Learnt from: qwerzl
Repo: photon-hq/buildspace PR: 62
File: .github/workflows/update-docs.yaml:164-167
Timestamp: 2026-04-05T00:07:12.194Z
Learning: In this repo (photon-hq/buildspace), reusable workflow blocks referenced under photon-hq/buildspace (e.g., `photon-hq/buildspace/.github/blocks/<block>main`) are intentionally pinned to `main` because the blocks and workflows ship together and are kept in sync. During review, do not flag these references as version-pinning/supply-chain issues just because they use `main`; only require pinning to a release tag if there’s a separate reason (e.g., referencing an external repo or a non-controlled branch).
Applied to files:
.github/workflows/typescript-service-release.yaml
📚 Learning: 2026-04-27T01:30:22.893Z
Learnt from: yanxue06
Repo: photon-hq/buildspace PR: 73
File: .github/workflows/check-readme.yaml:18-18
Timestamp: 2026-04-27T01:30:22.893Z
Learning: When reviewing this repo’s GitHub Actions workflows, treat Blacksmith runner labels like `blacksmith-4vcpu-ubuntu-2404` and other `blacksmith-*vcpu-ubuntu-*` values as valid/intentional third-party runner labels (Blacksmith: blacksmith.sh). Do not flag them as unknown or non-standard runner labels—these are an intentional drop-in replacement for GitHub-hosted runners.
Applied to files:
.github/workflows/typescript-service-release.yaml
📚 Learning: 2026-04-27T01:30:22.893Z
Learnt from: yanxue06
Repo: photon-hq/buildspace PR: 73
File: .github/workflows/check-readme.yaml:18-18
Timestamp: 2026-04-27T01:30:22.893Z
Learning: In photon-hq/buildspace GitHub workflow YAML files, runner labels that match `blacksmith-*vcpu-ubuntu-*` (e.g., `blacksmith-4vcpu-ubuntu-2404`) are intentionally managed by the Blacksmith CI service (blacksmith.sh) and serve as drop-in replacements for GitHub-hosted ephemeral microVM runners. Do not flag these labels as unknown/non-standard, supply-chain concerns, or “unrecognized runner” issues; any linter/actionlint warnings about these specific labels are expected false positives.
Applied to files:
.github/workflows/typescript-service-release.yaml
📚 Learning: 2026-05-21T04:14:41.715Z
Learnt from: yanxue06
Repo: photon-hq/buildspace PR: 76
File: .github/workflows/typescript-service-release.yaml:0-0
Timestamp: 2026-05-21T04:14:41.715Z
Learning: In photon-hq/buildspace’s `.github/workflows/typescript-service-release.yaml`, the `notify` job must remain intentionally gated to major releases only (e.g., `needs.release-info.outputs.release_type == 'major'`). Do not treat the absence of a `minor` (or broader) trigger as a bug, and do not recommend widening the condition (such as changing it to `!= 'patch'` or otherwise including non-major release types), since this is a deliberate noise-reduction decision to send announcement emails only for breaking-change (major) releases.
Applied to files:
.github/workflows/typescript-service-release.yaml
📚 Learning: 2026-05-21T04:14:41.715Z
Learnt from: yanxue06
Repo: photon-hq/buildspace PR: 76
File: .github/workflows/typescript-service-release.yaml:0-0
Timestamp: 2026-05-21T04:14:41.715Z
Learning: In `.github/workflows/typescript-service-release.yaml`, the `notify` job is intentionally gated so the email-monkey notification runs only when `needs.release-info.outputs.release_type == 'major'`. Minor and patch releases should not trigger this notification as a deliberate noise-reduction design. During code review, do not flag this as a missing `minor` handling case and do not suggest changing the condition (e.g., to `!= 'patch'`).
Applied to files:
.github/workflows/typescript-service-release.yaml
🪛 zizmor (1.25.2)
.github/workflows/typescript-service-release.yaml
[error] 224-224: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (5)
.github/workflows/typescript-service-release.yaml (3)
223-229: Pintailscale/github-actionto a full commit SHA.This was flagged in a previous review and remains unaddressed. The response about "major-only" was for a different concern. Using
@v3is a mutable tag that could be retargeted upstream.
65-69: LGTM!Also applies to: 83-88, 118-118
231-274: LGTM!.github/blocks/determine-publish-version/action.yaml (1)
20-22: LGTM!Also applies to: 27-77, 126-158
.github/blocks/generate-release-info/action.yaml (1)
23-25: LGTM!
064183e to
bbbab4b
Compare
Brings the email-monkey notify job into the public buildspace so PUBLIC
caller repos (e.g. photon-hq/spectrum-ts) can get release-notification
emails through plain `uses:` without needing the public->internal
App-token + REST-dispatch workaround.
Three coupled additions, atomic because notify needs release_type:
1. .github/blocks/determine-publish-version/action.yaml
- new `release-type` output classifying the bump (major|minor|patch).
- Get-last-release step now fetches a page of recent releases and
exposes BOTH `version` (latest of any kind — used for the AI commit
range) and `stable_version` (latest non-prerelease — used for
classification). Classifying against the last STABLE means a GA
finalization of an -rc (e.g. 2.0.0-rc.3 -> 2.0.0) correctly emits
`major` instead of silently downgrading to `patch`.
- Classify Bump strips any -rc.N suffix on NEXT before comparing
against PREV (which is already stable).
2. .github/blocks/generate-release-info/action.yaml
- forwards `release_type` from the underlying version block.
3. .github/workflows/typescript-service-release.yaml
- new `notify-on-release` input (default true). Description spells
out the actual gate: fires on MAJOR releases of allow-listed callers
only; minor/patch and non-allow-listed callers skip cleanly.
- new optional `TS_OAUTH_CLIENT_ID` / `TS_OAUTH_SECRET` secrets
(Tailscale OAuth for ephemeral tailnet join as tag:ci).
- `release-info` job exposes `release_type` for downstream jobs.
- new `notify` job: gates on caller == photon-hq/spectrum-ts AND
release_type == 'major'. Body joins tailnet as tag:ci, POSTs
{repo, version, releaseNotes, releaseType, serviceName} to
http://email-monkey/notify-release. Onboard additional callers by
extending the github.repository check.
Patch releases short-circuit; non-allowlisted callers short-circuit;
missing TS_OAUTH_* secrets fail loudly on the tailnet join step
(intentional, since you can't reach email-monkey without them).
Co-authored-by: Cursor <cursoragent@cursor.com>
bbbab4b to
87e77bf
Compare
Summary
Brings the email-monkey notify job into the public buildspace so PUBLIC caller repos (e.g.
photon-hq/spectrum-ts) can get release-notification emails through plainuses:without needing the public→internal App-token + REST-dispatch workaround.Background: GitHub blocks public → internal reusable-workflow
uses:at the platform level (the internal repo's "Accessible from repositories in the organization" setting only opens it up to other private/internal repos). The notify pipeline was previously living insidebuildspace-privatefor that reason, which forced spectrum-ts to either (a) move to internal visibility or (b) mint an App token in spectrum-ts and REST-dispatch a workflow in buildspace-private.The notify pipeline itself isn't actually sensitive — it's a thin Tailscale-join + curl-JSON wrapper. The actual secrets (
TS_OAUTH_*) stay org-secret regardless of where the workflow YAML lives, and the email-monkey hostname is a tailnet MagicDNS name unreachable from outside the tailnet. So the right call is to host it publicly and avoid the App-token dance.Three coupled additions (atomic because notify needs
release_type).github/blocks/determine-publish-version/action.yaml— newrelease-typeoutput classifying the bump (major/minor/patch) against the last stable (non-prerelease) release. Strips any-rc.Nsuffix before comparing so GA finalization of a prerelease (e.g.2.0.0-rc.3 → 2.0.0) correctly classifies asmajorinstead ofpatch..github/blocks/generate-release-info/action.yaml— forwardsrelease_typefrom the underlying version block..github/workflows/typescript-service-release.yaml— newnotify-on-releaseinput (default true), new optionalTS_OAUTH_CLIENT_ID/TS_OAUTH_SECRETsecrets, newnotifyjob (join tailnet → POST JSON tohttp://email-monkey/notify-release).Notify gate
The
notifyjob fires only when ALL of these hold:github.repository == 'photon-hq/spectrum-ts'— only allow-listed caller today(check-labels.release || inputs.release)— must actually be cutting a releaserelease-info,github-releaseall succeedednpm-publishsucceeded or was intentionally skippedinputs.notify-on-release == true(defaults to true; opt-out per-release via the caller'swith:block)release_type ∈ {major, minor, patch}— defensive bound on the AI classifier outputNon-allow-listed callers and non-release runs get a clean
skippedjob, no error, no email.Test plan
check-labels,release-info,bump-version,github-release,npm-publish, newnotify)check-readme,check-skillsall SUCCESSparseNotifyBodyexactly ({repo, version, releaseNotes, releaseType, serviceName})http://email-monkey/notify-releasehits internal listener via tailnet K8s Service (:80 → :3001) — verified out-of-bandTS_OAUTH_CLIENT_ID/TS_OAUTH_SECRETorg secrets exist (gh secret list --org photon-hq | grep TS_OAUTH)releaselabel triggers the notify job; check spectrum-ts Actions log + email-monkey pod logsWhat's NOT in this PR
TS_OAUTH_CLIENT_ID/TS_OAUTH_SECRETsetup (Tailscale OAuth client + org-level GitHub secret, Ryan's task)tag:ci → tag:internal-svc:80(operator task)GITHUB_APP_*andRESEND_*env vars (separate, in email-monkey repo + K8s manifest)Summary by CodeRabbit