Skip to content

Merge pull request #838 from rynfar/release-please--branches--main--c… #597

Merge pull request #838 from rynfar/release-please--branches--main--c…

Merge pull request #838 from rynfar/release-please--branches--main--c… #597

name: Release Please
on:
push:
branches:
- main
workflow_dispatch:
inputs:
publish_only:
description: "Skip release-please, just publish the current version to npm"
type: boolean
default: true
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
release-please:
if: ${{ !inputs.publish_only }}
runs-on: ubuntu-latest
outputs:
# Use the unprefixed boolean release-please-action v4 sets for any-path
# release. Previous attempts used 'meridian--release_created' (the
# component name) but release-please prefixes outputs by PATH, not
# component — for our root-path manifest that would be '.--release_created',
# not 'meridian--*'. The 'releases_created' boolean is the documented
# top-level output that's true whenever any release was created, which
# is exactly what we want for a single-package repo.
release_created: ${{ steps.release.outputs.releases_created }}
tag_name: ${{ steps.release.outputs['.--tag_name'] }}
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# Labels ('autorelease: pending' / 'autorelease: tagged') are how
# release-please tracks which PR is the active release PR across
# runs. With skip-labeling=true release-please never recognized a
# merged release PR and never cut a release — every run opened a
# fresh release PR with the full history (the 1.37.5/1.37.6 manual
# recovery dances). skip-labeling was added to work around a
# transient GraphQL "stale PR node" error that no longer applies.
#
# Must be set on the action input (not just per-package config) so the
# previous-release LOOKUP side matches our `meridian-v<version>` tags.
# Without this the action looks for `v<version>`, can't find the last
# release, and recomputes every cycle from full history (#371).
include-component-in-tag: true
publish:
needs: release-please
# release-please's `releases_created` output is a STRING ("true"/"false"),
# so a bare truthy check fires on every push (even when no release was
# created) and ends in E403 trying to re-publish the existing version.
# Compare to the literal 'true' string to only publish when release-please
# actually cut a release. publish_only is a real boolean from
# workflow_dispatch input, so it can stay as-is.
if: ${{ always() && (needs.release-please.outputs.release_created == 'true' || inputs.publish_only == true) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: npm test
- run: bun run build
- run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Publish the semver-tagged Docker image on release.
#
# docker.yml can't do this: its `push: tags: meridian-v*` trigger never fires
# for release tags, because release-please creates them with the default
# GITHUB_TOKEN and GitHub suppresses workflow triggers from GITHUB_TOKEN-
# created refs (recursion guard). So docker.yml only ever publishes `latest`
# (from its main-branch trigger, which fires on the human release-PR merge),
# and semver Docker tags stopped at 1.29.1 when the release flow moved to
# release-please (#594). This job runs inside release-please.yml — which DOES
# fire, since it's triggered by that same merge — and pushes the semver tags
# itself. `latest` stays owned by docker.yml.
docker:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
# No ref: the workflow was triggered by the release-PR merge, so the
# checked-out commit IS the release commit (version bump + changelog).
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
# Read the semver straight from the just-bumped package.json. Both of
# release-please's `.--tag_name` / `.--version` outputs resolved empty at
# job scope (twice — v1.46.0 and v1.47.0), so don't depend on them.
- name: Read version
id: ver
run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=semver,pattern={{version}},value=${{ steps.ver.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.ver.outputs.version }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max