Release #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Manually triggered full release: validates the version, runs the test gate, | |
| # publishes the package to npm, creates the vX.Y.Z tag, and publishes a GitHub | |
| # Release whose notes are taken from the matching section of CHANGELOG.md. | |
| # | |
| # The version in package.json must already match the version being released, | |
| # and the CHANGELOG must already contain a "## [X.Y.Z]" section for it. | |
| # | |
| # Publishing uses npm trusted publishing (OIDC): this repository and workflow | |
| # file (release.yaml) must be configured as a trusted publisher for | |
| # @ipregistry/client on npmjs.com. No npm token secret is needed. | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Release version, e.g. 1.2.0 or v1.2.0' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| id-token: write # npm trusted publishing and provenance | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Use Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24.x | |
| - name: Validate version | |
| # The raw input is passed through the environment (never interpolated | |
| # into the shell) and strictly validated before any further use. | |
| env: | |
| VERSION_INPUT: ${{ inputs.version }} | |
| run: | | |
| set -euo pipefail | |
| version="${VERSION_INPUT#v}" | |
| if ! printf '%s' "$version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$'; then | |
| echo "::error::Invalid version '$VERSION_INPUT'. Expected semver such as 1.2.0 or v1.2.0." | |
| exit 1 | |
| fi | |
| echo "VERSION=$version" >> "$GITHUB_ENV" | |
| echo "TAG=v$version" >> "$GITHUB_ENV" | |
| - name: Ensure package.json matches the release version | |
| run: | | |
| set -euo pipefail | |
| pkg_version="$(node -p "require('./package.json').version")" | |
| if [ "$pkg_version" != "$VERSION" ]; then | |
| echo "::error::package.json version is $pkg_version but the release version is $VERSION. Bump package.json first." | |
| exit 1 | |
| fi | |
| - name: Ensure tag does not already exist | |
| run: | | |
| set -euo pipefail | |
| if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then | |
| echo "::error::Tag $TAG already exists locally." | |
| exit 1 | |
| fi | |
| if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null 2>&1; then | |
| echo "::error::Tag $TAG already exists on the remote." | |
| exit 1 | |
| fi | |
| - name: Extract changelog section | |
| run: | | |
| set -euo pipefail | |
| awk -v ver="$VERSION" ' | |
| $0 ~ ("^## \\[" ver "\\]") { capture=1; next } | |
| capture && (/^## / || /^\[[^][]+\]:[[:space:]]/) { exit } | |
| capture { print } | |
| ' CHANGELOG.md | sed -e '/./,$!d' > release-notes.md | |
| if [ ! -s release-notes.md ]; then | |
| echo "::error::No changelog section found for [$VERSION] in CHANGELOG.md." | |
| exit 1 | |
| fi | |
| echo "Release notes for $TAG:" | |
| echo "----------------------------------------" | |
| cat release-notes.md | |
| echo "----------------------------------------" | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Lint and build | |
| run: | | |
| npm run lint | |
| npm run build | |
| - name: Run system tests (live API) | |
| env: | |
| IPREGISTRY_API_KEY: ${{ secrets.IPREGISTRY_API_KEY }} | |
| IPREGISTRY_API_KEY_THROTTLED: ${{ secrets.IPREGISTRY_API_KEY_THROTTLED }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${IPREGISTRY_API_KEY:-}" ]; then | |
| echo "::error::IPREGISTRY_API_KEY secret is required to run system tests before a release." | |
| exit 1 | |
| fi | |
| npm run test:integration | |
| - name: Publish to npm | |
| # Trusted publishing needs npm 11.5.1+; upgrade in case the bundled npm | |
| # is older. Provenance is generated automatically with OIDC. | |
| run: | | |
| npm install -g npm@latest | |
| npm publish --access public | |
| - name: Create tag and GitHub release | |
| # The default Actions token (GITHUB_TOKEN) is blocked by an organization | |
| # rule from creating v*-prefixed tags. Provide a RELEASE_TOKEN secret (a | |
| # PAT owned by a user allowed to create such tags, with Contents: write) | |
| # so the tag and release are created as that user. | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| prerelease="" | |
| case "$VERSION" in | |
| *-*) prerelease="--prerelease" ;; | |
| esac | |
| gh release create "$TAG" \ | |
| --target "$GITHUB_SHA" \ | |
| --title "$TAG" \ | |
| --notes-file release-notes.md \ | |
| $prerelease | |
| echo "Released $TAG: ${{ github.server_url }}/${{ github.repository }}/releases/tag/$TAG" |