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
157 changes: 72 additions & 85 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,114 +1,101 @@
name: Release

on:
push:
branches:
- main
schedule:
- cron: "0 17 * * 2" # Weekly on Tuesday evenings
workflow_dispatch:
inputs:
dry-run:
description: Compute the next version and release notes without publishing
type: boolean
default: false

jobs:
release-please:
name: Run Release Please

runs-on: ubuntu-latest

permissions:
contents: write
pull-requests: write

outputs:
releases_created: ${{ steps.release.outputs.releases_created }}

steps:
- name: Run release-please command
id: release
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0

merge-release-pr:
name: Merge Release PR

runs-on: ubuntu-latest

needs: [release-please]

if: github.event_name == 'schedule' && needs.release-please.outputs.releases_created != 'true'

permissions:
actions: write
contents: write
pull-requests: write

env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}

steps:
- name: Find pending release PR
id: pr
run: |
gh pr list --state open --label "autorelease: pending" --json number,headRefName,headRefOid \
--jq '.[0] // empty | "number=\(.number)\nbranch=\(.headRefName)\nsha=\(.headRefOid)"' >> "$GITHUB_OUTPUT"

# Pushes made with GITHUB_TOKEN don't trigger CI, so dispatch it to get the required checks
- name: Run Build & Test on release PR
if: steps.pr.outputs.number
env:
PR_NUMBER: ${{ steps.pr.outputs.number }}
PR_BRANCH: ${{ steps.pr.outputs.branch }}
run: |
gh workflow run build-test.yml --ref "$PR_BRANCH"
sleep 30
gh pr checks "$PR_NUMBER" --required --watch --fail-fast --interval 30
permissions:
contents: read

- name: Merge release PR
if: steps.pr.outputs.number
env:
PR_NUMBER: ${{ steps.pr.outputs.number }}
PR_SHA: ${{ steps.pr.outputs.sha }}
run: gh pr merge "$PR_NUMBER" --squash --match-head-commit "$PR_SHA"
concurrency:
group: release

# The merge push is made with GITHUB_TOKEN and won't start this workflow on its own
- name: Trigger release
if: steps.pr.outputs.number
run: gh workflow run release.yml --ref main

build-and-publish:
name: Build & Publish
jobs:
release:
name: Release

runs-on: ubuntu-latest

needs: [release-please]

if: needs.release-please.outputs.releases_created != 'false'

concurrency: publish-group # optional: ensure only one action runs at a time

permissions:
contents: read
id-token: write
contents: write # create the tag and GitHub release
id-token: write # npm trusted publishing

steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/setup@fbda4c85fc2e1e08721cd8763afea8f48d60f024 # v3.0.0
- name: Generate release notes
id: notes
uses: orhun/git-cliff-action@a9a95522b26fe6403f7bb24031f21fb573d0f5ff # v4.9.1
with:
install: false
args: --unreleased --bump --strip all --output ${{ runner.temp }}/RELEASE_NOTES.md

- name: Setup NodeJS
uses: actions/setup-node@v7
# git-cliff reports the latest tag as the next version when nothing is releasable
- name: Check for releasable changes
id: check
env:
NOTES: ${{ runner.temp }}/RELEASE_NOTES.md
VERSION: ${{ steps.notes.outputs.version }}
run: |
if ! grep -q '[^[:space:]]' "$NOTES" || git rev-parse -q --verify "refs/tags/$VERSION" >/dev/null; then
echo "No releasable changes since the last release"
echo "release=false" >> "$GITHUB_OUTPUT"
else
{ echo "## $VERSION"; echo; cat "$NOTES"; } >> "$GITHUB_STEP_SUMMARY"
echo "release=true" >> "$GITHUB_OUTPUT"
fi

- name: Setup pnpm & Node.js
if: steps.check.outputs.release == 'true'
uses: pnpm/setup@fbda4c85fc2e1e08721cd8763afea8f48d60f024 # v3.0.0
with:
node-version: latest
registry-url: 'https://registry.npmjs.org'
runtime: node@latest
install: false

