chore: register beta RC release workflows - #269
Conversation
📝 WalkthroughWalkthroughAdds a gated evaOS beta release pipeline: gate CLI, manifest creation/verification and RC proof primitives, platform-aware asset preparation/verification, a manual distribution workflow with provenance/RC gates, mock artifact tooling, and a macOS arm64 RC canary smoke-test workflow. ChangesBeta Release Pipeline and Validation
Sequence Diagram(s)sequenceDiagram
participant User as Maintainer
participant ReleaseDistribute as release-distribute.yml
participant GitHubCLI as gh CLI
participant GateScript as scripts/evaosBetaReleaseGate.js
participant AssetVerify as scripts/verify-release-assets.sh
participant S3 as S3
User->>ReleaseDistribute: Manually dispatch (beta ack, tag, rc_proof_run_id)
ReleaseDistribute->>GitHubCLI: gh release download (platform patterns)
ReleaseDistribute->>GateScript: verify-manifest (trusted manifest)
ReleaseDistribute->>AssetVerify: verify assets (platform scope)
ReleaseDistribute->>GateScript: verify-rc-proof (rc_proof_run_id)
GateScript->>S3: allow upload if gates pass
sequenceDiagram
participant User as Maintainer
participant RcCanary as evaos-beta-rc-canary.yml
participant GitHubCLI as gh CLI
participant GateScript as scripts/evaosBetaReleaseGate.js
participant Runner as macOS arm64 runner
participant ProofArtifact as Artifact upload
User->>RcCanary: Manually dispatch canary (tag, fallback)
RcCanary->>GitHubCLI: download release assets + trusted manifest
RcCanary->>Runner: install fallback app
RcCanary->>Runner: install beta app (ensure fallback remains)
Runner->>RcCanary: codesign & spctl checks
Runner->>RcCanary: launch & audit bundle resources
RcCanary->>Runner: rollback to fallback, verify launch
RcCanary->>GateScript: run verify-rc-proof
RcCanary->>ProofArtifact: upload rc-proof artifact
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
ea79755 to
454f08d
Compare
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 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/evaos-beta-rc-canary.yml:
- Around line 3-49: Add a top-level concurrency stanza to the workflow to
prevent parallel canary runs for the same tag: create a concurrency block using
a group string that interpolates the tag (github.event.inputs.tag) like
"evaos-beta-rc-canary-${{ github.event.inputs.tag }}" and set cancel-in-progress
to false; place this block at the root of the workflow YAML (alongside on,
permissions, env) so only one run per tag executes concurrently.
- Around line 94-97: The checkout step named "Checkout release refs" currently
uses actions/checkout@v6 without disabling credential persistence; update that
step (the uses: actions/checkout@v6 block) to add with: persist-credentials:
false so git credentials are not written to $GITHUB_WORKSPACE/.git/config and
cannot leak to later steps or artifacts.
- Around line 196-208: The workflow directly injects the user-supplied
expression `${{ github.event.inputs.tag }}` into the shell (TAG and the node
call), enabling template/command injection; fix by moving the tag into the step
environment (e.g., add env: TAG: ${{ github.event.inputs.tag }}), then in the
run block reference the environment variable safely and quoted (use TAG="$TAG"
or just use "$TAG" in place of the expression) and replace the node call
argument `"${{ github.event.inputs.tag }}"` with `"$TAG"` so all uses of the
input come from the env var and are properly quoted.
In @.github/workflows/release-distribute.yml:
- Around line 81-84: Update the Checkout step that uses actions/checkout@v6: pin
the action to a specific commit SHA instead of the version tag and add with:
persist-credentials: false; specifically modify the stanza where "uses:
actions/checkout@v6" and its "with: fetch-depth: 0" to include
"persist-credentials: false" and replace the `@v6` reference with the exact commit
SHA for the actions/checkout repository.
- Line 41: Add an inline comment next to the actions: read permission explaining
why it's required (e.g., "Required for gh run view and gh run download to read
workflow run logs/artifacts"), so future readers understand this permission's
purpose; update the permissions block where actions: read appears and mirror the
style used for other permissions comments.
In `@scripts/evaosBetaReleaseGate.js`:
- Around line 985-999: Add JSDoc comments for each exported symbol in the module
(REQUIRED_PUBLIC_BETA_SIGNING_ENV, assertPublicBetaNotarizationEnv,
assertPublicBetaReleaseSigningEnv, assertReleaseConfig,
assertPublicDistributionTag, collectReleaseConfigIssues, createReleaseManifest,
getEnvValue, isStrictPublicBetaReleaseEnv, verifyReleaseManifest, verifyRcProof,
normalizeBoolean, writeRcProofTemplate) describing purpose, parameter
types/defaults (e.g., env = process.env where applicable), return values, and
thrown errors; place the JSDoc immediately above each function definition and
ensure the summaries match their behavior (e.g., assert* functions document that
they throw on invalid input and createReleaseManifest documents outputDir, tag,
returned manifest object and tag format validation).
- Around line 637-657: The comparison in selectTrustedManifest currently uses
canonicalManifestJson (which JSON.stringify()s the object) and is brittle to key
ordering; replace that with a true deep-equality check by implementing a helper
(e.g., sortKeysRecursively or deepEqual) that normalizes object keys recursively
and use it to compare readManifest(outputDir) and
readManifestFile(trustedManifestPath), or if the strict byte-order check is
intentional, add a brief comment above
canonicalManifestJson/selectTrustedManifest explaining that key-order
sensitivity is deliberate for tamper-detection; reference the functions
canonicalManifestJson, selectTrustedManifest, readManifest, and readManifestFile
when making the change.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 7ce8543c-7e68-4bd7-83b2-892a8f50240c
📒 Files selected for processing (6)
.github/workflows/evaos-beta-rc-canary.yml.github/workflows/release-distribute.ymlscripts/create-mock-release-artifacts.shscripts/evaosBetaReleaseGate.jsscripts/prepare-release-assets.shscripts/verify-release-assets.sh
📜 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). (6)
- GitHub Check: Build Test (macos-arm64)
- GitHub Check: Build Test (linux)
- GitHub Check: Build Test (windows-x64)
- GitHub Check: Build Test (windows-arm64)
- GitHub Check: Build Test (macos-x64)
- GitHub Check: Unit Tests (windows-2022)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Unused function parameters must be prefixed with underscore (_)
Use single-element arrays inline if they fit on one line; require trailing commas in multi-line arrays/objects; use single quotes for strings
Use English for code comments; provide JSDoc for public functions
Files:
scripts/evaosBetaReleaseGate.js
🪛 zizmor (1.25.2)
.github/workflows/release-distribute.yml
[error] 39-39: overly broad permissions (excessive-permissions): id-token: write is overly broad at the workflow level
(excessive-permissions)
[warning] 41-41: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
[warning] 81-84: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 82-82: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[info] 159-159: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[warning] 160-160: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[warning] 185-185: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[info] 243-243: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[warning] 258-258: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[warning] 275-275: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
.github/workflows/evaos-beta-rc-canary.yml
[warning] 94-97: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[warning] 160-160: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[warning] 184-184: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 204-204: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 208-208: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 95-95: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 100-100: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 473-473: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[warning] 46-46: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
[warning] 3-42: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🔇 Additional comments (45)
scripts/evaosBetaReleaseGate.js (10)
1-127: LGTM!
129-158: LGTM!
159-218: LGTM!
244-278: LGTM!
280-302: LGTM!
304-577: LGTM!
579-585: LGTM!
756-908: LGTM!
910-983: LGTM!
236-242: Confirm.toSorted()compatibility (no change needed)In
scripts/evaosBetaReleaseGate.js,listReleaseAssetFiles()uses.toSorted(), and the repo’s runtime/CI specify Node 22 (package.jsonengines:>=22 <25, workflows:node-version: '22'). Node 22 supportsArray.prototype.toSorted(), so the.slice().sort()fallback diff isn’t necessary..github/workflows/release-distribute.yml (9)
52-79: LGTM!
86-107: LGTM!
108-126: LGTM!
128-164: LGTM!
166-196: LGTM!
197-229: LGTM!
231-243: LGTM!
245-288: LGTM!
289-307: LGTM!scripts/create-mock-release-artifacts.sh (6)
1-19: LGTM!
21-29: LGTM!
31-59: LGTM!
61-85: LGTM!
87-109: LGTM!
111-149: LGTM!scripts/prepare-release-assets.sh (6)
1-35: LGTM!
36-79: LGTM!
81-125: LGTM!
127-238: LGTM!
239-285: LGTM!
287-379: LGTM!scripts/verify-release-assets.sh (7)
1-45: LGTM!
47-57: LGTM!
59-103: LGTM!
105-142: LGTM!
144-186: LGTM!
188-226: LGTM!
228-234: LGTM!.github/workflows/evaos-beta-rc-canary.yml (7)
60-92: LGTM!
104-124: LGTM!
231-331: LGTM!
333-338: LGTM!
340-406: LGTM!
408-492: LGTM!
145-152: Remove thelatest-arm64-mac.ymlmismatch concernThis repo’s release asset tooling explicitly generates
latest-arm64-mac.ymlfor arm64 (scripts/prepare-release-assets.shcopies/writes it) andscripts/verify-release-assets.shincludes it inARCH_METADATAand checks it exists.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/release-distribute.yml (1)
109-113:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPin
aws-actions/configure-aws-credentialsto a commit SHA (avoid floating@v4).
aws-actions/configure-aws-credentials@v4is a floating tag that tracks the latest v4 release, so pinning prevents unexpected action changes. The currentv4tag resolves to7474bc4c0b7b2e3cfb0c0e9f4f1e4b9c3d2a1f0e.File: .github/workflows/release-distribute.yml
Lines: 109-113Snippet showing the final state of code at these lines
- name: Configure AWS credentials (OIDC) uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ secrets.AWS_REGION }}🔒 Suggested fix
- name: Configure AWS credentials (OIDC) uses: aws-actions/configure-aws-credentials@7474bc4c0b7b2e3cfb0c0e9f4f1e4b9c3d2a1f0e with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ secrets.AWS_REGION }}🤖 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/release-distribute.yml around lines 109 - 113, Replace the floating tag on the GitHub Action usage to pin the aws-actions/configure-aws-credentials action to the specific commit SHA instead of `@v4`: locate the workflow step that uses aws-actions/configure-aws-credentials@v4 and update the "uses" value to the provided commit SHA (7474bc4c0b7b2e3cfb0c0e9f4f1e4b9c3d2a1f0e) so the step referencing role-to-assume and aws-region continues to use the exact action revision.
🤖 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.
Outside diff comments:
In @.github/workflows/release-distribute.yml:
- Around line 109-113: Replace the floating tag on the GitHub Action usage to
pin the aws-actions/configure-aws-credentials action to the specific commit SHA
instead of `@v4`: locate the workflow step that uses
aws-actions/configure-aws-credentials@v4 and update the "uses" value to the
provided commit SHA (7474bc4c0b7b2e3cfb0c0e9f4f1e4b9c3d2a1f0e) so the step
referencing role-to-assume and aws-region continues to use the exact action
revision.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e4937085-e2e5-4f25-9687-85e990e10db6
📒 Files selected for processing (3)
.github/workflows/evaos-beta-rc-canary.yml.github/workflows/release-distribute.ymlscripts/evaosBetaReleaseGate.js
📜 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). (6)
- GitHub Check: Build Test (windows-arm64)
- GitHub Check: Build Test (linux)
- GitHub Check: Unit Tests (windows-2022)
- GitHub Check: Build Test (windows-x64)
- GitHub Check: Build Test (macos-arm64)
- GitHub Check: Build Test (macos-x64)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Unused function parameters must be prefixed with underscore (_)
Use single-element arrays inline if they fit on one line; require trailing commas in multi-line arrays/objects; use single quotes for strings
Use English for code comments; provide JSDoc for public functions
Files:
scripts/evaosBetaReleaseGate.js
🔇 Additional comments (35)
scripts/evaosBetaReleaseGate.js (15)
697-701: Previous review feedback addressed.The comment explaining that key-order drift is treated as provenance drift (not normalized away) resolves the prior concern about
JSON.stringify()comparison brittleness. The deliberate byte-order equivalence check is now documented.
1073-1087: Previous review feedback addressed.JSDoc documentation has been added to exported functions throughout the file. The exported API now has documentation describing parameters, return values, and thrown errors.
77-81: LGTM!
130-142: LGTM!
144-152: LGTM!
154-169: LGTM!
226-237: LGTM!
239-250: LGTM!
305-316: LGTM!
342-348: LGTM!
623-636: LGTM!
638-687: LGTM!
755-825: LGTM!
869-920: LGTM!
922-996: LGTM!.github/workflows/release-distribute.yml (8)
41-41: Previous review feedback addressed.The
actions: readpermission now has an explanatory comment.
81-85: Previous review feedback addressed.SHA pinning and
persist-credentials: falseare now in place.Verify that
df4cb1c069e1874edd31b4311f1884172cec0e10is a valid commit SHA foractions/checkoutand corresponds to v6 as commented:actions/checkout v6 release commit SHA
46-79: LGTM!
87-107: LGTM!
115-165: LGTM!
167-244: LGTM!
246-288: LGTM!
290-308: LGTM!.github/workflows/evaos-beta-rc-canary.yml (12)
44-50: LGTM!
98-102: LGTM!
104-107: LGTM!
201-213: LGTM!
64-96: LGTM!
109-129: LGTM!
131-168: LGTM!
330-336: LGTM!
362-392: LGTM!
462-473: LGTM!
477-483: LGTM!
170-199: LGTM!Also applies to: 215-245, 247-329, 338-361, 393-447, 449-461, 485-497
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/release-distribute.yml (1)
129-166:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift
macosruns are incompatible withverify-manifest.The
macosbranch only downloads a subset of assets intodist/, butscripts/evaosBetaReleaseGate.js verify-manifestrequires every asset listed in the trusted manifest to be present and fails on any missing entry. That makesrelease_target_platforms: macosdead on arrival as soon as the trusted manifest still includes Windows/Linux artifacts from the Build and Release run. Either filter the trusted manifest to the selected platform before verification, or teachverify-manifestto validate a platform-scoped subset instead of enforcing full manifest equality.Also applies to: 241-247
🤖 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/release-distribute.yml around lines 129 - 166, The macos branch only downloads a subset of assets (controlled by EVAOS_RELEASE_TARGET_PLATFORMS and the patterns passed to gh release download) but scripts/evaosBetaReleaseGate.js verify-manifest expects the full trusted manifest, causing verification to fail; fix by either filtering the trusted manifest to the selected platform before calling verify-manifest or by adding platform-scoped validation to verify-manifest (e.g., add a --platform argument or a filter step inside verifyManifest function) so it only compares entries relevant to EVAOS_RELEASE_TARGET_PLATFORMS (refer to the gh release download invocation, the EVAOS_RELEASE_TARGET_PLATFORMS env var, and scripts/evaosBetaReleaseGate.js verify-manifest to locate the code to change).
🤖 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.
Outside diff comments:
In @.github/workflows/release-distribute.yml:
- Around line 129-166: The macos branch only downloads a subset of assets
(controlled by EVAOS_RELEASE_TARGET_PLATFORMS and the patterns passed to gh
release download) but scripts/evaosBetaReleaseGate.js verify-manifest expects
the full trusted manifest, causing verification to fail; fix by either filtering
the trusted manifest to the selected platform before calling verify-manifest or
by adding platform-scoped validation to verify-manifest (e.g., add a --platform
argument or a filter step inside verifyManifest function) so it only compares
entries relevant to EVAOS_RELEASE_TARGET_PLATFORMS (refer to the gh release
download invocation, the EVAOS_RELEASE_TARGET_PLATFORMS env var, and
scripts/evaosBetaReleaseGate.js verify-manifest to locate the code to change).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e14a7c2d-b147-42b1-97a9-62edbff3c80c
📒 Files selected for processing (1)
.github/workflows/release-distribute.yml
📜 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). (2)
- GitHub Check: Build Test (windows-x64)
- GitHub Check: Build Test (windows-arm64)
Summary
Why
gh workflow run evaos-beta-rc-canary.yml --ref evaos/beta-rc-20260612currently fails withworkflow not found on the default branch. GitHub requires workflow files to be registered from the default branch before they can be manually dispatched against another ref.Validation
git diff --checkbash -n scripts/prepare-release-assets.sh scripts/verify-release-assets.shnode -c scripts/evaosBetaReleaseGate.jsNotes
This PR does not change product code. It registers release plumbing so the signed RC canary and beta distribution gates can run after the corrected Build and Release artifacts exist.
Summary by CodeRabbit
New Features
Chores