Skip to content

Pin the model revision and add the release publication pipeline#1

Merged
YurMil merged 4 commits into
mainfrom
feat/publish-pipeline
Jul 21, 2026
Merged

Pin the model revision and add the release publication pipeline#1
YurMil merged 4 commits into
mainfrom
feat/publish-pipeline

Conversation

@YurMil

@YurMil YurMil commented Jul 21, 2026

Copy link
Copy Markdown
Owner

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-tiny is pinned to the immutable commit ff41770 instead of main. 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.
  • The release build output config from docs/06-site-integration.md is now actually applied.
  • __APP_VERSION__ / __BUILD_ID__ are injected from package.json and git rev-parse, shown in the in-app diagnostics, and emitted to dist/build-info.json together 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.
  • Download sizes are formatted in decimal MB so the model size shown in the app matches the published documentation (~77 MB rather than ~73 MiB).

Publication pipeline

Tagging v* (or running Release manually with a tag) now:

  1. builds, typechecks and audits the bundle;
  2. packages whisper-transcriber-<tag>.zip, computes its SHA-256, and attaches both to a GitHub release;
  3. sends a whisper-transcriber-release repository_dispatch to 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 to YurMil/cadautoscript.com with 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 build and pnpm verify pass locally, and the produced artifact was published into the host checkout through both the local-build and the --archive --sha256 release path, including a deliberate checksum mismatch to confirm it is rejected before extraction.

🤖 Generated with Claude Code

YurMil and others added 4 commits July 21, 2026 14:04
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>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +74 to +82
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}`);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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}`);
}
}

Comment on lines +86 to +97
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');
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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']);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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']);

Comment thread package.json
"react-dom": "^19.1.0"
},
"devDependencies": {
"@types/node": "^26.1.1",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
"@types/node": "^26.1.1",
"@types/node": "^20.0.0",

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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 }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

@YurMil
YurMil merged commit bc8fa80 into main Jul 21, 2026
1 check passed
@YurMil YurMil mentioned this pull request Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant