Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Android build

on:
workflow_call:
inputs:
ref:
type: string
required: false
push:
branches:
- main
Expand Down Expand Up @@ -28,26 +33,28 @@ jobs:
shell: bash
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Use Node.js 22.13.0
uses: actions/setup-node@v4
with:
node-version: 22.13.0
- uses: actions/setup-java@v2
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Restore yarn workspaces
id: yarn-cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- name: Install dependencies
run: yarn install
run: yarn install --frozen-lockfile
- name: Install example app dependencies
run: yarn install
run: yarn install --frozen-lockfile
working-directory: example
- name: Build android example app with new arch disabled
run: ./.github/scripts/build-android.sh false
Expand All @@ -62,26 +69,28 @@ jobs:
shell: bash
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Use Node.js 22.13.0
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 22.13.0
- uses: actions/setup-java@v2
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Restore yarn workspaces
id: yarn-cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- name: Install dependencies
run: yarn install
run: yarn install --frozen-lockfile
- name: Install example app dependencies
run: yarn install
run: yarn install --frozen-lockfile
working-directory: example
- name: Build android example app with new arch enabled
run: ./.github/scripts/build-android.sh true
19 changes: 14 additions & 5 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: iOS build

on:
workflow_call:
inputs:
ref:
type: string
required: false
push:
branches:
- main
Expand All @@ -24,6 +29,8 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Use Node.js 22.13.0
uses: actions/setup-node@v4
with:
Expand All @@ -34,9 +41,9 @@ jobs:
working-directory: example
bundler-cache: true
- name: Install dependencies
run: yarn install
run: yarn install --frozen-lockfile
- name: Install example app dependencies
run: yarn install
run: yarn install --frozen-lockfile
working-directory: example
- name: Install pods
run: RCT_NEW_ARCH_ENABLED=0 npx pod-install
Expand All @@ -48,8 +55,10 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Use Node.js 22.13.0
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 22.13.0
- uses: ruby/setup-ruby@v1
Expand All @@ -58,11 +67,11 @@ jobs:
working-directory: example
bundler-cache: true
- name: Install dependencies
run: yarn install
run: yarn install --frozen-lockfile
- name: Verify SwiftPM manifest
run: yarn jest src/__tests__/swiftpm-test.ts
- name: Install example app dependencies
run: yarn install
run: yarn install --frozen-lockfile
working-directory: example
- name: Install pods for new arch
run: RCT_NEW_ARCH_ENABLED=1 npx pod-install
Expand Down
24 changes: 21 additions & 3 deletions .github/workflows/js.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,43 @@
name: JavaScript tests

on: [push, pull_request]
on:
workflow_call:
inputs:
ref:
type: string
required: false
push:
branches:
- '**'
pull_request:

