Skip to content

ci: publish to npm automatically from CI - #1225

Open
Naturalclar wants to merge 2 commits into
masterfrom
claude/init-yfdkki
Open

ci: publish to npm automatically from CI#1225
Naturalclar wants to merge 2 commits into
masterfrom
claude/init-yfdkki

Conversation

@Naturalclar

Copy link
Copy Markdown
Member

Overview

Implements #1223. Releases move from a manual local operation to a CI workflow.

Today a release means a maintainer running yarn release with npm credentials on hand. Every published release is authored by one person, and master currently carries four releasable commits since v2.0.0 that have never reached npm — feat(ios): preferredElementSize (#1202) plus three fix: commits.

The release tooling itself was already configured; only the automation was missing. This PR does not change how versions or changelogs are produced.

.github/workflows/release.yml

Triggers on the Build workflow completing on master and runs the existing release-it configuration if Build passed. Using workflow_run means the gate is exact — lint, tsc, android, and both iOS builds must be green before anything is published — and it builds on the push trigger fixed in #1224.

Version and release notes still come from @release-it/conventional-changelog, so the output matches the current manual release. The bump is decided entirely by commit messages: fix:/perf: → patch, feat: → minor, ! or a BREAKING CHANGE: footer → major.

Two guards:

  • Unvalidated commits are never published. If master has moved past the commit Build validated, the run skips instead of shipping code CI never checked. The next green Build picks it up.
  • A release cannot trigger another release. The chore: release <version> commit that release-it pushes is ignored.

A push whose commits are all chore/docs/test/refactor stops before touching npm, since the angular preset would produce no bump.

Authentication uses an NPM_TOKEN repository secret, read through the .npmrc that actions/setup-node writes. GITHUB_TOKEN with contents: write covers the release commit, tag, and GitHub release.

Release can also be dispatched manually for a release that failed partway through. That path skips the Build gate by design and is documented as such.

Gradle heap bump

Separate commit, and a prerequisite rather than an unrelated drive-by. The android job fails intermittently — roughly half of recent runs — during dependency resolution:

Failed to transform react-android-0.81.1-debug.aar
  > Execution failed for JetifyTransform: .../react-android-0.81.1-debug.aar
     > Java heap space

It failed on #1222's first attempt and on the master push run after #1224 merged, and passed on #1222's re-run and on #1224. Since publishing is gated on a green Build, a job that fails half the time blocks releases half the time. -Xmx2g is no longer enough for the Jetifier transform; ubuntu runners have ample memory.

Before the first release

An npm access token with publish rights on @react-native-menu/menu must be added as an NPM_TOKEN repository secret. Without it the workflow runs and fails at the publish step.

Two things worth checking:

  • Branch protection. release-it pushes the release commit and tag directly to master. If master requires pull requests or status checks for pushes, GITHUB_TOKEN will be rejected and the release will fail after publishing to npm, leaving npm and git out of sync.
  • Commit messages are now load-bearing. With release-on-merge, a feat mislabelled as chore silently ships nothing. CONTRIBUTING.md states that pre-commit hooks verify the format, but no husky, lefthook, or commitlint configuration exists in the repo — so squash-merge titles are what actually decide the version. This is documented rather than enforced; wiring up commitlint would be a separate change.

Test Plan

A workflow_run trigger only fires from the workflow file on the default branch, so this workflow cannot execute before merge. The first merge to master is the real test. What was verified instead:

  • The release guard was run against real history, not eyeballed. On the current master it resolves git describe --tags --abbrev=0 to v2.0.0, walks v2.0.0..HEAD, and finds exactly 4 releasable commits — the 1 feat and 3 fix listed above — which is a minor bump. Re-running it after a release would find 0 and skip.
  • The guard's regex requires colon-space, matching conventional-changelog's own header parser, so the guard and release-it agree on what counts as releasable. (Note this means a historical subject like fix:lint error would be skipped by both, consistently.)
  • release.yml was parsed as YAML to confirm it is well formed.
  • The Jetifier OOM was read from the failing job logs of run 31983633654 (the master push run) and cross-checked against the same failure on docs: add CLAUDE.md with build commands and architecture overview #1222, confirming it happens in :app:checkDebugAarMetadata during dependency transform, before any project code compiles.
  • yarn lint could not be run — dependencies are not installed in this environment. Biome 1.9.4 covers JS/TS/JSON, and this diff is YAML, Markdown, and a .properties file, so it is outside Biome's scope regardless. The lint job on this PR confirms it.

The android job on this PR is the first check of the heap bump; if it passes here and on subsequent runs, the OOM is addressed.


Generated by Claude Code

claude added 2 commits August 17, 2026 01:30
The android job fails intermittently — roughly half of recent runs — while
Jetifier rewrites react-android-0.81.1-debug.aar:

    Failed to transform react-android-0.81.1-debug.aar
      > Execution failed for JetifyTransform: .../react-android-0.81.1-debug.aar
         > Java heap space

The failure happens during dependency resolution, before any project code is
compiled, and is unrelated to whatever change is under test. 2g is no longer
enough for the transform; ubuntu runners have ample memory.

This matters beyond the flake itself: publishing is gated on a green Build, so
an intermittently red android job intermittently blocks releases.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWYKHSVSNoLM8Hquum8CuD
Releases were a manual, local operation: a maintainer ran `yarn release` with
npm credentials on hand. Every published release is authored by one person, and
master has carried four releasable commits since v2.0.0 without them reaching
npm.

Add a Release workflow that runs the existing release-it configuration in CI.
It triggers on the Build workflow completing on master and releases only if
Build passed, so publishing is gated on lint, tsc, and the Android/iOS builds.
Version and changelog still come from @release-it/conventional-changelog, so
output matches the current manual release.

Two guards keep it honest:

- If master has moved past the commit Build validated, the run skips rather
  than publishing code CI never checked. The next green Build picks it up.
- The `chore: release` commit release-it pushes is ignored, so a release
  cannot trigger another release.

A run whose commits are all chore/docs/test/refactor stops before touching npm,
since the angular preset would produce no version bump.

Authentication uses an NPM_TOKEN repository secret, read via the .npmrc that
actions/setup-node writes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWYKHSVSNoLM8Hquum8CuD
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.

2 participants