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
2 changes: 2 additions & 0 deletions .changeset/all-singers-arrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
16 changes: 16 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.3/schema.json",
"changelog": [
"@changesets/changelog-github",
{
"repo": "ForgeRock/ping-react-native-sdk"
}
],
"commit": false,
"fixed": [["@ping-identity/*"]],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,41 @@ jobs:
turbo_scm_head: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
secrets: inherit

# Enforce that every PR includes a changeset file.
# changeset version consumes these files on release to bump versions and write CHANGELOGs.
# Controlled by the REQUIRE_CHANGESET repo variable (Settings → Variables → Actions).
# Set REQUIRE_CHANGESET=true to enable. Leave unset or set to any other value to skip.
changeset-check:
if: github.event_name == 'pull_request' && vars.REQUIRE_CHANGESET == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: yarn install
- name: Check for changeset file
run: yarn changeset status --since=origin/main

# Detect manual version drift in package.json files.
# Fails if any @ping-identity/* package version has been edited outside of changeset version.
lockstep-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: yarn install
- name: Check lockstep versions
run: yarn release:check-lockstep

# Execute Android unit tests across affected packages.
android-unit-tests:
needs: js-unit-tests
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#
# Copyright (c) 2026 Ping Identity Corporation. All rights reserved.
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE file for details.
#
name: Release

on:
workflow_dispatch:

permissions:
contents: write
id-token: write # required for npm provenance signing

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# PAT required — GITHUB_TOKEN cannot push to a branch protected by required status checks.
# Required scopes: contents:write (to push version bump commit and tags).
# Do NOT grant repo-wide admin or workflow scopes — contents:write is sufficient.
token: ${{ secrets.GH_TOKEN }}
Comment thread
tsdamas marked this conversation as resolved.

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'

- name: Install dependencies
run: yarn install

- name: Configure git user
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Version packages
run: yarn release:version
env:
# changelog-github uses GITHUB_TOKEN to resolve PR links and author info in CHANGELOG.md
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Check lockstep
run: yarn release:check-lockstep

- name: Commit and push version bump
run: |
# Stage only the files changeset version touches — avoids accidentally
# committing build artifacts or install-state changes from yarn install.
git add packages/*/package.json packages/*/CHANGELOG.md .changeset
git commit -m "chore: version packages"
git push

- name: Build and publish
# changeset publish: publishes packages not yet at current version, creates git tags
# NPM_CONFIG_PROVENANCE links each package to this workflow run and source commit
run: yarn release:publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true

- name: Push tags
# Tags are created by changeset publish — push them after publish succeeds
run: git push --follow-tags
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ android/build/
ios/build/
ios/Pods/
ios/DerivedData/
DerivedData/

# IDEs
.vscode/
Expand All @@ -24,6 +25,7 @@ ios/DerivedData/

# Misc
*.jks
*.xcresult
coverage/
docs/
classes.jar
Expand Down
Binary file modified .yarn/install-state.gz
Binary file not shown.
93 changes: 93 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,99 @@ The root `package.json` contains scripts for common tasks:
- `yarn test:device-id`: run device-id package tests.
- `yarn test:device-profile`: run device-profile package tests.

### Release Process

This repo uses [Changesets](https://github.com/changesets/changesets) for versioning and publishing. All 9 `@ping-identity/*` SDK packages are versioned and published together (lockstep) on every release.

#### How it works

```mermaid
sequenceDiagram
participant Dev as Developer
participant Main as main branch
participant npm as npm registry

Note over Dev: work on feature #1
Dev->>Dev: yarn changeset (pick bump + description)
Dev->>Main: PR #1 merged (.changeset/abc.md)

Note over Dev: work on feature #2
Dev->>Dev: yarn changeset (pick bump + description)
Dev->>Main: PR #2 merged (.changeset/def.md)

Note over Dev: work on feature #3
Dev->>Dev: yarn changeset (pick bump + description)
Dev->>Main: PR #3 merged (.changeset/ghi.md)

Note over Main: changeset files accumulate<br/>nothing published yet

Dev->>Main: trigger workflow_dispatch

Note over Main: changeset version<br/>• all 9 packages → 0.1.1<br/>• CHANGELOG.md written<br/>• .changeset/*.md deleted<br/>• version bump committed

Main->>npm: changeset publish
Note over npm: @ping-identity/rn-* @ 0.1.1<br/>git tags created
```

#### Every PR must include a changeset file

Before opening a PR, run:

```sh
yarn changeset
```

The CLI will prompt you to select a bump type (`patch`, `minor`, or `major`) and write a short description of your change. This creates a `.changeset/xyz.md` file — commit it with your PR.

The changeset description becomes the entry in each package's `CHANGELOG.md` on the next release, linked to your PR and commit SHA. CI will fail if no changeset file is present.

**Bump type guidance:**
- `patch` — bug fixes, non-breaking internal changes
- `minor` — new backwards-compatible features
- `major` — breaking API changes

If your PR does not affect any published package (e.g. CI config changes, documentation edits, test-only changes), run:

```sh
yarn changeset --empty
```

This creates a changeset file with no version bump, satisfying the CI check without affecting the next release version.

#### Releases are triggered manually

Releases do **not** happen automatically on merge. Changeset files accumulate in `.changeset/` until a maintainer is ready to ship.

To release, trigger the [Release workflow](../../actions/workflows/release.yml) via `workflow_dispatch` in GitHub Actions. It will:

1. Bump all 9 packages to the same next version
2. Write `CHANGELOG.md` entries from accumulated changeset files
3. Commit the version bump to `main`
4. Publish to npm
5. Create git tags

**Why `workflow_dispatch` instead of the Changesets bot?**
We deliberately chose manual `workflow_dispatch` instead of the Changesets GitHub bot because:
- This is an early-stage SDK where releases should be deliberate, not automatic
- It avoids a permanently-open "Release PR" that creates pressure to ship before the team is ready
- One explicit button-push makes the release boundary clear

We can adopt the bot pattern later once release cadence is established.

#### Checking release status

To see what version would be released from current pending changesets:

```sh
yarn release:status
```

To verify all packages are at the same version (catches accidental manual edits):

```sh
yarn release:check-lockstep
```

### Sending A Pull Request

When you are sending a pull request:
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@
"docs:journey": "typedoc --options typedoc.journey.json",
"prettier": "turbo run prettier",
"typecheck": "turbo run typecheck",
"postinstall": "lefthook install"
"postinstall": "lefthook install",
"release:status": "changeset status",
"release:version": "changeset version",
"release:publish": "yarn packages:build && changeset publish",
"release:check-lockstep": "node scripts/check-lockstep.mjs"
},
"workspaces": {
"packages": [
Expand All @@ -61,6 +65,8 @@
]
},
"devDependencies": {
"@changesets/changelog-github": "^0.6.0",
"@changesets/cli": "^2.30.0",
"@eslint/compat": "^2.0.5",
"@eslint/js": "^10.0.1",
"@react-native/codegen": "^0.82.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"typescript": "^5.9.2"
},
"dependencies": {
"@ping-identity/rn-core": "^0.1.0",
"@ping-identity/rn-types": "^0.1.0"
"@ping-identity/rn-core": "workspace:*",
"@ping-identity/rn-types": "workspace:*"
},
"react-native-builder-bob": {
"source": "src",
Expand Down
4 changes: 2 additions & 2 deletions packages/device-id/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"prettier": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\""
},
"dependencies": {
"@ping-identity/rn-core": "^0.1.0",
"@ping-identity/rn-types": "^0.1.0"
"@ping-identity/rn-core": "workspace:*",
"@ping-identity/rn-types": "workspace:*"
},
"peerDependencies": {
"react": "*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ final class RNPingDeviceProfileCommonTests: XCTestCase {
}
)

