feat(docs): validate USB Creator screenshot imports - #522
Conversation
📝 WalkthroughWalkthroughChangesUSB Creator import
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant Importer as USB Creator importer
participant Bundle as Guide bundle
participant Destination as Static destination
Operator->>Importer: Run importer with bundle path
Importer->>Bundle: Load and validate metadata
Importer->>Bundle: Verify image paths and SHA-256 digests
Importer->>Destination: Replace destination with staged screenshots
Destination-->>Operator: Imported screenshot set
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
## Summary Trusted screenshot publication reached the docs step but failed with exit 126; this invokes the checked-in publisher through Bash so its non-executable Git mode cannot block the workflow. ## Why This Exists The first main-branch run with `UNRAID_BOT_GITHUB_ADMIN_TOKEN` successfully verified the credential and checked out `unraid/docs`, then failed before publication because `e2e/docs/publish.sh` is mode `100644`. ## Resolution Invoke the script explicitly with Bash. This is portable across Git checkouts and makes the interpreter choice visible in the workflow without changing any publication boundary or credential handling. ## Reviewer Considerations - This PR depends operationally on unraid/docs#522, which adds the docs-owned verified screenshot importer called by the publisher. - The trusted-event secret gate remains unchanged. ## Behavior Changes Successful trusted QEMU runs can proceed into screenshot import instead of stopping with permission denied. ## Implementation Summary - Run `bash e2e/docs/publish.sh ...` in the publication step. ## Verification - `bash -n e2e/docs/publish.sh` - `actionlint .github/workflows/e2e-qemu.yml` - `git diff --check` ## Risk Low; only the invocation method changes.
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 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 `@scripts/import-usb-creator-flow.mjs`:
- Around line 17-19: Update the DESTINATION constant in the import-usb creator
script to resolve from the repository location derived from import.meta.url,
rather than the caller’s working directory, while preserving the existing
static/img/unraid-os/getting-started/create-unraid-usb path.
- Around line 93-100: Update the publication identity validation in the flow
import logic to require identity.publicationKey to equal the USB Creator
publication key “usb-creator:linux:create-unraid-usb”, while retaining the
existing non-empty string validation and captureId checks. Keep captureId
variable per capture as currently supported.
- Around line 140-141: Update the publication sequence around rm and rename to
replace DESTINATION atomically or through a reversible swap, retaining the
existing destination until the staged directory is successfully published and
rolling back on failure. Add a failure-path test for the importer that verifies
the previous DESTINATION remains available when publication fails.
- Around line 126-137: Update the staging write in the import flow after digest
and filename validation to write the already verified bytes from
readFile(source), replacing copyFile(source, path.join(staging, filename)).
Preserve the existing validation and destination filename behavior.
In `@scripts/import-usb-creator-flow.test.mjs`:
- Around line 65-81: Make the importer destination configurable and update the
success test around its fixture setup to use a unique mkdtemp-created directory
instead of the repository publication directory. Pass that destination to the
importer, assert outputs there, and ensure every cleanup block removes only the
test-owned temporary directory while leaving the repository’s published
screenshots untouched.
🪄 Autofix
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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 4291e8c2-2034-4dc4-9496-fb9cafef41a7
📒 Files selected for processing (2)
scripts/import-usb-creator-flow.mjsscripts/import-usb-creator-flow.test.mjs
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
unraid-docs | 502abd6 | Commit Preview URL Branch Preview URL |
Aug 06 2026, 02:30 PM |
Summary
USB Creator's accepted E2E captures need a docs-owned trust boundary; this adds the importer that verifies and exactly replaces the public screenshot set before automation opens a docs PR.
Why This Exists
The Creator pipeline correctly keeps guide prose out of the product repository and produces an immutable screenshot handoff. The docs publication step needs a repository-local importer to reject malformed, stale, path-escaping, or digest-mismatched bundles before any image becomes public.
Resolution
Add a narrowly scoped importer for the
unraid-os/create-unraid-usbflow. It validates schema version 2, the exact Linux publication identity, safe paths and filenames, every accepted SHA-256 digest, and contiguous step order. It writes the verified bytes into a complete staging set and swaps that set into place with rollback protection.Reviewer Considerations
Behavior Changes
Trusted USB Creator CI can create or refresh screenshot-only PRs in this repository after its destructive QEMU journey passes.
Implementation Summary
scripts/import-usb-creator-flow.mjswith schema, identity, path, filename, and digest validation.Verification
node --test scripts/import-usb-creator-flow.test.mjs— 3 tests passed.git diff --check— passed.Risk
Low. Writes are confined to one static-image directory and occur only after the full incoming set validates and stages successfully; a failed final swap restores the previous set.
Repository checklist