From 1372c55b3a559fd8d58d71faa82b112fae25ce76 Mon Sep 17 00:00:00 2001 From: sunnylqm Date: Sun, 18 Oct 2026 21:51:29 +0800 Subject: [PATCH 1/2] ci: publish the version named by the release tag A release is now only a GitHub Release whose tag (vX.Y.Z) points at a green master commit: no version-bump commit, so no extra native E2E run before publishing. The publish job writes the tag's version into package.json and harmony/pushy/oh-package.json5 (scripts/stamp-release-version.js, which replaces check-release-version.js) before the HAR build and npm publish. The committed versions are no longer bumped and may lag the published one. Co-Authored-By: Claude Opus 5.5 --- .github/actions/publish-npm/action.yml | 11 +++--- harmony/pushy/src/README.md | 6 ++-- scripts/build-harmony-har.js | 4 +-- scripts/check-release-version.js | 40 --------------------- scripts/stamp-release-version.js | 50 ++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 49 deletions(-) delete mode 100644 scripts/check-release-version.js create mode 100644 scripts/stamp-release-version.js diff --git a/.github/actions/publish-npm/action.yml b/.github/actions/publish-npm/action.yml index 27886876..8904e0e2 100644 --- a/.github/actions/publish-npm/action.yml +++ b/.github/actions/publish-npm/action.yml @@ -70,6 +70,13 @@ runs: shell: bash run: node scripts/verify-android-so.js + # The release tag is the version: no version-bump commit precedes a + # release, so write it into package.json and oh-package.json5 before the + # HAR build and npm publish read them. + - name: Stamp the release version + shell: bash + run: node scripts/stamp-release-version.js + - name: Build Harmony HAR if: inputs.harmony-har == 'build' shell: bash @@ -98,10 +105,6 @@ runs: shell: bash run: test -f harmony/pushy.har - - name: Verify release tag matches package version - shell: bash - run: node scripts/check-release-version.js - - name: Verify publish file list shell: bash run: node scripts/check-packlist.js --release diff --git a/harmony/pushy/src/README.md b/harmony/pushy/src/README.md index d307bfdd..5210a5d7 100644 --- a/harmony/pushy/src/README.md +++ b/harmony/pushy/src/README.md @@ -66,9 +66,9 @@ so a debug rebuild does not look like a new binary. Add the generated file to ## Versioning -`oh-package.json5` `version` mirrors the npm package version; -`scripts/build-harmony-har.js` rewrites it before `assembleHar` and -`scripts/check-release-version.js` asserts the committed value matches. +`oh-package.json5` `version` mirrors the npm package version: the publish +workflow writes the release tag's version into both (`scripts/stamp-release-version.js`), +and `scripts/build-harmony-har.js` syncs it from `package.json` before `assembleHar`. This file is packaged with the npm module (`harmony/pushy/src/`) so it is available next to the sources in `node_modules/react-native-update`. diff --git a/scripts/build-harmony-har.js b/scripts/build-harmony-har.js index 22621092..496ef9f5 100644 --- a/scripts/build-harmony-har.js +++ b/scripts/build-harmony-har.js @@ -157,7 +157,7 @@ function buildHar() { // The HAR carries its own version in oh-package.json5. Consumers' // oh-package-lock.json5 and diagnostics can only tell installs apart when it // equals the npm version, so rewrite it from package.json before assembleHar -// (scripts/check-release-version.js keeps the committed value honest). +// (scripts/stamp-release-version.js writes both from the release tag). function syncOhPackageVersion() { const packageJsonPath = path.join(projectRoot, 'package.json'); const ohPackagePath = path.join(harmonyModuleDir, 'oh-package.json5'); @@ -166,7 +166,7 @@ function syncOhPackageVersion() { fail('package.json has no version to write into oh-package.json5'); } const content = fs.readFileSync(ohPackagePath, 'utf8'); - // JSON5 allows the key bare or quoted (check-release-version.js matches + // JSON5 allows the key bare or quoted (stamp-release-version.js matches // the same shapes). const versionLine = /^(\s*(?:"version"|'version'|version)\s*:\s*)(['"])([^'"]*)\2(\s*,?)/m; diff --git a/scripts/check-release-version.js b/scripts/check-release-version.js deleted file mode 100644 index 580d22a3..00000000 --- a/scripts/check-release-version.js +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env node -// The release tag (vX.Y.Z) must be the package.json version being published: -// a mismatch means the tag points at the wrong commit or the version bump -// was forgotten, and npm would happily publish under the stale number. -const pkg = require('../package.json'); -const tag = process.env.RELEASE_VERSION || ''; -if (!tag) { - console.error('check-release-version: RELEASE_VERSION is not set'); - process.exit(1); -} -const expected = `v${pkg.version}`; -if (tag !== expected && tag !== pkg.version) { - console.error( - `check-release-version: tag ${tag} does not match package.json version ${pkg.version}` - ); - process.exit(1); -} - -// The Harmony HAR carries its own version (oh-package.json5); consumers' -// oh-package-lock.json5 and diagnostics can only tell installs apart when it -// tracks package.json. scripts/build-harmony-har.js rewrites it before -// assembleHar, and this check keeps the committed value from drifting. -const fs = require('fs'); -const path = require('path'); -const ohPackagePath = path.join(__dirname, '..', 'harmony/pushy/oh-package.json5'); -const ohPackage = fs.readFileSync(ohPackagePath, 'utf8'); -// JSON5 allows the key bare or quoted; the regex is shared in spirit with -// syncOhPackageVersion in scripts/build-harmony-har.js. -const ohVersion = (ohPackage.match( - /^\s*(?:"version"|'version'|version)\s*:\s*['"]([^'"]+)['"]/m -) || [])[1]; -if (ohVersion !== pkg.version) { - console.error( - `check-release-version: harmony/pushy/oh-package.json5 version ${ohVersion} does not match package.json version ${pkg.version}` - ); - process.exit(1); -} -console.log( - `check-release-version: ${tag} matches package.json and oh-package.json5 ${pkg.version}` -); diff --git a/scripts/stamp-release-version.js b/scripts/stamp-release-version.js new file mode 100644 index 00000000..fe147ec8 --- /dev/null +++ b/scripts/stamp-release-version.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node +// Releases are cut from the GitHub Release tag alone (vX.Y.Z on a green +// master commit, no version-bump commit), so the version is written into the +// package here, before the HAR build and npm publish: +// - package.json: the version npm publishes and the podspec reads. +// - harmony/pushy/oh-package.json5: the HAR's own version. Consumers' +// oh-package-lock.json5 and diagnostics can only tell installs apart when it +// equals the npm version (scripts/build-harmony-har.js syncs it from +// package.json again before assembleHar). +const fs = require('fs'); +const path = require('path'); + +const tag = process.env.RELEASE_VERSION || ''; +const version = tag.replace(/^v/, ''); +// semver: X.Y.Z with an optional prerelease (10.62.0-beta.1). +if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) { + console.error( + `stamp-release-version: release tag '${tag}' is not vX.Y.Z or vX.Y.Z-prerelease` + ); + process.exit(1); +} + +const root = path.join(__dirname, '..'); +const packageJsonPath = path.join(root, 'package.json'); +const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); +pkg.version = version; +fs.writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`); + +const ohPackagePath = path.join(root, 'harmony/pushy/oh-package.json5'); +const ohPackage = fs.readFileSync(ohPackagePath, 'utf8'); +// JSON5 allows the key bare or quoted (syncOhPackageVersion in +// scripts/build-harmony-har.js matches the same shapes). +const versionLine = + /^(\s*(?:"version"|'version'|version)\s*:\s*)(['"])([^'"]*)\2(\s*,?)/m; +if (!versionLine.test(ohPackage)) { + console.error( + 'stamp-release-version: no version field in harmony/pushy/oh-package.json5' + ); + process.exit(1); +} +fs.writeFileSync( + ohPackagePath, + ohPackage.replace( + versionLine, + (_, prefix, quote, __, suffix) => `${prefix}${quote}${version}${quote}${suffix}` + ) +); +console.log( + `stamp-release-version: package.json and oh-package.json5 set to ${version} from ${tag}` +); From 82def1339ab2efda1791ee913b4f033d46e5d76a Mon Sep 17 00:00:00 2001 From: sunnylqm Date: Sun, 18 Oct 2026 21:57:47 +0800 Subject: [PATCH 2/2] ci: reject malformed prerelease tags Co-Authored-By: Claude Opus 5.5 --- scripts/stamp-release-version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/stamp-release-version.js b/scripts/stamp-release-version.js index fe147ec8..6d841b65 100644 --- a/scripts/stamp-release-version.js +++ b/scripts/stamp-release-version.js @@ -13,7 +13,7 @@ const path = require('path'); const tag = process.env.RELEASE_VERSION || ''; const version = tag.replace(/^v/, ''); // semver: X.Y.Z with an optional prerelease (10.62.0-beta.1). -if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) { +if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.test(version)) { console.error( `stamp-release-version: release tag '${tag}' is not vX.Y.Z or vX.Y.Z-prerelease` );