Automate transcriber publication and fix the blocked ONNX runtime#131
Conversation
Releases in YurMil/ws-speech-text now notify this repository, which republishes the artifact and opens a pull request for review. Nothing deploys unreviewed, and the site still never builds the app or downloads model weights. - sync-whisper-transcriber.mjs gains an --archive/--sha256 mode: the checksum is verified before anything is extracted, then the existing audit runs unchanged; - the manifest takes its build time from the source build rather than now(), so republishing an unchanged release produces no diff and CI can skip the PR; - .github/workflows/sync-whisper-transcriber.yml wires it together and can also be run manually with a tag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
git diff misses untracked files, so a release that only adds a newly hashed asset would have looked unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The previous bundle let Transformers.js load ONNX Runtime from jsDelivr, which the site CSP blocks: transcription failed with MODEL_DOWNLOAD_FAILED and a blocked script-src for ort-wasm-simd-threaded.jsep.mjs. The source now pins the runtime to the copies shipped inside the artifact. Verified by serving this artifact with the exact headers from vercel.json: both the WebGPU and the WASM-only paths prepare the model and transcribe with no console errors, so the only third-party request left is the pinned model download from the Hugging Face Hub. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
Code Review
This pull request introduces an automated pipeline to sync and publish the Whisper Transcriber app from its own repository as a static artifact, updating the sync script to support verifying and extracting release archives. The review feedback highlights three key areas for improvement: addressing a cross-platform compatibility issue on Linux runners where GNU tar cannot extract .zip archives, hardening the command-line flag parser to prevent misinterpreting adjacent flags as values, and adding defensive checks to ensure the parsed build-info JSON is a valid object before accessing its properties.
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.
| function readFlag(name) { | ||
| const index = process.argv.indexOf(name); | ||
| return index === -1 ? undefined : process.argv[index + 1]; | ||
| } |
There was a problem hiding this comment.
The readFlag function currently returns the next argument in process.argv without verifying if it is another flag. If a flag is passed without a value (or if flags are passed in a different order), this can lead to unexpected behavior (e.g., treating --sha256 as the archive path).
Adding a check to ensure the value does not start with a hyphen (-) makes the argument parsing more robust.
| function readFlag(name) { | |
| const index = process.argv.indexOf(name); | |
| return index === -1 ? undefined : process.argv[index + 1]; | |
| } | |
| function readFlag(name) { | |
| const index = process.argv.indexOf(name); | |
| if (index === -1) return undefined; | |
| const value = process.argv[index + 1]; | |
| return value && !value.startsWith('-') ? value : undefined; | |
| } |
| if (!info.buildId || !info.version || !info.buildTime) { | ||
| fail('build-info.json is missing version, buildId or buildTime.'); | ||
| } |
There was a problem hiding this comment.
Defensive programming: JSON.parse can theoretically return null or non-object values if the JSON file is malformed or empty. Accessing properties like buildId on null will throw a TypeError and crash the script with an unhelpful error message.
Adding a check to ensure info is a non-null object before accessing its properties provides better safety.
| if (!info.buildId || !info.version || !info.buildTime) { | |
| fail('build-info.json is missing version, buildId or buildTime.'); | |
| } | |
| if (!info || typeof info !== 'object' || !info.buildId || !info.version || !info.buildTime) { | |
| fail('build-info.json is missing version, buildId or buildTime.'); | |
| } |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a237da974
ℹ️ 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".
|
|
||
| scratchDir = fs.mkdtempSync(path.join(os.tmpdir(), 'whisper-transcriber-')); | ||
| // bsdtar reads zip archives and is present on Windows, macOS and the runners. | ||
| run('tar', ['-xf', path.resolve(archive), '-C', scratchDir]); |
There was a problem hiding this comment.
Extract release ZIPs with a ZIP-capable tool
The workflow downloads whisper-transcriber-${TAG}.zip and passes it to this --archive path, but on ubuntu-latest tar is GNU tar rather than bsdtar; I checked the CLI behavior (tar --version reports tar (GNU tar) 1.35) and tar -xf on a ZIP exits with This does not look like a tar archive. As a result, repository_dispatch/manual syncs for the advertised ZIP release will fail here immediately after checksum verification, before the artifact can be republished or a PR opened.
Useful? React with 👍 / 👎.
Added: mobile support, and a leak that would have shippedThis branch now also carries the mobile work (source: YurMil/ws-speech-text#3), because it republishes the same artifact and would otherwise conflict. What was wrong. A mobile-optimization branch had been prepared separately. Its engineering direction was right —
Both fixed: the font is gone (system stack, zero requests), and there is now one interface, mobile-first, with the editable transcript restored. Guard. Docs. Updated in all six locales: per-device download size (41 MB WASM / 77 MB WebGPU) instead of one wrong number for both paths, control names matching the interface, conveyor windows documented per platform, and a new "on a phone" section. Verified under the exact headers from Merge order: YurMil/ws-speech-text#2, then #3, then this — the artifact here is built from #3. Still unverified: a real iPhone. The tab-kill that started this is device behaviour I cannot reproduce locally. |
Follow-up to #130, which was merged after only its first commit. This carries the rest of that work: the publication pipeline and a user-visible fix — the transcriber currently fails on production.
1. Fix: transcription fails with
MODEL_DOWNLOAD_FAILEDThe artifact on
mainlets Transformers.js load ONNX Runtime from jsDelivr, which the site CSP blocks:Transformers.js defaults ORT's
wasmPathsto a CDN URL, which also overrode the runtime copies we already ship — the 21 MB.wasmin the artifact was never used. The source now clears that default (YurMil/ws-speech-text#2) and the artifact here is rebuilt from it.No CSP change: widening
script-srcto a third-party CDN to fetch a file we already host would be the wrong trade.Verified by serving the published artifact with the exact headers from
vercel.jsonand running a real transcription:auto→ WebGPUwasmonlyThe only third-party request left at runtime is the pinned model download from the Hugging Face Hub.
2. Automated publication pipeline
.github/workflows/sync-whisper-transcriber.ymlreacts to awhisper-transcriber-releaserepository_dispatchfromYurMil/ws-speech-text(or runs manually with a tag): it downloads the release archive, refuses it unless the SHA-256 matches, republishes the artifact throughscripts/sync-whisper-transcriber.mjs, runs typecheck/lint/build, and opens a pull request. Nothing deploys without review, and this repository still never builds the app or downloads model weights.Supporting changes to the sync script:
--archive … --sha256 …mode — the checksum is verified before anything is extracted, then the existing file audit runs unchanged;now(), so republishing an unchanged release produces no diff and the workflow can skip opening a PR;git status --porcelain, sincegit diffwould miss a release that only adds a newly hashed asset.Requires: the
SITE_DISPATCH_TOKENsecret inYurMil/ws-speech-text— a fine-grained PAT scoped to this repository with Contents: read and write. Optional here:SOURCE_RELEASE_TOKEN, only needed if the source repository becomes private.Merge order
Merge YurMil/ws-speech-text#2 first so the source matches the artifact published here; the artifact in this PR is already built from that fix.
Verification
npm run typecheck,npm run lint(0 errors) and a six-localenpm run buildpass. The archive path was exercised with a matching checksum (byte-identical republish) and with a deliberate mismatch (rejected, exit 1, target untouched).🤖 Generated with Claude Code