Pin the model revision and add the release publication pipeline#1
Conversation
Prepare the prototype for publication on cadautoscript.com: - pin onnx-community/whisper-tiny to an immutable commit SHA so the host CSP allowlist and rollback stay meaningful; - add the release build output config from docs/06-site-integration.md; - inject __APP_VERSION__/__BUILD_ID__ and emit dist/build-info.json so the host sync script can label and verify what it publishes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tagging `v*` now builds the bundle, audits it, attaches a checksummed archive to a GitHub release, and notifies cadautoscript.com, which republishes the artifact behind a pull request. The host never builds this app and never downloads model weights. - scripts/verify-artifact.mjs runs the same audit the host applies, so a bad bundle fails here instead of blocking the host pipeline; - build-info.json now carries buildTime as well, which keeps the published manifest a pure function of the artifact — republishing an unchanged release is a no-op the host can detect; - CI runs typecheck, build and the artifact audit on every pull request. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a release and publication pipeline for the Whisper transcriber utility. Key changes include adding a build verification script (scripts/verify-artifact.mjs) to audit the production bundle, generating a build-info.json asset during the Vite build, pinning the Whisper model to an immutable commit SHA, and updating the documentation. The review feedback suggests several improvements to the verification script: handling potential JSON parsing errors when reading build-info.json, allowing common web assets like images and fonts, and refining the relative path check to avoid false positives on external links. Additionally, it is recommended to align the @types/node dependency version with the targeted Node.js runtime.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| for (const reference of referenced) { | ||
| if (!reference.startsWith('./')) { | ||
| problems.push(`entry HTML must reference assets relatively, found: ${reference}`); | ||
| continue; | ||
| } | ||
| if (!assets.includes(reference.replace(/^\.\//, ''))) { | ||
| problems.push(`entry HTML references an unpackaged asset: ${reference}`); | ||
| } | ||
| } |
There was a problem hiding this comment.
The current relative path check is too restrictive because it flags all src and href attributes that do not start with ./. This will cause false positives for standard external hyperlinks (e.g., https://...), mailto links, or anchor links (e.g., #) in the HTML.
To make this check robust, we should skip external URLs and anchor links.
| for (const reference of referenced) { | |
| if (!reference.startsWith('./')) { | |
| problems.push(`entry HTML must reference assets relatively, found: ${reference}`); | |
| continue; | |
| } | |
| if (!assets.includes(reference.replace(/^\.\//, ''))) { | |
| problems.push(`entry HTML references an unpackaged asset: ${reference}`); | |
| } | |
| } | |
| for (const reference of referenced) { | |
| if (/^(https?:|mailto:|tel:|#)/.test(reference)) { | |
| continue; | |
| } | |
| if (!reference.startsWith('./')) { | |
| problems.push(`entry HTML must reference assets relatively, found: ${reference}`); | |
| continue; | |
| } | |
| if (!assets.includes(reference.replace(/^\.\//, ''))) { | |
| problems.push(`entry HTML references an unpackaged asset: ${reference}`); | |
| } | |
| } |
| const infoPath = path.join(DIST_DIR, 'build-info.json'); | ||
| if (!fs.existsSync(infoPath)) { | ||
| problems.push('missing build-info.json'); | ||
| } else { | ||
| const info = JSON.parse(fs.readFileSync(infoPath, 'utf8')); | ||
| for (const field of ['version', 'buildId', 'buildTime']) { | ||
| if (!info[field]) problems.push(`build-info.json is missing ${field}`); | ||
| } | ||
| if (info.buildId === 'unversioned') { | ||
| problems.push('build-info.json has no git build id — build inside a checkout'); | ||
| } | ||
| } |
There was a problem hiding this comment.
If build-info.json is empty, corrupted, or contains invalid JSON, JSON.parse will throw an unhandled exception and crash the verification script with a stack trace.
Wrapping this in a try-catch block allows the script to handle JSON parsing errors gracefully and report them as a validation problem.
const infoPath = path.join(DIST_DIR, 'build-info.json');
if (!fs.existsSync(infoPath)) {
problems.push('missing build-info.json');
} else {
try {
const info = JSON.parse(fs.readFileSync(infoPath, 'utf8'));
for (const field of ['version', 'buildId', 'buildTime']) {
if (!info[field]) problems.push(`build-info.json is missing ${field}`);
}
if (info.buildId === 'unversioned') {
problems.push('build-info.json has no git build id — build inside a checkout');
}
} catch (err) {
problems.push(`build-info.json is not valid JSON: ${err.message}`);
}
}| const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); | ||
| const DIST_DIR = path.resolve(process.argv[2] ?? path.join(ROOT, 'dist')); | ||
|
|
||
| const ALLOWED_EXTENSIONS = new Set(['.js', '.css', '.wasm', '.json', '.html', '.mjs']); |
There was a problem hiding this comment.
The allowed extensions list is highly restrictive and does not include common web assets such as images (.png, .svg, .ico, .webp) or web fonts (.woff2).
If the application needs to include a favicon, logo, or custom fonts in the future, this verification script (and the host's sync script) will fail. Consider adding these common extensions to the allowed list or documenting this limitation.
| const ALLOWED_EXTENSIONS = new Set(['.js', '.css', '.wasm', '.json', '.html', '.mjs']); | |
| const ALLOWED_EXTENSIONS = new Set(['.js', '.css', '.wasm', '.json', '.html', '.mjs', '.ico', '.png', '.svg', '.woff2']); |
| "react-dom": "^19.1.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^26.1.1", |
There was a problem hiding this comment.
The targeted Node.js version in engines is >=20, but @types/node is set to ^26.1.1. Since Node.js 26 does not exist yet, this can lead to type definitions for non-existent APIs or mismatched types.
It is highly recommended to align @types/node with the major version of Node.js you are targeting (e.g., ^20.0.0 or ^22.0.0) to ensure type safety and prevent the accidental use of APIs that are not available in your target runtime.
| "@types/node": "^26.1.1", | |
| "@types/node": "^20.0.0", |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 68e390c8bc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| SITE_REPOSITORY: YurMil/cadautoscript.com | ||
| # Read into env so the notify step can test it — the secrets context is | ||
| # not available in step-level `if` conditions. | ||
| SITE_DISPATCH_TOKEN: ${{ secrets.SITE_DISPATCH_TOKEN }} |
There was a problem hiding this comment.
Scope the dispatch token to the notify step
When SITE_DISPATCH_TOKEN is set, defining it in the job-level env makes the PAT available to every preceding step in this release job, including pnpm install, pnpm build, and any dependency lifecycle/build code they execute. Since this token has write access to the host repository and is only needed for the dispatch, keep the secret off the job environment and pass it only to the notify step, doing the empty-token check inside that step or via a non-secret boolean.
Useful? React with 👍 / 👎.
Prepares this repository to publish the transcriber to cadautoscript.com as a versioned static artifact, and automates that publication.
Companion PR on the host: YurMil/cadautoscript.com#130
Reproducible, traceable builds
onnx-community/whisper-tinyis pinned to the immutable commitff41770instead ofmain. The host CSP allowlists the Hub origins and rollback depends on the weights behind a given release never changing under us, so a branch name was not good enough.docs/06-site-integration.mdis now actually applied.__APP_VERSION__/__BUILD_ID__are injected frompackage.jsonandgit rev-parse, shown in the in-app diagnostics, and emitted todist/build-info.jsontogether with the build time. The host copies those into its manifest, so a deployed bundle always traces back to a source commit — and republishing an unchanged release is a no-op the host can detect.Publication pipeline
Tagging
v*(or running Release manually with a tag) now:whisper-transcriber-<tag>.zip, computes its SHA-256, and attaches both to a GitHub release;whisper-transcriber-releaserepository_dispatchto the host repository, which verifies the checksum, republishes the artifact and opens a pull request.scripts/verify-artifact.mjs(pnpm verify) runs the same audit the host applies — no symlinks, no path traversal, no source maps, no development references, and the entry document may only reference packaged relative assets — so a bad bundle fails here rather than in the host pipeline. CI runs typecheck, build and that audit on every pull request.Required secret
SITE_DISPATCH_TOKEN— a fine-grained PAT scoped toYurMil/cadautoscript.comwith Contents: read and write, used only to send the dispatch event. Without it the release still succeeds; the host sync can then be started manually from its Actions tab with the tag.Verification
pnpm typecheck,pnpm buildandpnpm verifypass locally, and the produced artifact was published into the host checkout through both the local-build and the--archive --sha256release path, including a deliberate checksum mismatch to confirm it is rejected before extraction.🤖 Generated with Claude Code