diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 15dcf5f..5ca31d5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,6 +32,15 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 + # Admin PAT (repo secret GH_TOKEN) so @semantic-release/git can push the + # version + CHANGELOG commit past main's branch protection — same pattern + # as invertase/react-native-google-mobile-ads and react-native-firebase. + token: ${{ secrets.GH_TOKEN }} + + - name: Git identity for the release commit + run: | + git config user.name 'Invertase Publisher' + git config user.email 'oss@invertase.io' - name: Setup uses: ./.github/actions/setup @@ -49,8 +58,14 @@ jobs: - name: Release run: yarn semantic-release env: - # Default Actions token is enough for tags/releases when contents:write. + # Admin PAT (repo secret) for both GitHub Releases AND the + # @semantic-release/git commit-back push past branch protection. # No NPM_TOKEN: OIDC trusted publishing after first human publish + Trusted Publisher setup. - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} # Avoid setup-node writing an .npmrc that breaks OIDC (semantic-release docs). NPM_CONFIG_PROVENANCE: 'true' + # @semantic-release/npm runs `npm version`; in a Yarn workspaces monorepo + # npm cannot parse `workspace:` protocols when relinking. Only bump the + # version field. (Matches RNGMA's publish workflow.) + npm_config_workspaces_update: 'false' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..44349e5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,46 @@ +# Changelog + +All notable changes to this project are documented here. + +This file is maintained by [semantic-release](https://github.com/semantic-release/semantic-release): +each entry is generated from [Conventional Commits](https://www.conventionalcommits.org/) and +corresponds to a published npm version, a `v*` git tag, and a GitHub Release. + +> The `0.1.0`–`0.2.1` sections below were reconstructed retroactively from git history and the +> existing GitHub Releases (this file was added after the fact). Entries from `0.2.2` onward are +> written automatically by `@semantic-release/changelog` at release time. + +## [0.2.1](https://github.com/invertase/react-native-coverage/compare/v0.2.0...v0.2.1) (2026-09-18) + +### Bug Fixes + +* **ci:** root JS coverage instrumentation at the workspace ([52b6c18](https://github.com/invertase/react-native-coverage/commit/52b6c18a9489b0b7965639ecceea29f90e2a26e4)) +* launch prebuilt WDA via xcodebuild instead of simctl ([d372d20](https://github.com/invertase/react-native-coverage/commit/d372d20eedf04ef8be3a797d60db1a3319f2d18d)) +* pin Appium to the xcodebuild product and always reinstall ([8b71e56](https://github.com/invertase/react-native-coverage/commit/8b71e56ce2b7ded5cbc490fec7d136d24c6807d5)) +* recover Expo pod lock drift and pin json 2.21.2 ([7533c89](https://github.com/invertase/react-native-coverage/commit/7533c89ba619166c4b798077e9f022a582a559b4)) +* take the expected Expo 57.0.24 patch ([a64dd6c](https://github.com/invertase/react-native-coverage/commit/a64dd6c2a451d998b220f2085995fd8718ba85ed)) +* treat already-installed Appium drivers as success ([d4fd00b](https://github.com/invertase/react-native-coverage/commit/d4fd00b5fe9b6b468698abe8fa0a461b2bbaa46b)) + +## [0.2.0](https://github.com/invertase/react-native-coverage/compare/v0.1.0...v0.2.0) (2026-09-02) + +> **Note:** `0.2.0` was a trusted-publishing smoke test and carries no user-facing changes over +> `0.1.0`. The commit that triggered it was typed `feat:` and so burned a real minor; infrastructure +> and publishing tests should use `chore:`/`test:` to avoid consuming a version. + +### Features + +* trusted publish commit test ([4b8b717](https://github.com/invertase/react-native-coverage/commit/4b8b717df2d6ad7b49063479626b5fdd8f963a12)) + +## 0.1.0 (2026-09-02) + +Initial public release. + +### Features + +* add JS/TS coverage with Istanbul, NYC remap, and Codecov ([4c39e09](https://github.com/invertase/react-native-coverage/commit/4c39e09c39bf997491de00cb04bb67802fb7329e)) +* add manual semantic-release and commitlint scaffolding ([309e307](https://github.com/invertase/react-native-coverage/commit/309e30792edc4e1d103a2f065f6e1f3b811a28a3)) +* add Appium e2e CI for dynamic and static iOS cells ([6304bb1](https://github.com/invertase/react-native-coverage/commit/6304bb158216408f7c23541433c6c731cad5fd53)) +* wire Expo Gradle and CocoaPods coverage build helpers ([ad4250d](https://github.com/invertase/react-native-coverage/commit/ad4250de64ec0193da8dbfb82842c358e21f816a)) +* port native TurboModule coverage flushers and fixture lib ([22d8918](https://github.com/invertase/react-native-coverage/commit/22d8918b18b3ecac0dfd32fb19186ba0c03c8a30)) +* **cli:** add full coverage CLI with strict exit 2 ([3f6f2cf](https://github.com/invertase/react-native-coverage/commit/3f6f2cfb594200d1ccf3fb592ec2801b2d6e3bc5)) +* scaffold react-native-coverage package and tooling ([2314f9a](https://github.com/invertase/react-native-coverage/commit/2314f9aa708c7f9ea8ea46748266506878650770)) diff --git a/docs/releasing.mdx b/docs/releasing.mdx index e649433..3f95ac1 100644 --- a/docs/releasing.mdx +++ b/docs/releasing.mdx @@ -59,7 +59,29 @@ Examples: `feat: …`, `fix: …`, `docs: …`, `chore: …`. Breaking changes: | Workflow | `.github/workflows/release.yml` (`workflow_dispatch` only) | | Analyzer | Conventional Commits via `@semantic-release/commit-analyzer` | | Publish | `@semantic-release/npm` + `@semantic-release/github` | -| **Not used** | `@semantic-release/git` — dropped so releases do not need a bot push past branch protection; version tags + GitHub Releases carry the release, not in-repo `package.json` bumps | +| Changelog | `@semantic-release/changelog` prepends generated notes to `CHANGELOG.md` | +| Commit back | `@semantic-release/git` commits the bumped `package.json` + `CHANGELOG.md` and tags **that** commit | + +### Branch protection and the commit-back step + +`@semantic-release/git` pushes the release commit to `main`, which is branch-protected. The +default `GITHUB_TOKEN` cannot bypass required pull requests, so the release fails at the git +step unless the workflow runs with a privileged token. + +**Setup (one-time, repo admin):** add a repository secret **`GH_TOKEN`** = an admin +Personal Access Token with `repo` scope, owned by a user allowed to bypass `main`'s protection. +The `release.yml` workflow already consumes it (on `actions/checkout` and as `GH_TOKEN` / +`GITHUB_TOKEN` for `semantic-release`). This mirrors how +[`react-native-google-mobile-ads`](https://github.com/invertase/react-native-google-mobile-ads/blob/main/.github/workflows/publish.yml) +(semantic-release) and +[`react-native-firebase`](https://github.com/invertase/react-native-firebase/blob/main/.github/workflows/publish.yml) +(Lerna) do it — both carry `GH_TOKEN` as a **repo secret**. + +The commit message carries `[skip ci]` so the pushed release commit does not re-trigger CI. + +Because tags now point at the release commit (not the source commit), a checkout at any `v*` +tag has a truthful `package.json` and `CHANGELOG.md`. **Never delete a released tag** — it is +still the source of truth for the next version calculation. Dry-run (no publish; needs network + git history): diff --git a/package.json b/package.json index 7f9f2bd..0e138b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-coverage", - "version": "0.1.0", + "version": "0.2.1", "description": "Native code coverage tooling for React Native (TurboModule + CLI + Expo config plugin)", "main": "./lib/module/index.js", "types": "./lib/typescript/src/index.d.ts", @@ -99,7 +99,9 @@ "@eslint/js": "^9.39.4", "@react-native/babel-preset": "0.86.3", "@react-native/eslint-config": "0.86.3", + "@semantic-release/changelog": "^6.0.3", "@semantic-release/commit-analyzer": "^13.0.1", + "@semantic-release/git": "^10.0.1", "@semantic-release/github": "^12.0.0", "@semantic-release/npm": "^13.1.1", "@semantic-release/release-notes-generator": "^14.1.0", diff --git a/release.config.js b/release.config.js index 29fe26f..dc8957f 100644 --- a/release.config.js +++ b/release.config.js @@ -1,11 +1,15 @@ /** - * semantic-release config (release bootstrap). + * semantic-release config. * * - Manual publish only via workflow_dispatch (see .github/workflows/release.yml). - * - No @semantic-release/git: under branch protection the git plugin needs a - * privileged token to push version bumps; prefer tags + GitHub Releases only. * - npm OIDC trusted publishing is configured after the human first publish. * This config is ready for OIDC (no NPM_TOKEN required once trusted publisher is set). + * - @semantic-release/git commits the version bump + CHANGELOG back to `main` and + * tags THAT commit, so a checkout at any tag has a truthful `package.json` and + * `CHANGELOG.md`. Because `main` is branch-protected, the release workflow must run + * with a token allowed to bypass protection (a GitHub App/PAT, or an "allow + * specified actors to bypass required pull requests" rule for the release bot). + * The `[skip ci]` in the commit message keeps that push from re-triggering CI. */ module.exports = { branches: ['main'], @@ -22,7 +26,20 @@ module.exports = { preset: 'conventionalcommits', }, ], + // Prepend the generated notes to CHANGELOG.md before npm bumps the version. + '@semantic-release/changelog', + // Bumps package.json version in the published tarball. '@semantic-release/npm', + // Creates the GitHub Release from the generated notes. '@semantic-release/github', + // MUST be last: commits the files the previous steps modified, then tags it. + [ + '@semantic-release/git', + { + assets: ['package.json', 'CHANGELOG.md'], + message: + 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}', + }, + ], ], }; diff --git a/yarn.lock b/yarn.lock index a810efc..900ca0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5053,6 +5053,20 @@ __metadata: languageName: node linkType: hard +"@semantic-release/changelog@npm:^6.0.3": + version: 6.0.3 + resolution: "@semantic-release/changelog@npm:6.0.3" + dependencies: + "@semantic-release/error": "npm:^3.0.0" + aggregate-error: "npm:^3.0.0" + fs-extra: "npm:^11.0.0" + lodash: "npm:^4.17.4" + peerDependencies: + semantic-release: ">=18.0.0" + checksum: 10c0/94c9c287d34fde6d4c6c574869e853dc04180b1d9e6036097d83e0d14783bf5bb8e546fdc4fac2e979d636fa170fd573eaa4265b9d332e436e4813b7aebe7728 + languageName: node + linkType: hard + "@semantic-release/commit-analyzer@npm:^13.0.1": version: 13.0.1 resolution: "@semantic-release/commit-analyzer@npm:13.0.1" @@ -5071,6 +5085,13 @@ __metadata: languageName: node linkType: hard +"@semantic-release/error@npm:^3.0.0": + version: 3.0.0 + resolution: "@semantic-release/error@npm:3.0.0" + checksum: 10c0/51f06d11186a6efc543b44996ca1c368a77c6ed18dd823f0362188c37b7ef32f3580bd17654f594e6a72b931ebe69b44bbcb1ee16c755a1d3e44dcb652b47275 + languageName: node + linkType: hard + "@semantic-release/error@npm:^4.0.0": version: 4.0.0 resolution: "@semantic-release/error@npm:4.0.0" @@ -5078,6 +5099,24 @@ __metadata: languageName: node linkType: hard +"@semantic-release/git@npm:^10.0.1": + version: 10.0.1 + resolution: "@semantic-release/git@npm:10.0.1" + dependencies: + "@semantic-release/error": "npm:^3.0.0" + aggregate-error: "npm:^3.0.0" + debug: "npm:^4.0.0" + dir-glob: "npm:^3.0.0" + execa: "npm:^5.0.0" + lodash: "npm:^4.17.4" + micromatch: "npm:^4.0.0" + p-reduce: "npm:^2.0.0" + peerDependencies: + semantic-release: ">=18.0.0" + checksum: 10c0/90077068b97ff894e5f6bea05d0c7482929d3bae64c242a1556bc85db4d8f0a52b71215300472539b95248778cdf239a3f8cbad5effaaba719a32bf347dbdd93 + languageName: node + linkType: hard + "@semantic-release/github@npm:^12.0.0": version: 12.0.9 resolution: "@semantic-release/github@npm:12.0.9" @@ -9173,7 +9212,7 @@ __metadata: languageName: node linkType: hard -"dir-glob@npm:^3.0.1": +"dir-glob@npm:^3.0.0, dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" dependencies: @@ -14812,7 +14851,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -16150,6 +16189,13 @@ __metadata: languageName: node linkType: hard +"p-reduce@npm:^2.0.0": + version: 2.1.0 + resolution: "p-reduce@npm:2.1.0" + checksum: 10c0/27b8ff0fb044995507a06cd6357dffba0f2b98862864745972562a21885d7906ce5c794036d2aaa63ef6303158e41e19aed9f19651dfdafb38548ecec7d0de15 + languageName: node + linkType: hard + "p-reduce@npm:^3.0.0": version: 3.0.0 resolution: "p-reduce@npm:3.0.0" @@ -17169,7 +17215,9 @@ __metadata: "@eslint/js": "npm:^9.39.4" "@react-native/babel-preset": "npm:0.86.3" "@react-native/eslint-config": "npm:0.86.3" + "@semantic-release/changelog": "npm:^6.0.3" "@semantic-release/commit-analyzer": "npm:^13.0.1" + "@semantic-release/git": "npm:^10.0.1" "@semantic-release/github": "npm:^12.0.0" "@semantic-release/npm": "npm:^13.1.1" "@semantic-release/release-notes-generator": "npm:^14.1.0"