jobs:
js-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
- name: Use Node.js 22.13.0
uses: actions/setup-node@v4
with:
node-version: 22.13.0
- name: Restore yarn workspaces
id: yarn-cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- name: Install dependencies
run: yarn install
run: yarn install --frozen-lockfile
- name: Run tests
run: yarn test
- name: Test release safeguards
run: node --test scripts/*.test.mjs
- name: Build and inspect npm package
run: |
mkdir artifacts
npm pack --pack-destination artifacts
node scripts/check-package.mjs artifacts/*.tgz
108 changes: 108 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Release

on:
push:
tags:
- 'v*'

permissions:
contents: read

concurrency:
group: npm-release
cancel-in-progress: false

jobs:
package:
runs-on: ubuntu-latest
outputs:
sha: ${{ steps.candidate.outputs.sha }}
filename: ${{ steps.pack.outputs.filename }}
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
fetch-depth: 0
- name: Use the repository build runtime
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 22.13.0
package-manager-cache: false
- name: Validate candidate before native CI
id: candidate
run: |
git merge-base --is-ancestor HEAD origin/main
node scripts/check-release.mjs "$GITHUB_REF_NAME"
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- name: Enable the pinned Yarn version
run: |
corepack enable
corepack prepare yarn@1.22.22 --activate
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Test release safeguards
run: node --test scripts/*.test.mjs
- name: Build package
run: yarn build
- name: Pack and inspect
id: pack
run: |
mkdir artifacts
npm pack --ignore-scripts --pack-destination artifacts
filename=$(node -e 'const fs=require("node:fs"); const files=fs.readdirSync("artifacts").filter(f=>f.endsWith(".tgz")); if(files.length!==1) throw new Error("Expected exactly one tarball"); console.log(files[0])')
node scripts/check-package.mjs "./artifacts/$filename"
echo "filename=$filename" >> "$GITHUB_OUTPUT"
- name: Preserve verified package
uses: actions/upload-artifact@v4
with:
name: npm-package
path: artifacts/*.tgz
if-no-files-found: error
retention-days: 7

verify-javascript:
needs: package
uses: ./.github/workflows/js.yml
with:
ref: ${{ needs.package.outputs.sha }}

verify-android:
needs: package
uses: ./.github/workflows/android.yml
with:
ref: ${{ needs.package.outputs.sha }}

verify-ios:
needs: package
uses: ./.github/workflows/ios.yml
with:
ref: ${{ needs.package.outputs.sha }}

publish:
needs: [package, verify-javascript, verify-android, verify-ios]
runs-on: ubuntu-latest
environment: release
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
ref: ${{ needs.package.outputs.sha }}
- name: Use Node.js 24
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24
registry-url: https://registry.npmjs.org
package-manager-cache: false
- name: Download verified package
uses: actions/download-artifact@v4
with:
name: npm-package
path: artifacts
- name: Publish and verify with npm trusted publishing
env:
PACKAGE_FILENAME: ${{ needs.package.outputs.filename }}
run: |
node --version
npm --version
node scripts/publish-package.mjs "./artifacts/$PACKAGE_FILENAME" "${GITHUB_REF_NAME#v}"
53 changes: 53 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Release process

Pushing a `vX.Y.Z` tag starts [Release](.github/workflows/release.yml).
The workflow validates the tag, repository metadata, and packed files, then runs
JavaScript, Android, and iOS checks on the same commit. After approval of the
`release` environment, it publishes the saved tarball through npm trusted
publishing with provenance. Stable releases use `latest`; prereleases use `next`.

## Release

1. Check npm's current versions and prepare the version bump in a separate PR.
2. Merge it after review and successful CI. Local npm publishing remains disabled
in `release-it`.
3. Tag the merged commit, using the actual version in place of `X.Y.Z`:

```sh
git switch main
git pull --ff-only
node scripts/check-release.mjs vX.Y.Z
git tag -a vX.Y.Z -m 'Release X.Y.Z'
git push origin vX.Y.Z
```

4. Approve the `release` environment after checks pass. Confirm npm publication:

```sh
npm view react-native-safe-area-context@X.Y.Z version dist.integrity dist.attestations --json
npm view react-native-safe-area-context dist-tags --json
```

5. Create the GitHub release:

```sh
gh release create vX.Y.Z --verify-tag --generate-notes --title 'Release X.Y.Z'
```

Normal PR CI tests the release safeguards and inspects the package. Merging a PR
alone does not publish. Existing Android release-APK generation remains separate
and runs when the GitHub release is published.

## Recovery

- Use `gh run rerun RUN_ID --failed` to retry a failed publish with the saved
artifact, retained for seven days. Matching published versions are skipped;
integrity mismatches fail. Retrying never moves a newer dist-tag backward.
- npm processing can take several minutes. Verification polls for up to ten
minutes after acceptance. If it times out, check the exact registry version
before retrying; do not blindly republish or bump the version.
- If the artifact expired, rerun all jobs. Reruns use the original workflow
revision. Never move an already-published tag.
- For authentication failures, check the saved npm owner, repository, workflow,
environment, and direct-publish permission. For provenance failures, check the
repository URL casing in the tarball.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"format:spotless:write": "cd android && ./gradlew spotlessApply",
"format:check": "yarn format:prettier:check && yarn format:clang:check && yarn format:spotless:check",
"format:write": "yarn format:prettier:write && yarn format:clang:write && yarn format:spotless:write",
"build": "bob build",
"release": "release-it",
"prepare": "bob build"
},
Expand Down Expand Up @@ -95,7 +96,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/AppAndFlow/react-native-safe-area-context.git"
"url": "git+https://github.com/appandflow/react-native-safe-area-context.git"
},
"jest": {
"preset": "@react-native/jest-preset",
Expand Down
Loading
Loading