Repository navigation
ci(v3): keep @wailsio/runtime in lockstep with the CLI version - #5820
Conversation
The npm package version was produced by `npm version prerelease`, which increments the trailing numeric identifier and knows nothing about the release channel. That is how the two series drifted: the CLI went alpha -> alpha2 -> beta while npm kept counting alpha.N. Today the CLI is v3.0.0-alpha2.117 and npm is 3.0.0-alpha.97, and at beta a v3.0.0-beta.0 CLI would have shipped alongside an "alpha" runtime, with every upgrading user needing to be told the mismatch was expected. The runtime version now comes from v3/internal/version/version.txt, the same file go:embed puts into the CLI, so the two always agree. Because the version now only moves when version.txt moves, a run triggered by a runtime source change between releases would try to republish an existing version. Such runs now skip the publish step while still committing regenerated assets, and version.txt is added to the trigger and detection paths so a release that moves it does publish. Merging this publishes nothing: a workflow-file-only change does not match the detect job's file lists, so the publish job does not run. The next publish happens when version.txt next moves, and it will be 3.0.0-alpha2.117 rather than 3.0.0-alpha.98. That sorts higher, so nothing downstream breaks. Verified: actionlint clean; version derivation exercised for both the current master value and the beta value; the already-published guard correctly detects 3.0.0-alpha.97 as present and 3.0.0-beta.0 as absent. Claude-Session: https://claude.ai/code/session_01FigQqUQbNu9ngE4a2CSNm8
leaanthony
left a comment
There was a problem hiding this comment.
Deriving from version.txt is the right anchor: it is already the single source the CLI embeds, so lockstep falls out rather than needing to be maintained.
The republish guard is the part I would have missed. Without it, the first runtime source change after a release fails the workflow at npm publish, which is precisely the failure mode that left npm frozen at alpha.79 for months last time.
Agreed on not bumping package.json here so the merge stays inert.
WalkthroughThe npm publishing workflow now triggers on runtime version changes, derives the package version from Changesnpm publish workflow
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant version.txt
participant publish-npm.yml
participant npm_registry
version.txt->>publish-npm.yml: Provide the package version
publish-npm.yml->>publish-npm.yml: Validate and set the package version
publish-npm.yml->>npm_registry: Check whether the version exists
npm_registry-->>publish-npm.yml: Return published status
publish-npm.yml->>npm_registry: Publish missing versions with latest tag
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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 |
Follows the lockstep change in #5820: from the beta onwards @wailsio/runtime takes its version from the same file the CLI embeds, so the upgrade page no longer has to explain away a mismatch. It now says the two agree, and why an alpha project's runtime version looks unrelated. Claude-Session: https://claude.ai/code/session_01FigQqUQbNu9ngE4a2CSNm8
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/publish-npm.yml:
- Around line 167-181: Update the already-published check in the “Skip publish
if this version is already on npm” step to distinguish a missing package version
from npm lookup failures: treat only an E404 response as unpublished, while
propagating or failing the workflow for network, registry, authentication, or
other errors. Preserve the existing published=true output and notice for
versions confirmed to exist.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1fafeeff-b523-47a2-af77-d8a26c34c5b2
📒 Files selected for processing (1)
.github/workflows/publish-npm.yml
| - name: Skip publish if this version is already on npm | ||
| id: already-published | ||
| # Lockstep means the version only moves when version.txt moves, so a run | ||
| # triggered by a runtime source change between releases would otherwise | ||
| # try to republish an existing version and fail. Regenerated assets are | ||
| # still committed below; only the publish is skipped. | ||
| run: | | ||
| echo "version=$(npm --no-git-tag-version --force version prerelease)" >> "$GITHUB_OUTPUT" | ||
| set -euo pipefail | ||
| VERSION="${{ steps.bump-version.outputs.version }}" | ||
| if npm view "@wailsio/runtime@${VERSION}" version >/dev/null 2>&1; then | ||
| echo "published=true" >> "$GITHUB_OUTPUT" | ||
| echo "::notice::@wailsio/runtime@${VERSION} is already on npm; skipping publish. It will publish when version.txt next moves." | ||
| else | ||
| echo "published=false" >> "$GITHUB_OUTPUT" | ||
| fi |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set +e
npm view '`@wailsio/runtime`@0.0.0-coderabbit-absent' version >/dev/null 2>npm-view.err
status=$?
echo "exit status: $status"
cat npm-view.err
rm -f npm-view.errRepository: wailsapp/wails
Length of output: 795
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow relevant lines =="
sed -n '140,210p' .github/workflows/publish-npm.yml
echo
echo "== npm view E404 behavior for a non-existent `@wailsio/runtime` version =="
set +e
tmp="$(mktemp)"
npm view '`@wailsio/runtime`@0.0.0-coderabbit-absent-mock' version >/dev/null 2>"$tmp"
status=$?
echo "exit status: $status"
grep -n 'npm error code E404' "$tmp" || true
rm -f "$tmp"
echo
echo "== npm view E404 behavior for the existing wailsio runtime version =="
set +e
tmp="$(mktemp)"
npm view '`@wailsio/runtime`@1.0.0' version >/dev/null 2>"$tmp"
status=$?
echo "exit status: $status"
if [ "$status" -eq 0 ]; then
echo "already published"
fi
rm -f "$tmp"Repository: wailsapp/wails
Length of output: 4061
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== npm view stdout with existing version =="
set +e
tmp="$(mktemp)"
npm view '`@wailsio/runtime`@1.0.0' version >/dev/null 2>"$tmp"
status=$?
echo "exit status: $status"
printf ':=%s=:' "$(head -n 5 "$tmp" | tr '\n' ' ')"
rm -f "$tmp"
echo
echo "== npm view with non-existent version =="
tmp="$(mktemp)"
npm view '`@wailsio/runtime`@0.0.0-coderabbit-absent-mock' version >/dev/null 2>"$tmp"
status=$?
echo "exit status: $status"
cat "$tmp"
rm -f "$tmp"Repository: wailsapp/wails
Length of output: 1266
🌐 Web query:
npm CLI registry https://registry.npmjs.org wailsio/runtime package latest npm view
💡 Result:
The npm package for the Wails framework's frontend runtime in Wails v3 is @wailsio/runtime [1][2]. As of July 26, 2026, the latest version of @wailsio/runtime available on the npm registry is 3.0.0-alpha.97 [1][3]. The Wails team manages this package as part of the Wails v3 ecosystem [1][4], and it is intended to be installed as a dependency in Wails projects to provide frontend access to the Wails runtime [2][5]. For historical context, older versions of the Wails framework used different packages, such as @wails/runtime and @wailsapp/runtime (associated with Wails v2) [6][7][8]. Users should ensure they are using @wailsio/runtime for Wails v3 projects [2].
Citations:
- 1: https://www.npmjs.com/package/@wailsio/runtime
- 2: https://v3.wails.io/reference/frontend-runtime/
- 3: https://cdn.jsdelivr.net/npm/@wailsio/runtime/
- 4: https://registry.npmjs.org/@wailsio/runtime
- 5: [v3] Move runtime to "dependencies", organize package.json files #4133
- 6: https://www.npmjs.com/package/@wails/runtime
- 7: https://registry.npmjs.org/@wailsapp/runtime
- 8: https://registry.npmjs.org/@wails/runtime
Fail closed when the npm lookup errors.
A failed npm view covers registry/network failures too, not just missing versions. This marks the version unpublished and commits generated assets, so the subsequent publish can fail without retrying that release. Treat only E404 as not yet published.
Proposed fix
run: |
set -euo pipefail
VERSION="${{ steps.bump-version.outputs.version }}"
- if npm view "`@wailsio/runtime`@${VERSION}" version >/dev/null 2>&1; then
+ error_file="$(mktemp)"
+ trap 'rm -f "$error_file"' EXIT
+ if npm view "`@wailsio/runtime`@${VERSION}" version >/dev/null 2>"$error_file"; then
echo "published=true" >> "$GITHUB_OUTPUT"
echo "::notice::`@wailsio/runtime`@${VERSION} is already on npm; skipping publish. It will publish when version.txt next moves."
else
- echo "published=false" >> "$GITHUB_OUTPUT"
+ status=$?
+ if grep -q '^npm error code E404$' "$error_file"; then
+ echo "published=false" >> "$GITHUB_OUTPUT"
+ else
+ cat "$error_file" >&2
+ exit "$status"
+ fi
fi📝 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.
| - name: Skip publish if this version is already on npm | |
| id: already-published | |
| # Lockstep means the version only moves when version.txt moves, so a run | |
| # triggered by a runtime source change between releases would otherwise | |
| # try to republish an existing version and fail. Regenerated assets are | |
| # still committed below; only the publish is skipped. | |
| run: | | |
| echo "version=$(npm --no-git-tag-version --force version prerelease)" >> "$GITHUB_OUTPUT" | |
| set -euo pipefail | |
| VERSION="${{ steps.bump-version.outputs.version }}" | |
| if npm view "@wailsio/runtime@${VERSION}" version >/dev/null 2>&1; then | |
| echo "published=true" >> "$GITHUB_OUTPUT" | |
| echo "::notice::@wailsio/runtime@${VERSION} is already on npm; skipping publish. It will publish when version.txt next moves." | |
| else | |
| echo "published=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Skip publish if this version is already on npm | |
| id: already-published | |
| # Lockstep means the version only moves when version.txt moves, so a run | |
| # triggered by a runtime source change between releases would otherwise | |
| # try to republish an existing version and fail. Regenerated assets are | |
| # still committed below; only the publish is skipped. | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ steps.bump-version.outputs.version }}" | |
| error_file="$(mktemp)" | |
| trap 'rm -f "$error_file"' EXIT | |
| if npm view "`@wailsio/runtime`@${VERSION}" version >/dev/null 2>"$error_file"; then | |
| echo "published=true" >> "$GITHUB_OUTPUT" | |
| echo "::notice::`@wailsio/runtime`@${VERSION} is already on npm; skipping publish. It will publish when version.txt next moves." | |
| else | |
| status=$? | |
| if grep -q '^npm error code E404$' "$error_file"; then | |
| echo "published=false" >> "$GITHUB_OUTPUT" | |
| else | |
| cat "$error_file" >&2 | |
| exit "$status" | |
| fi | |
| fi |
🧰 Tools
🪛 zizmor (1.26.1)
[info] 175-175: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 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/publish-npm.yml around lines 167 - 181, Update the
already-published check in the “Skip publish if this version is already on npm”
step to distinguish a missing package version from npm lookup failures: treat
only an E404 response as unpublished, while propagating or failing the workflow
for network, registry, authentication, or other errors. Preserve the existing
published=true output and notice for versions confirmed to exist.
Picks up the contribution terms (wailsapp#5816), the release workflow hardening (wailsapp#5815), the runtime/CLI version lockstep (wailsapp#5820) and the crash fixes merged since the first sync. Clean merge, no conflicts. The branch was six commits behind again within hours of the first sync, which is why this is now an audit blocker rather than something to remember: a release branch that quietly ages is how a release ships without fixes everyone believes are in it. Claude-Session: https://claude.ai/code/session_01FigQqUQbNu9ngE4a2CSNm8
The problem
publish-npm.ymlbumped the package with:That increments the trailing numeric identifier and knows nothing about the release channel. It is exactly why the two version series drifted apart: the CLI moved
alpha→alpha2→betawhile npm carried on countingalpha.N.Today the CLI reports
v3.0.0-alpha2.117and npm's latest is3.0.0-alpha.97. At beta that becomes user-visible: av3.0.0-beta.0CLI sitting next to an@wailsio/runtimethat still saysalpha, and every upgrading user has to be told the mismatch is fine.The change
The runtime version now comes from
v3/internal/version/version.txt— the same filego:embedputs into the CLI — so the two always agree.Two consequences handled:
version.txtmoves, so a run triggered by a runtime source change between releases would try to republish an existing version and fail. Those runs now skip the publish step while still committing regenerated assets, with a notice explaining why.version.txtis added to both the trigger paths and the detect job's file list, so a release that moves it does publish.Merging this publishes nothing
A workflow-file-only change does not match the detect job's file lists, so the publish job will not run on merge. I deliberately did not bump
package.jsonin this PR for that reason.The next publish happens when
version.txtnext moves, and it will be3.0.0-alpha2.117rather than3.0.0-alpha.98. That sorts higher under semver, solatestresolution and every downstream pin behave correctly. It is a visible jump in the npm series, which is the one-off cost of ending the drift.Verification
actionlintclean.version.txt(v3.0.0-alpha2.117→3.0.0-alpha2.117) and against the beta branch value (v3.0.0-beta.0→3.0.0-beta.0).3.0.0-alpha.97as present (would skip) and3.0.0-beta.0as absent (would publish).Once this is in, the alpha-to-beta upgrade page on the beta branch loses its "the runtime version will not match your CLI" caveat, which is a better outcome than documenting the confusion.
Summary by CodeRabbit
latesttag behavior.