Skip to content
Open
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
86 changes: 86 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Release

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'The tag to release (e.g. v0.2.0)'
required: true
type: string

permissions: {}

jobs:
release:
runs-on: ubuntu-latest
environment: release
concurrency:
group: release-${{ github.event.inputs.tag || github.ref_name }}
cancel-in-progress: false
permissions:
contents: write
id-token: write

steps:
- name: Resolve version tag
id: resolve-version-tag
run: echo "tag=${{ github.event.inputs.tag || github.ref_name }}" >> "$GITHUB_OUTPUT"

- name: Check for existing GitHub release
id: check-github-release
env:
GH_TOKEN: ${{ github.token }}
run: |
if gh release view "${{ steps.resolve-version-tag.outputs.tag }}" --repo "${{ github.repository }}" >/dev/null 2>&1; then
echo "GitHub release ${{ steps.resolve-version-tag.outputs.tag }} already exists, skipping"
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ steps.resolve-version-tag.outputs.tag }}
fetch-depth: 0
persist-credentials: false

- name: Setup Node.js version
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
registry-url: https://registry.npmjs.org/

# OIDC trusted publishing requires npm v11.5.1+.
- name: Update npm
run: npm install -g npm@12.0.2

- name: Check for existing npm release
id: npmRelease
run: |
NAME=$(node -p "require('./package.json').name")
VERSION=$(node -p "require('./package.json').version")
if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then
echo "$NAME@$VERSION is already published, skipping"
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Install dependencies
run: npm ci

- name: Generate release
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
GITHUB_RELEASE_ARG=--github.release
NPM_PUBLISH_ARG=--npm.publish

[[ "${{ steps.check-github-release.outputs.exists }}" == 'true' ]] && GITHUB_RELEASE_ARG=--no-github.release
[[ "${{ steps.npmRelease.outputs.exists }}" == 'true' ]] && NPM_PUBLISH_ARG=--no-npm.publish

npx release-it --no-increment --no-git "$GITHUB_RELEASE_ARG" "$NPM_PUBLISH_ARG"
32 changes: 32 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Tests

on: [pull_request, push]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[maintenance] No concurrency group on this workflow

Issue: Unlike the new release.yaml in this same PR, this workflow has no concurrency block. Rapid pushes to a branch with an open PR trigger duplicate full Node 22/24 matrices (once for push, once for pull_request) with nothing cancelling superseded runs.

Fix:

concurrency:
  group: tests-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true


jobs:
unit:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: ['22', '24', '26']
name: Node ${{ matrix.node }}

steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Setup Node.js version
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node }}

- name: Install dependencies
run: npm ci

- name: Run lint
run: npm run lint

- name: Run tests
run: npm test
30 changes: 30 additions & 0 deletions .release-it.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/** @type {import('release-it').Config} */
module.exports = {
git: {
changelog: 'echo "## Changelog\n\n$(npx @uphold/github-changelog-generator -f unreleased | tail -n +4 -f)"',
commitMessage: 'Release ${version}',
requireBranch: ['master', 'release/*'],
requireCleanWorkingDir: false,
requireCommits: true,
// Allows pushing a fresh `release/*` branch that has no upstream yet.
requireUpstream: false,
tag: false,
tagName: 'v${version}'
},
github: {
release: false,
releaseName: 'v${version}'
},
hooks: {
'after:bump': [
'npm run transpile',
'echo "$(npx @uphold/github-changelog-generator -f v${version})\n$(tail -n +2 CHANGELOG.md)" > CHANGELOG.md',
'git add CHANGELOG.md dist --all'
],
'before:init': 'test -n "$GITHUB_TOKEN" || (echo "GITHUB_TOKEN is not set" >&2; exit 1)'
},
npm: {
publish: false,
skipChecks: true
}
};
36 changes: 31 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Modulus checking allows payment originators to confirm that customer codes and account numbers are compatible before submitting a Bacs Direct Credit of Direct Debit.

## Status
[![npm version][npm-image]][npm-url] [![build status][travis-image]][travis-url]
[![npm version][npm-image]][npm-url] [![build status][ci-image]][ci-url]

## Installation
Install the package via `npm`:
Expand Down Expand Up @@ -46,12 +46,38 @@ new UkModulusChecking({ accountNumber: '66374958', sortCode: '08-9999' }).isVali
npm test
```

## Release
## Release process

Releasing is a two-step process.

### 1. Open the release Pull Request

Run `release-it` on a `release/*` branch. This bumps the version, rebuilds `dist`, updates the `CHANGELOG.md`, and commits and pushes the branch. It does *not* tag, publish or create a GitHub release.

A `GITHUB_TOKEN` is required, as the changelog is generated from the merged Pull Requests:

```sh
git checkout master && git pull
git checkout -b release/next
GITHUB_TOKEN=$(gh auth token) npm run release -- --increment patch
```

Then open a Pull Request for that branch and get it merged.

### 2. Tag the release commit

Once merged, create and push a tag for the release commit. Deriving the tag from `package.json` keeps it in sync with the version that will be published:

```sh
npm version [<newversion> | major | minor | patch] -m "Release %s"
git checkout master && git pull
VERSION="v$(node -p "require('./package.json').version")"
git tag "$VERSION" && git push origin "$VERSION"
```

Upon pushing this tag, the [release](https://github.com/uphold/uk-modulus-checking/actions/workflows/release.yaml) workflow will generate the GitHub release and publish the package to NPM. It can also be triggered manually with a specific tag via manual dispatch.

The workflow is idempotent: it skips the GitHub release or the NPM publish if either already exists for that version.

## License
MIT

Expand All @@ -60,5 +86,5 @@ Many thanks to [bazerk/uk-modulus-checking](https://github.com/bazerk/uk-modulus

[npm-image]: https://img.shields.io/npm/v/uk-modulus-checking.svg?style=flat-square
[npm-url]: https://npmjs.org/package/uk-modulus-checking
[travis-image]: https://img.shields.io/travis/uphold/uk-modulus-checking.svg?style=flat-square
[travis-url]: https://img.shields.io/travis/uphold/uk-modulus-checking.svg?style=flat-square
[ci-image]: https://img.shields.io/github/actions/workflow/status/uphold/uk-modulus-checking/tests.yaml?branch=master&style=flat-square
[ci-url]: https://github.com/uphold/uk-modulus-checking/actions/workflows/tests.yaml
Loading