[codex] add editor image self-heal workflow#288
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a scheduled GitHub Actions workflow and a Node.js reconciliation script that check Docker Hub for missing Unity prerequisite/editor images, optionally fetch Unity's latest editor info, and dispatch repository events to queue rebuilds. ChangesEditor Image Self-Healing Automation
Sequence DiagramsequenceDiagram
participant Runner as GitHub Actions Runner
participant Script as self-heal-editor-images.js
participant DockerHub as Docker Hub
participant UnitySite as Unity "What's New"
participant GitHubAPI as GitHub REST API
Runner->>Script: run script with UNITY_VERSIONS_JSON, repo context
Script->>UnitySite: fetch latest official editor info (optional)
Script->>DockerHub: check prerequisite image tags (base, hub)
DockerHub-->>Script: 200 / 404 responses
Script->>DockerHub: check editor image tags per platform/version
DockerHub-->>Script: 200 / 404 responses
Script->>GitHubAPI: dispatch repository events for missing images
GitHubAPI-->>Script: 2xx / error responses
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
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)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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/workflows/self-heal-editor-images.js:
- Around line 42-55: The splitRepoVersion function currently only checks that
major and minor exist after a simple split, allowing inputs like "3.2.1.4.5";
update splitRepoVersion to validate the normalized version against a strict
semver pattern (or use the semver library's valid/parse functions) before
splitting: call normalizeVersion(version) then verify it matches a full semver
regex (e.g. ^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-.]+)?(\\+[0-9A-Za-z-.]+)?$) or
semver.valid(normalized), and if invalid throw a clearer error message
referencing the original input; keep returning full/minor/major but derive minor
from the first two numeric components only (major.minor) using the validated
semver parts.
In @.github/workflows/self-heal-editor-images.yml:
- Around line 25-26: The workflow's permissions block currently grants overly
broad rights via "contents: write"; change the permissions setting under
permissions to the least-privilege scope needed (replace "contents: write" with
"contents: read") so the job that dispatches repository events and queries
Docker Hub only has read access; update any job or step that assumed write
access to use a scoped token if necessary and verify the dispatch step still
works after the change (look for the permissions key and the "contents: write"
entry to modify).
- Around line 34-37: Replace the loose actions/checkout@v6 reference with a
pinned commit SHA for the intended v6 tag (e.g., the full commit SHA for v6.0.3)
instead of a floating tag, and under the same checkout step's with: block add
persist-credentials: false while keeping fetch-depth: 0; specifically update the
uses string "actions/checkout@v6" to the chosen commit SHA and add the
"persist-credentials: false" key in the with: section to prevent credential
leakage.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: bd45ed23-7e81-4cae-b592-993789c38162
📒 Files selected for processing (2)
.github/workflows/self-heal-editor-images.js.github/workflows/self-heal-editor-images.yml
| const splitRepoVersion = (version) => { | ||
| const normalized = normalizeVersion(version); | ||
| const [major, minor] = normalized.split('.'); | ||
|
|
||
| if (!major || !minor) { | ||
| throw new Error(`Repo version "${version}" does not look like a semantic version`); | ||
| } | ||
|
|
||
| return { | ||
| full: normalized, | ||
| minor: `${major}.${minor}`, | ||
| major, | ||
| }; | ||
| }; |
There was a problem hiding this comment.
Strengthen version validation and clarify error message.
The function only checks that major and minor components exist after splitting on ., but does not validate full semantic versioning format. For example, "3" would fail correctly, but "3.2.1.4.5" would pass with major="3" and minor="2.1.4.5", which may not be the intended behavior. The error message claims to check for "semantic version" but the validation is much weaker.
🛡️ Proposed fix to add semver pattern validation
const splitRepoVersion = (version) => {
const normalized = normalizeVersion(version);
- const [major, minor] = normalized.split('.');
+ const match = /^(\d+)\.(\d+)(?:\.\d+)?$/.exec(normalized);
- if (!major || !minor) {
- throw new Error(`Repo version "${version}" does not look like a semantic version`);
+ if (!match) {
+ throw new Error(`Repo version "${version}" must be in MAJOR.MINOR or MAJOR.MINOR.PATCH format`);
}
+ const [, major, minor] = match;
+
return {
full: normalized,
minor: `${major}.${minor}`,
major,
};
};🤖 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/self-heal-editor-images.js around lines 42 - 55, The
splitRepoVersion function currently only checks that major and minor exist after
a simple split, allowing inputs like "3.2.1.4.5"; update splitRepoVersion to
validate the normalized version against a strict semver pattern (or use the
semver library's valid/parse functions) before splitting: call
normalizeVersion(version) then verify it matches a full semver regex (e.g.
^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-.]+)?(\\+[0-9A-Za-z-.]+)?$) or
semver.valid(normalized), and if invalid throw a clearer error message
referencing the original input; keep returning full/minor/major but derive minor
from the first two numeric components only (major.minor) using the validated
semver parts.
| permissions: | ||
| contents: write |
There was a problem hiding this comment.
Overly permissive workflow permissions.
The workflow grants contents: write but the script only dispatches repository events via the GitHub API and queries Docker Hub. Repository dispatch typically requires only contents: read (with an appropriately scoped token).
🔐 Recommended fix to apply least-privilege permissions
permissions:
- contents: write
+ contents: read📝 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.
| permissions: | |
| contents: write | |
| permissions: | |
| contents: read |
🤖 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/self-heal-editor-images.yml around lines 25 - 26, The
workflow's permissions block currently grants overly broad rights via "contents:
write"; change the permissions setting under permissions to the least-privilege
scope needed (replace "contents: write" with "contents: read") so the job that
dispatches repository events and queries Docker Hub only has read access; update
any job or step that assumed write access to use a scoped token if necessary and
verify the dispatch step still works after the change (look for the permissions
key and the "contents: write" entry to modify).
| - name: Checkout | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify the latest actions/checkout v6 release and its commit SHA
gh api repos/actions/checkout/releases --jq '.[] | select(.tag_name | startswith("v6")) | {tag_name, target_commitish} | `@json`' | head -5Repository: game-ci/docker
Length of output: 299
Pin actions/checkout to a commit SHA and disable credential persistence.
In .github/workflows/self-heal-editor-images.yml (lines 34-37), the checkout uses actions/checkout@v6 and should be pinned to a commit SHA. The proposed v6.2.0 reference isn’t present in the actions/checkout releases data returned here (only v6.0.3, v6.0.2, v6.0.1, v6.0.0, and v6-beta appear), so the pinned SHA needs to correspond to the actual intended v6 tag (e.g., v6.0.3). Also add persist-credentials: false under with: to avoid leaking credentials to subsequent steps.
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 34-37: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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/self-heal-editor-images.yml around lines 34 - 37, Replace
the loose actions/checkout@v6 reference with a pinned commit SHA for the
intended v6 tag (e.g., the full commit SHA for v6.0.3) instead of a floating
tag, and under the same checkout step's with: block add persist-credentials:
false while keeping fetch-depth: 0; specifically update the uses string
"actions/checkout@v6" to the chosen commit SHA and add the "persist-credentials:
false" key in the with: section to prevent credential leakage.
…load The chocolatey unity-hub package download URL returns HTTP 404, causing the Windows Base and Hub CI job to fail. Download the installer directly from Unity's official CDN and run it silently instead. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
9671082 to
bdafb21
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@images/windows/hub/Dockerfile`:
- Line 6: The RUN PowerShell command uses Start-Process to install
UnityHubSetup.exe but doesn't fail the Docker build on installer errors; update
the PowerShell snippet to capture the installer process (use Start-Process with
-PassThru or inspect $LASTEXITCODE/.ExitCode) and explicitly exit/throw when the
installer returns a non-zero code so the Docker build fails; target the
Start-Process invocation and the 'C:\UnityHubSetup.exe' installation step to add
the exit-code check and an error/exit with that code.
- Line 6: The Dockerfile RUN step downloads and executes UnityHubSetup.exe
without authenticity or integrity checks; update the RUN powershell command that
handles 'C:\UnityHubSetup.exe' to first download and verify the binary (e.g.,
fetch the vendor-provided signature or published SHA256, compute a local SHA256
and compare to a pinned value, or use PowerShell's Get-AuthenticodeSignature to
verify publisher/trusted signature) and only call Start-Process if the
verification succeeds; ensure failures abort the build and log the mismatch so
UnityHubSetup.exe is never executed unless the signature/hash verification
passes.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: f79f7b0c-8d43-4059-aec1-9c58cc86c04e
📒 Files selected for processing (1)
images/windows/hub/Dockerfile
| # Install unity hub | ||
| RUN choco install unity-hub --no-progress -y | ||
| # Install Unity Hub directly from Unity CDN (chocolatey unity-hub package CDN URL returns 404) | ||
| RUN powershell -NoLogo -Command "$ProgressPreference='SilentlyContinue'; Invoke-WebRequest -Uri 'https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.exe' -OutFile 'C:\UnityHubSetup.exe'; Start-Process -FilePath 'C:\UnityHubSetup.exe' -ArgumentList '/S' -Wait; Remove-Item 'C:\UnityHubSetup.exe' -Force" |
There was a problem hiding this comment.
Fail the build when Unity Hub installer returns a non-zero exit code.
Start-Process -Wait alone does not enforce success; this can silently produce/push a broken hub image if installation fails.
🤖 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 `@images/windows/hub/Dockerfile` at line 6, The RUN PowerShell command uses
Start-Process to install UnityHubSetup.exe but doesn't fail the Docker build on
installer errors; update the PowerShell snippet to capture the installer process
(use Start-Process with -PassThru or inspect $LASTEXITCODE/.ExitCode) and
explicitly exit/throw when the installer returns a non-zero code so the Docker
build fails; target the Start-Process invocation and the 'C:\UnityHubSetup.exe'
installation step to add the exit-code check and an error/exit with that code.
Add authenticity/integrity verification before executing the downloaded EXE.
This step downloads and runs UnityHubSetup.exe without validating publisher signature or a pinned hash, which is a supply-chain exposure on an automated publish path.
Suggested hardening
-RUN powershell -NoLogo -Command "$ProgressPreference='SilentlyContinue'; Invoke-WebRequest -Uri 'https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.exe' -OutFile 'C:\UnityHubSetup.exe'; Start-Process -FilePath 'C:\UnityHubSetup.exe' -ArgumentList '/S' -Wait; Remove-Item 'C:\UnityHubSetup.exe' -Force"
+RUN powershell -NoLogo -Command "$ProgressPreference='SilentlyContinue'; \
+ Invoke-WebRequest -Uri 'https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.exe' -OutFile 'C:\UnityHubSetup.exe'; \
+ $sig = Get-AuthenticodeSignature 'C:\UnityHubSetup.exe'; \
+ if ($sig.Status -ne 'Valid' -or $sig.SignerCertificate.Subject -notmatch 'Unity') { throw 'Unity Hub installer signature validation failed'; } ; \
+ $p = Start-Process -FilePath 'C:\UnityHubSetup.exe' -ArgumentList '/S' -Wait -PassThru; \
+ if ($p.ExitCode -ne 0) { throw ('Unity Hub installer failed with exit code ' + $p.ExitCode) } ; \
+ Remove-Item 'C:\UnityHubSetup.exe' -Force"📝 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.
| RUN powershell -NoLogo -Command "$ProgressPreference='SilentlyContinue'; Invoke-WebRequest -Uri 'https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.exe' -OutFile 'C:\UnityHubSetup.exe'; Start-Process -FilePath 'C:\UnityHubSetup.exe' -ArgumentList '/S' -Wait; Remove-Item 'C:\UnityHubSetup.exe' -Force" | |
| RUN powershell -NoLogo -Command "$ProgressPreference='SilentlyContinue'; \ | |
| Invoke-WebRequest -Uri 'https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.exe' -OutFile 'C:\UnityHubSetup.exe'; \ | |
| $sig = Get-AuthenticodeSignature 'C:\UnityHubSetup.exe'; \ | |
| if ($sig.Status -ne 'Valid' -or $sig.SignerCertificate.Subject -notmatch 'Unity') { throw 'Unity Hub installer signature validation failed'; } ; \ | |
| $p = Start-Process -FilePath 'C:\UnityHubSetup.exe' -ArgumentList '/S' -Wait -PassThru; \ | |
| if ($p.ExitCode -ne 0) { throw ('Unity Hub installer failed with exit code ' + $p.ExitCode) } ; \ | |
| Remove-Item 'C:\UnityHubSetup.exe' -Force" |
🤖 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 `@images/windows/hub/Dockerfile` at line 6, The Dockerfile RUN step downloads
and executes UnityHubSetup.exe without authenticity or integrity checks; update
the RUN powershell command that handles 'C:\UnityHubSetup.exe' to first download
and verify the binary (e.g., fetch the vendor-provided signature or published
SHA256, compute a local SHA256 and compare to a pinned value, or use
PowerShell's Get-AuthenticodeSignature to verify publisher/trusted signature)
and only call Start-Process if the verification succeeds; ensure failures abort
the build and log the mismatch so UnityHubSetup.exe is never executed unless the
signature/hash verification passes.
Unity renamed UnityHubSetup.exe to UnityHubSetup-x64.exe on their CDN. Both the chocolatey package and the previous direct URL were pointing to the old path, causing HTTP 404. Use the current working URL. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Unity Hub 3.16 added aggressive Chromium network initialization that fails in Windows containers without --no-sandbox. Ubuntu already uses this flag via its unityhub-bin wrapper. Apply it to all three Windows editor Dockerfile Hub invocations (install-path, install, install-modules). Also add a Docker daemon readiness wait to the windows-editor CI job; some Windows 2022 runners emit "docker engine not found" when the job starts before the daemon is ready. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
The same Docker-not-ready race affects windows-base-and-hub, not just windows-editor. Both Windows jobs now wait for the daemon before running any docker commands. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

Summary
New: self-healing workflow
CI fixes (Windows images were broken)
These failures were pre-existing but hidden because the Windows hub image hadn't built successfully in a long time. Fixing the hub unblocked the editor jobs and exposed the rest.
Testing