wait(for: [expectation], timeout: 2)
// This path executes multiple real collectors and can exceed 2s under
// parallel simulator load in CI.
wait(for: [expectation], timeout: 5)
}

func testCollectDeviceProfileDeduplicatesDuplicateCollectors() {
Expand Down
4 changes: 2 additions & 2 deletions packages/device-profile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
"android"
],
"dependencies": {
"@ping-identity/rn-core": "^0.1.0",
"@ping-identity/rn-types": "^0.1.0"
"@ping-identity/rn-core": "workspace:*",
"@ping-identity/rn-types": "workspace:*"
},
"peerDependencies": {
"react": "*",
Expand Down
4 changes: 2 additions & 2 deletions packages/journey/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"clean": "rimraf lib"
},
"dependencies": {
"@ping-identity/rn-core": "^0.1.0",
"@ping-identity/rn-types": "^0.1.0"
"@ping-identity/rn-core": "workspace:*",
"@ping-identity/rn-types": "workspace:*"
},
"peerDependencies": {
"react": "*",
Expand Down
4 changes: 2 additions & 2 deletions packages/logger/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
},
"dependencies": {
"@forgerock/sdk-logger": "^1.3.0",
"@ping-identity/rn-core": "^0.1.0",
"@ping-identity/rn-types": "^0.1.0"
"@ping-identity/rn-core": "workspace:*",
"@ping-identity/rn-types": "workspace:*"
},
"peerDependencies": {
"react": "*",
Expand Down
4 changes: 2 additions & 2 deletions packages/oidc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"typescript": "^5.9.2"
},
"dependencies": {
"@ping-identity/rn-core": "^0.1.0",
"@ping-identity/rn-types": "^0.1.0"
"@ping-identity/rn-core": "workspace:*",
"@ping-identity/rn-types": "workspace:*"
},
"react-native-builder-bob": {
"source": "src",
Expand Down
4 changes: 2 additions & 2 deletions packages/storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"prettier": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\""
},
"dependencies": {
"@ping-identity/rn-core": "^0.1.0",
"@ping-identity/rn-types": "^0.1.0"
"@ping-identity/rn-core": "workspace:*",
"@ping-identity/rn-types": "workspace:*"
},
"peerDependencies": {
"react": "*",
Expand Down
9 changes: 9 additions & 0 deletions scripts/check-copyright.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ has_copyright_header() {
head -"$HEADER_SEARCH_LINES" "$file_path" | grep -qiE "$COPYRIGHT_PATTERN"
}

# Returns 0 (true) if the given file should be excluded from validation.
# Changesets must start with frontmatter and therefore cannot include a
# leading copyright header.
should_skip_file() {
local file_path="$1"
[[ "$file_path" == .changeset/*.md || "$file_path" == ./.changeset/*.md ]]
}

# Prints a formatted error listing all files missing the copyright header
# and exits with a non-zero code to abort the commit.
report_missing_and_fail() {
Expand All @@ -57,6 +65,7 @@ main() {

for file_path in "${staged_files[@]}"; do
file_exists "$file_path" || continue
should_skip_file "$file_path" && continue
has_copyright_header "$file_path" || missing_files+=("$file_path")
done

Expand Down
Loading
Loading