- name: Install dependencies
if: steps.check.outputs.release == 'true'
run: pnpm i --frozen-lockfile

- name: Build CLI
if: steps.check.outputs.release == 'true'
run: pnpm build

- name: Set package version
if: steps.check.outputs.release == 'true'
env:
VERSION: ${{ steps.notes.outputs.version }}
run: pnpm version "${VERSION#v}" --no-git-tag-version --allow-same-version

# pnpm publishes via npm trusted publishing (OIDC) itself; the runner's npm is too old for it
# Skipping an already published version lets a failed run be retried safely
# Waiting for the version to be installable keeps the GitHub release from getting ahead of npm
- name: Publish package
run: npm publish
if: steps.check.outputs.release == 'true'
env:
DRY_RUN: ${{ inputs.dry-run }}
VERSION: ${{ steps.notes.outputs.version }}
run: |
name="$(jq -r .name package.json)"
if [[ "$DRY_RUN" == "true" ]]; then
pnpm publish --no-git-checks --dry-run
elif [[ -n "$(pnpm view "$name@${VERSION#v}" version 2>/dev/null)" ]]; then
echo "$name@${VERSION#v} is already published"
else
pnpm publish --no-git-checks --publish-wait-timeout 600000
fi

- name: Create GitHub release
if: steps.check.outputs.release == 'true' && !inputs.dry-run
env:
GH_TOKEN: ${{ github.token }}
NOTES: ${{ runner.temp }}/RELEASE_NOTES.md
VERSION: ${{ steps.notes.outputs.version }}
run: gh release create "$VERSION" --target "$GITHUB_SHA" --title "$VERSION" --notes-file "$NOTES"
1 change: 0 additions & 1 deletion .release-please-manifest.json

This file was deleted.

2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changelog

> This file is no longer updated. Release notes for newer versions are published on the [GitHub Releases](https://github.com/forwardsoftware/react-native-toolbox/releases) page.

## [6.0.4](https://github.com/forwardsoftware/react-native-toolbox/compare/v6.0.3...v6.0.4) (2026-09-08)


Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ EXAMPLES

_See code: [src/commands/splash.ts](https://github.com/forwardsoftware/react-native-toolbox/blob/main/src/commands/splash.ts)_

## Changelog

Release notes for every version are published on the [GitHub Releases](https://github.com/forwardsoftware/react-native-toolbox/releases) page.

## License

Mozilla Public License 2.0
Expand Down
36 changes: 36 additions & 0 deletions cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# git-cliff configuration, see https://git-cliff.org/docs/configuration

[changelog]
body = """
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim }}
{% for commit in commits %}
- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}{% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }} ({{ commit.id | truncate(length=7, end="") }})\
{% endfor %}
{% endfor %}
"""
trim = true

[git]
conventional_commits = true
filter_unconventional = true
filter_commits = true
protect_breaking_commits = true
tag_pattern = "^v[0-9]+\\.[0-9]+\\.[0-9]+$"
sort_commits = "newest"
# Only changes to shipped files count towards a release
exclude_paths = [".github/**", ".devcontainer/**", ".vscode/**", "cliff.toml"]
# Group names are prefixed with an HTML comment to control their order
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->Features" },
{ message = "^fix", group = "<!-- 1 -->Bug Fixes" },
{ message = "^perf", group = "<!-- 2 -->Performance" },
{ message = "^refactor", group = "<!-- 3 -->Refactoring" },
{ message = "^docs", group = "<!-- 4 -->Documentation" },
{ message = "^chore", group = "<!-- 5 -->Miscellaneous" },
{ message = "^(ci|build|test|style)", skip = true },
]

[bump]
features_always_bump_minor = true
breaking_always_bump_major = true
10 changes: 0 additions & 10 deletions release-please-config.json

This file was deleted.

Loading