ci: report router releases to a Linear release pipeline#3066
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:
WalkthroughA new release workflow routes published component tags to a reusable Linear reporting workflow. The reusable workflow receives scoped paths and a secret key, checks out full history, and submits the release metadata to Linear. ChangesLinear release reporting workflows
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
226810d to
7b9e34c
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/linear-release.yaml (1)
88-96: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winMissing-secret case isn't actually skipped.
The PR description states unmatched tags or missing secrets are skipped, and the mapping-resolution step only guards on
matched == 'true'. If the correspondingLINEAR_RELEASE_KEY_<SLUG>secret isn't configured,secrets[format(...)]resolves to an empty string, and this step still runs with an emptyaccess_key, likely surfacing an opaque failure fromlinear/linear-release-actioninstead of a graceful skip.💡 Proposed fix: add an explicit secret-presence check
+ - name: Check Linear access key secret + id: secret_check + if: steps.component.outputs.matched == 'true' + env: + ACCESS_KEY: ${{ secrets[format('LINEAR_RELEASE_KEY_{0}', steps.component.outputs.slug)] }} + run: | + if [[ -z "$ACCESS_KEY" ]]; then + echo "No LINEAR_RELEASE_KEY_${{ steps.component.outputs.slug }} secret configured; skipping." + echo "has_key=false" >> "$GITHUB_OUTPUT" + else + echo "has_key=true" >> "$GITHUB_OUTPUT" + fi + - name: Checkout repository - if: steps.component.outputs.matched == 'true' + if: steps.component.outputs.matched == 'true' && steps.secret_check.outputs.has_key == 'true' uses: actions/checkout@v4 with: fetch-depth: 0 - name: Report release to Linear - if: steps.component.outputs.matched == 'true' + if: steps.component.outputs.matched == 'true' && steps.secret_check.outputs.has_key == 'true' uses: linear/linear-release-action@v0🤖 Prompt for 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. In @.github/workflows/linear-release.yaml around lines 88 - 96, The release reporting step in the workflow only checks steps.component.outputs.matched, so it still runs when the LINEAR_RELEASE_KEY_<SLUG> secret is missing and passes an empty access_key to linear/linear-release-action. Update the condition on the Report release to Linear step to also verify the resolved secret is present before running, using the same steps.component.outputs.slug and secrets[format(...)] lookup, so missing-secret cases are skipped cleanly instead of failing in the action.
🧹 Nitpick comments (1)
.github/workflows/linear-release.yaml (1)
92-92: 🔒 Security & Privacy | 🔵 Trivial | ⚖️ Poor tradeoffDynamic secret lookup necessarily exposes the whole
secretscontext.zizmor's overprovisioned-secrets warning is an inherent consequence of selecting the secret name dynamically (
secrets[format('LINEAR_RELEASE_KEY_{0}', slug)]) to support per-component keys. There's no low-cost fix without restructuring to a static per-component step/matrix, which would add significant duplication for marginal benefit here.🤖 Prompt for 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. In @.github/workflows/linear-release.yaml at line 92, The `access_key` assignment in `linear-release.yaml` uses a dynamic `secrets[format(...)]` lookup, which triggers the overprovisioned-secrets warning. To fix it, replace the dynamic secret access with statically referenced secrets by restructuring the release job around explicit per-component steps or a matrix in the `linear-release` workflow. If you keep the dynamic lookup, add an explicit suppression/justification in the workflow near this secret reference so the intended per-component key selection is documented.Source: Linters/SAST tools
🤖 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/linear-release.yaml:
- Around line 80-86: The Checkout repository step in the linear-release workflow
currently leaves Git credentials persisted for the rest of the job even though
nothing pushes afterward. Update the actions/checkout@v4 configuration in that
step to set persist-credentials to false, keeping the existing full-history
fetch-depth behavior intact.
---
Outside diff comments:
In @.github/workflows/linear-release.yaml:
- Around line 88-96: The release reporting step in the workflow only checks
steps.component.outputs.matched, so it still runs when the
LINEAR_RELEASE_KEY_<SLUG> secret is missing and passes an empty access_key to
linear/linear-release-action. Update the condition on the Report release to
Linear step to also verify the resolved secret is present before running, using
the same steps.component.outputs.slug and secrets[format(...)] lookup, so
missing-secret cases are skipped cleanly instead of failing in the action.
---
Nitpick comments:
In @.github/workflows/linear-release.yaml:
- Line 92: The `access_key` assignment in `linear-release.yaml` uses a dynamic
`secrets[format(...)]` lookup, which triggers the overprovisioned-secrets
warning. To fix it, replace the dynamic secret access with statically referenced
secrets by restructuring the release job around explicit per-component steps or
a matrix in the `linear-release` workflow. If you keep the dynamic lookup, add
an explicit suppression/justification in the workflow near this secret reference
so the intended per-component key selection is documented.
🪄 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: c644eee7-2e95-47d8-8981-ed0f1b91847e
📒 Files selected for processing (1)
.github/workflows/linear-release.yaml
| - name: Checkout repository | ||
| if: steps.component.outputs.matched == 'true' | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| # Full history is required so the action can scan commits since the | ||
| # pipeline's previous release for issue references. | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Set persist-credentials: false on checkout.
No push happens afterward, so persisting the checkout credentials for the remainder of the job is unnecessary exposure.
🔒️ Proposed fix
- name: Checkout repository
if: steps.component.outputs.matched == 'true'
uses: actions/checkout@v4
with:
+ persist-credentials: false
# Full history is required so the action can scan commits since the
# pipeline's previous release for issue references.
fetch-depth: 0📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Checkout repository | |
| if: steps.component.outputs.matched == 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| # Full history is required so the action can scan commits since the | |
| # pipeline's previous release for issue references. | |
| fetch-depth: 0 | |
| - name: Checkout repository | |
| if: steps.component.outputs.matched == 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| # Full history is required so the action can scan commits since the | |
| # pipeline's previous release for issue references. | |
| fetch-depth: 0 |
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 80-86: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for 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.
In @.github/workflows/linear-release.yaml around lines 80 - 86, The Checkout
repository step in the linear-release workflow currently leaves Git credentials
persisted for the rest of the job even though nothing pushes afterward. Update
the actions/checkout@v4 configuration in that step to set persist-credentials to
false, keeping the existing full-history fetch-depth behavior intact.
Source: Linters/SAST tools
7b9e34c to
5f6d9e1
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.github/workflows/linear-release.yaml (1)
71-71: 🔒 Security & Privacy | 🔵 Trivial | ⚖️ Poor tradeoffDynamic secret lookup exposes the entire secrets context to the runner.
Using
secrets[steps.component.outputs.secret_name]is valid GitHub Actions syntax for dynamic secret selection, but because the key isn't statically known, GitHub injects the fullsecretscontext into the runner for this job (flagged by zizmor asoverprovisioned-secrets). This means every repo secret, not just the intended per-component key, is available to the runner process during this job. Given the job also checks out untrusted-by-default release metadata and calls a third-party action, this widens the blast radius if either is compromised.If this is an accepted tradeoff for the incremental-rollout design, no action is needed; otherwise, consider a per-component job matrix with statically-referenced secrets (or per-component GitHub Environments) to scope secret access.
Also applies to: 92-92
🤖 Prompt for 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. In @.github/workflows/linear-release.yaml at line 71, The release workflow is using a dynamic secret lookup in the job, which causes the full secrets context to be injected. Update the `linear-release` workflow to avoid `secrets[steps.component.outputs.secret_name]` in the `ACCESS_KEY` assignment, and instead scope secret access per component using a job matrix with statically referenced secrets or separate GitHub Environments so only the intended key is available.Source: Linters/SAST tools
🤖 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/linear-release.yaml:
- Around line 68-79: The guard step in the workflow is interpolating
steps.component.outputs.secret_name and steps.component.outputs.component
directly into the shell body, which creates a template-injection risk. Update
the “Check pipeline is configured” step to pass those outputs through env
variables alongside ACCESS_KEY, and have the run script reference shell
variables only. Keep the logic in the guard step the same, but remove direct ${{
... }} expansion from the script body so the shell never sees raw template text.
---
Nitpick comments:
In @.github/workflows/linear-release.yaml:
- Line 71: The release workflow is using a dynamic secret lookup in the job,
which causes the full secrets context to be injected. Update the
`linear-release` workflow to avoid
`secrets[steps.component.outputs.secret_name]` in the `ACCESS_KEY` assignment,
and instead scope secret access per component using a job matrix with statically
referenced secrets or separate GitHub Environments so only the intended key is
available.
🪄 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: 6ff3b2f4-4560-438c-a8cf-528ee2b86146
📒 Files selected for processing (1)
.github/workflows/linear-release.yaml
5f6d9e1 to
eeb1124
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
.github/workflows/linear-release.yaml (1)
52-66: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winMalformed tag silently falls back to bogus component/version.
If
TAGdoesn't contain@, both${TAG%@*}and${TAG##*@}leavecomponent/versionequal to the full tag string rather than failing. The guard step's secret lookup coincidentally prevents a bad run in practice (no matching secret → skipped), but an explicit check would make the failure mode clearer and avoid depending on that side-effect.component="${TAG%@*}" version="${TAG##*@}" + if [ "$component" = "$TAG" ] || [ "$version" = "$TAG" ]; then + echo "Tag '$TAG' does not match <component>@<semver>; skipping." >&2 + exit 1 + fi🤖 Prompt for 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. In @.github/workflows/linear-release.yaml around lines 52 - 66, The tag parsing in the release workflow currently assumes TAG always contains “@”, so malformed tags can produce bogus component/version values instead of failing fast. Update the shell logic in the release step that derives component, version, and secret_name to explicitly validate TAG contains a separator before using ${TAG%@*} and ${TAG##*@}, and exit with a clear error if it does not. Keep the existing output keys and slug derivation in place, but make the validation part of the same release-tag parsing block so the failure is immediate and obvious.
🤖 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.
Nitpick comments:
In @.github/workflows/linear-release.yaml:
- Around line 52-66: The tag parsing in the release workflow currently assumes
TAG always contains “@”, so malformed tags can produce bogus component/version
values instead of failing fast. Update the shell logic in the release step that
derives component, version, and secret_name to explicitly validate TAG contains
a separator before using ${TAG%@*} and ${TAG##*@}, and exit with a clear error
if it does not. Keep the existing output keys and slug derivation in place, but
make the validation part of the same release-tag parsing block so the failure is
immediate and obvious.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1c1678f4-b30e-4da4-9139-a7d1472f1360
📒 Files selected for processing (1)
.github/workflows/linear-release.yaml
eeb1124 to
59a3c99
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/linear-release-report.yaml:
- Around line 32-35: The checkout in the release report workflow leaves
persisted Git credentials enabled by default, which is unnecessary for a
history-only job. Update the existing actions/checkout step in the
linear-release-report workflow to disable persisted credentials while keeping
the full-history fetch behavior, so later steps and nested actions do not
inherit the repo token.
🪄 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: 83ca8f46-6992-45ba-a0e3-2a477ed64c12
📒 Files selected for processing (2)
.github/workflows/linear-release-report.yaml.github/workflows/linear-release.yaml
59a3c99 to
a5b56d8
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
.github/workflows/linear-release-report.yaml (1)
37-42: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low valueConsider pinning
linear/linear-release-actionto a commit SHA.Pinning to
@v0trusts the tag not being force-moved; a SHA pin is safer against supply-chain tampering, per GitHub's own guidance that using the commit SHA is safest for stability and security.🤖 Prompt for 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. In @.github/workflows/linear-release-report.yaml around lines 37 - 42, The workflow uses linear/linear-release-action@v0, which should be pinned to a specific commit SHA for supply-chain safety. Update the action reference in the release job to use an immutable SHA instead of the moving `@v0` tag, keeping the existing with inputs unchanged.
🤖 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.
Nitpick comments:
In @.github/workflows/linear-release-report.yaml:
- Around line 37-42: The workflow uses linear/linear-release-action@v0, which
should be pinned to a specific commit SHA for supply-chain safety. Update the
action reference in the release job to use an immutable SHA instead of the
moving `@v0` tag, keeping the existing with inputs unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 666d00be-05aa-4a4a-beb1-eaf2c83b57da
📒 Files selected for processing (2)
.github/workflows/linear-release-report.yaml.github/workflows/linear-release.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/linear-release.yaml
9076b1a to
923ad05
Compare
923ad05 to
f04f223
Compare
Add Linear release reporting for the router component, following the continuous-deployment pattern in the Linear docs. lerna publishes one GitHub release per component (tagged '<component>@<semver>'); linear-release.yaml has a router job that runs on the 'released' event for the 'router@' tag prefix and hands off to the reusable linear-release-report workflow with the router path filter and its pipeline access key (LINEAR_ACCESS_KEY_ROUTER). More components can be added by copying the job. Generated with [Linear](https://linear.app/wundergraph/issue/COSMO-52/set-up-linear-releases-for-cosmo-monorepo-components#agent-session-f5d3e845) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
f04f223 to
283ed03
Compare
The report job only reads git history, so persist-credentials: false avoids leaving the repo token in git config for later steps. Generated with [Linear](https://linear.app/wundergraph/issue/COSMO-52/set-up-linear-releases-for-cosmo-monorepo-components#agent-session-f5d3e845) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
Sets up Linear release reporting for the
routercomponent to start, following the continuous-deployment pattern in the Linear docs.The setup is per-component by design: more components are added by copying the
routerjob and adjusting the tag prefix,include_paths, and access-key secret — each reporting to its own Linear pipeline.Required setup before this takes effect
router/.LINEAR_ACCESS_KEY_ROUTER.The
routerjob only runs for its own release tag, so additional components can be rolled out independently later.Summary by CodeRabbit