diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 75321a6..5066b77 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,23 +1,6 @@ name: Release on: - workflow_dispatch: - inputs: - release_tag: - description: 'Existing release tag to publish (leave empty for a dry run)' - required: false - type: string - pull_request: - branches: - - main - paths: - - '.github/actions/setup/**' - - '.github/workflows/ci.yml' - - '.github/workflows/release.yml' - - 'package.json' - - 'scripts/check-package.mjs' - - 'scripts/check-release.mjs' - - 'tsconfig.build.json' push: tags: - 'v*' @@ -31,32 +14,24 @@ concurrency: jobs: verify: - if: github.event_name != 'pull_request' uses: ./.github/workflows/ci.yml package: needs: verify - if: >- - always() && - (github.event_name == 'pull_request' || needs.verify.result == 'success') runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.0.0 with: fetch-depth: 0 - ref: ${{ inputs.release_tag || github.ref }} - name: Setup uses: ./.github/actions/setup - name: Validate release tag - if: github.event_name == 'push' || inputs.release_tag != '' - env: - RELEASE_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.release_tag }} run: | git merge-base --is-ancestor HEAD origin/main - node scripts/check-release.mjs "$RELEASE_TAG" + node scripts/check-release.mjs "$GITHUB_REF_NAME" - name: Build package run: yarn build @@ -73,12 +48,9 @@ jobs: name: npm-package path: artifacts/*.tgz if-no-files-found: error - retention-days: 1 + retention-days: 7 publish: - if: >- - (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) || - (github.event_name == 'workflow_dispatch' && inputs.release_tag != '') needs: package runs-on: ubuntu-latest environment: release @@ -101,13 +73,11 @@ jobs: - name: Publish with npm trusted publishing shell: bash - env: - RELEASE_TAG: ${{ github.event_name == 'push' && github.ref_name || inputs.release_tag }} run: | set -euo pipefail package_name=react-native-ease - version="${RELEASE_TAG#v}" + version="${GITHUB_REF_NAME#v}" tarball="./artifacts/$package_name-$version.tgz" dist_tag=latest if [[ "$version" == *-* ]]; then dist_tag=next; fi @@ -137,7 +107,7 @@ jobs: npm publish "$tarball" --provenance --access public --tag "$dist_tag" - for attempt in {1..12}; do + for attempt in {1..60}; do if npm view "$package_name@$version" version dist.integrity --json > "$registry_file" && npm view "$package_name" "dist-tags.$dist_tag" --json > "$RUNNER_TEMP/dist-tag.json" && node -e ' @@ -158,5 +128,5 @@ jobs: sleep 10 done - echo "Registry verification failed." >&2 + echo "npm accepted publication, but registry verification is still pending. Check the exact version before retrying with the saved artifact." >&2 exit 1 diff --git a/RELEASE.md b/RELEASE.md index ef37f59..2e1a1d2 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -4,27 +4,6 @@ This repository publishes one npm package, `react-native-ease`. The example and documentation site are not published to npm. Keep this document aligned with [the Release workflow](.github/workflows/release.yml). -## One-time trusted-publisher setup - -Configure a GitHub Actions trusted publisher in the npm package settings: - -| Field | Value | -| ----------------- | ------------------------------------ | -| Organization | `appandflow` | -| Repository | `react-native-ease` | -| Workflow filename | `release.yml` | -| Environment | `release` | -| Allowed action | Direct publishing with `npm publish` | - -The workflow uses npm's OpenID Connect integration and does not need an npm -write token. It publishes with Node 24 and npm provenance. See -[npm's trusted publishing guide](https://docs.npmjs.com/trusted-publishers/). - -Create the GitHub `release` environment, require a maintainer review, and limit -deployment tags to `v*`. Declaring the environment in the workflow does not -create its protection rules, and the npm trust relationship must also be -configured separately. - ## Prepare and verify a candidate Start from reviewed, current `main`. Check npm before choosing a version; a Git @@ -57,15 +36,6 @@ node scripts/check-release.mjs vX.Y.Z CI also builds the Android, iOS, and tvOS examples. Device behavior affected by the release still needs device validation. -After this workflow has been merged into the default branch, use **Actions → -Release → Run workflow** with `release_tag` empty for a publication-free -integration test. The manual run executes the full reusable CI workflow, builds -and validates the npm tarball, and uploads it as a one-day workflow artifact. - -The dry run cannot test npm's OIDC trust relationship because npm authenticates -the workflow only when `npm publish` runs. Use the first intentional prerelease -to validate trusted publishing end to end. - ## Tag and publish 1. Run `yarn release X.Y.Z` from current `main`. `release-it` creates the release @@ -93,17 +63,18 @@ move a newer dist-tag backward. - If authentication fails, verify the npm publisher's organization, repository, workflow filename, and environment. Do not add a long-lived npm token as a workaround. -- If validation fails before publication, fix the issue on `main` and prepare a - new version. Never move a pushed release tag. -- If a publish is interrupted, query the exact npm version before retrying. The - workflow refuses registry errors other than a real missing-version response. - If the tagged workflow itself needs a fix, merge the fix to `main`, then run - the Release workflow manually with the existing tag in `release_tag`. It - checks out and validates that immutable tag before publishing its exact package. -- npm versions cannot be overwritten. Publish a new version for any correction. -- Do not rerun an old release to change `latest` or `next` after a newer release - has advanced that dist-tag. - -Adding this workflow does not publish anything. npm publication begins only when -a matching release tag is pushed, or supplied explicitly as `release_tag` to a -manual recovery run, and the protected environment is approved. +- Retry a failed publish with `gh run rerun RUN_ID --failed`. This reuses the + inspected tarball, retained for seven days, without repeating native CI. +- npm processing can take several minutes. The workflow allows approximately + ten minutes for verification after acceptance. If verification times out, + inspect the exact npm version before retrying with the same artifact. +- If the artifact has expired, rerun all jobs. A rerun uses the original workflow + revision, including its checkout and scripts. Merging a workflow fix does not + update an existing run. +- Never move an already-published tag. npm versions cannot be overwritten; + publish a new version for corrections to a published package. +- An existing version is skipped only when its integrity matches the saved + tarball. This does not change `latest` or `next`. + +Adding this workflow does not publish anything. Publication requires a matching +`v*` tag push, successful CI, and approval of the protected release environment.