Skip to content

ci: publish npm packages through ESRP#3041

Draft
Saadnajmi wants to merge 2 commits into
microsoft:mainfrom
Saadnajmi:esrp-npm-publish-main
Draft

ci: publish npm packages through ESRP#3041
Saadnajmi wants to merge 2 commits into
microsoft:mainfrom
Saadnajmi:esrp-npm-publish-main

Conversation

@Saadnajmi

@Saadnajmi Saadnajmi commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Migrate the Azure DevOps npm release path from token-based yarn npm publish to
Microsoft ESRP while preserving the original RNM publishing shape.

  • Keep one original-style NPM stage and the existing
    .ado/jobs/npm-publish.yml template.
  • Pack dynamically discovered public workspaces in a normal job, then consume
    the pipeline artifact from a dependent 1ES production release job in the
    same stage.
  • Replace PowerShell release checks with directly invoked Node/TypeScript
    helpers.
  • Add a manual dryRun parameter, default false, that still packs, filters,
    and validates onboarding while preventing EsrpRelease@11.
  • Use one npm tag per release line and remove npm-token/additional-tag handling.

Original-contract build behavior

The parent publish job ran yarn install, release configuration, and workspace
yarn npm publish. It did not run root yarn build or yarn build-types.

The revised pack job therefore runs only:

yarn workspaces foreach --all --topological --no-private run build

This preserves RNM's original package contents while building
react-native-macos-init, whose existing package contract expects generated
CommonJS output.

Corrected package parity

Earlier PR evidence incorrectly treated
450d3dd494b8db00d706f908cc952d8bee147a77e055ad5ba4f6d207d5685210
as the canonical RNM tarball. That artifact was contaminated by an extra
yarn build-types step that the original publish job never ran.

Clean Node 22.22.0/Yarn 4.12.0 reproductions on both main and 0.83 establish the
original-contract hashes:

  • react-native-macos:
    73c592e775d773d246d7a9c7dc3569012d3a5e29b7d62f7857cf8a2c9e02d558
  • react-native-macos-init:
    546371a1931e2a54891afb836b14d3d7f58b28c538a4d6f9a6b5b60d7cbfe7de

Original and revised RNM tarballs are byte-identical. Their extracted contents,
modes, manifests, tar headers, and member order also match. Both clean runs
contain zero package/types_generated/ entries.

Two additional independent clean main reproductions produced the same RNM
bytes, proving the hash does not depend on retained generated state.

The stale 450d... artifact differs only by 230 generated declaration files:
all 4,365 common members are content- and metadata-identical. The published
react-native-macos@0.81.9 tarball independently contains zero
package/types_generated/ entries among 4,194 members, corroborating the
original published contract.

Release behavior

  • Main remains a no-op because nightly publishing is disabled.
  • Current/latest and promoted release lines publish with latest.
  • Older stable lines publish with their branch/minor stable tag.
  • Release candidates publish with next.
  • Already-published exact package versions are removed before ESRP, making
    partial retries idempotent.
  • Missing, blank, or unexpanded ESRP onboarding variables fail before release
    without logging secret values.
  • dryRun: true runs pack, registry filtering, and onboarding validation but
    cannot execute EsrpRelease@11.

Validation

  • 10 focused Node tests passed.
  • Targeted Prettier, ESLint, direct TypeScript, YAML parsing, changeset status,
    and git diff --check passed.
  • Static pipeline checks prove one NPM stage, NpmPack followed by
    NpmEsrpRelease, default dryRun: false, and an ESRP condition requiring
    both unpublished packages and dryRun: false.
  • The revised release path contains no PowerShell, npm token, additional-tag,
    root-build, or build-types path.
  • Main no-op, empty filtering, populated onboarding, missing onboarding, and
    value-safe onboarding errors were exercised directly.
  • Full closed 1ES expansion cannot be run outside Microsoft's private pipeline
    environment; the same-stage release-job artifact shape follows existing
    public 1ES pipeline precedents.

Follow-up rollout

After independent review and main landing, backport this commit directly to
0.83-stable. Recreate the 0.84-0.87 release stack so those branches inherit
the main change once through ancestry rather than duplicate cherry-picks.

Saadnajmi and others added 2 commits July 20, 2026 20:28
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the original single-stage npm publishing shape, replace PowerShell release checks with Node helpers, and add a safe manual dry-run gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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