Skip to content

fix(publish): normalize semver metadata#806

Merged
jdx merged 8 commits into
mainfrom
fix/publish-normalize-version
May 29, 2026
Merged

fix(publish): normalize semver metadata#806
jdx merged 8 commits into
mainfrom
fix/publish-normalize-version

Conversation

@jdx

@jdx jdx commented May 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • Normalize npm publish-facing semver values before registry checks and PUT metadata
  • Rebuild the publish tarball with normalized package/package.json bytes when package versions need npm-style cleaning
  • Detect npm OTP challenges that say one-time pass and retry through the interactive OTP prompt
  • Add regression coverage for the mise failure shape and npm OTP wording

Why

Mise release packages use tags like v2026.5.16 as package.json#version. npm publish auto-corrects that to 2026.5.16 in publish metadata and in the packed package JSON, but aube publish sent the raw v... value and npm rejected it with New versions must be valid semver.

The user-reported OTP path also failed because npm returns You must provide a one-time pass..., while aube only detected one-time password wording.

Latest failed mise run showing the semver regression: https://github.com/jdx/mise/actions/runs/26599017929

Discussion report for the OTP prompt UX: https://github.com/endevco/aube/discussions/345#discussioncomment-17049217

Test

  • cargo test -p aube commands::publish::tests::
  • Local OTP publish without --otp prompted after npm challenge and published @endevco/aube-publish-otp-smoke@0.0.0-interactive.1780033846

This PR was generated by an AI coding assistant.


Note

Medium Risk
Changes publish tarball contents and registry version keys (behavioral fix aligned with npm); OTP heuristics are slightly broader but still gated on 401/403.

Overview
Publish now normalizes semver the way npm does before registry checks, tarball naming, and PUT metadata. Versions like v2026.5.16 are parsed with node_semver to 2026.5.16; when that changes the on-disk string, publish rebuilds the archive via build_archive_with_package_json so package/package.json inside the .tgz and versions.<v> / dist-tags in the publish body all use the cleaned version (fixes npm’s “New versions must be valid semver” for mise-style tags).

Pack gains optional in-memory package.json bytes (data_override on packed files) so publish can ship normalized manifest content without rewriting the workspace file.

OTP retry detection now treats npm’s one-time pass / one time pass challenges like existing one-time password wording, so interactive OTP prompt works on current npm 2FA errors.

Tests: unit coverage for normalization, publish body keys, tarball contents, and OTP phrasing; deploy bats assert on empty instead of is not when miette wraps long paths.

Reviewed by Cursor Bugbot for commit c8242f4. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-apps Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two publish regressions: npm rejecting v-prefixed semver tags (e.g. v2026.5.16) and OTP retry not triggering on npm's one-time pass challenge wording.

  • Semver normalization: normalize_publish_version strips the v prefix via node_semver, applied to the pre-flight version check, registry PUT metadata (dist-tags, versions key, _id, version field), tarball filename, and — via build_archive_for_publish + data_override — the embedded package/package.json bytes inside the .tgz, making the tarball self-consistent with what npm would produce.
  • OTP detection: Adds "one-time pass" and "one time pass" as additional trigger substrings alongside the existing "one-time password" / "one time password" variants.
  • Test hardening: deploy.bats assertions switch from "is not" to "empty" to survive miette line-wrap when temp-dir paths grow long enough to push "not" onto its own line.

Confidence Score: 5/5

Safe to merge — the normalization path is publish-only, the plain aube pack code path is unchanged, and the three new behaviors are each independently tested.

All changed code paths are narrowly scoped: normalization only fires when a v-prefix is present, the data_override mechanism does not alter the on-disk file, and the OTP substring additions are additive. The test suite covers the introduced code branches end-to-end. No regressions are visible in the existing paths.

No files require special attention.

Important Files Changed

Filename Overview
crates/aube/src/commands/publish.rs Adds version normalization (v-prefix stripping), tarball override for embedded package.json, OTP wording expansion, and aligned version field in publish body; logic is self-consistent and well-tested.
crates/aube/src/commands/pack.rs Adds data_override field to PackedFile and build_archive_with_package_json entry point; plain aube pack path is unchanged (delegates to the new function with None).
test/deploy.bats Tightens the word-wrap-resistant assertion from is not to empty in two deploy error tests; more robust when temp-dir paths cause miette to break the line before not.

Reviews (5): Last reviewed commit: "test(deploy): tolerate wrapped empty mes..." | Re-trigger Greptile

Comment thread crates/aube/src/commands/publish.rs
@jdx jdx enabled auto-merge (squash) May 29, 2026 05:59
@jdx jdx disabled auto-merge May 29, 2026 06:07
@jdx jdx merged commit 7cfcd56 into main May 29, 2026
18 checks passed
@jdx jdx deleted the fix/publish-normalize-version branch May 29, 2026 06:21
@greptile-apps greptile-apps Bot mentioned this pull request May 29, 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