Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
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
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