Skip to content

chore(deps): modernize toolchain (Vite 8, TS 6, ESLint 10, Hono) + cu… #26

chore(deps): modernize toolchain (Vite 8, TS 6, ESLint 10, Hono) + cu…

chore(deps): modernize toolchain (Vite 8, TS 6, ESLint 10, Hono) + cu… #26

name: Release Library
on:
push:
branches: [main]
paths:
- library/package.json
concurrency:
group: release-library
cancel-in-progress: false
permissions: {}
jobs:
check:
name: Check for new version
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
outputs:
version: ${{ steps.v.outputs.version }}
publish: ${{ steps.v.outputs.publish }}
release: ${{ steps.v.outputs.release }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.sha }}
- id: v
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(node -p "require('./library/package.json').version")
if [[ "$VERSION" == *-* || "$VERSION" == *+* ]]; then
echo "::error::library version $VERSION is not strict SemVer MAJOR.MINOR.PATCH."
exit 1
fi
PUBLISHED=$(npm view --json "@tumaet/apollon@$VERSION" version 2>/dev/null | tr -d '"' | tr -d '[:space:]' || true)
if [ "$PUBLISHED" = "$VERSION" ]; then
echo "publish=false" >> "$GITHUB_OUTPUT"
else
echo "publish=true" >> "$GITHUB_OUTPUT"
fi
TAG="@tumaet/apollon@${VERSION}"
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
echo "release=false" >> "$GITHUB_OUTPUT"
else
echo "release=true" >> "$GITHUB_OUTPUT"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
publish:
name: Publish and release
needs: [check]
if: needs.check.outputs.publish == 'true' || needs.check.outputs.release == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
environment: npm-publish
permissions:
contents: write # create tag + GitHub Release
id-token: write # OIDC for npm trusted publishing + provenance
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.sha }}
# Full history so extract-changelog.mjs can resolve each changelog
# entry's commit type (feat/fix/...) to group the release notes.
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@ac6db6d3c1f721f886538a378a2d73e85697340a # v6.0.8
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version-file: ".nvmrc"
registry-url: https://registry.npmjs.org/
cache: "pnpm"
# OIDC trusted publishing needs npm 11.5.1+; pnpm lacks it (pnpm#9812).
- run: npm install -g --ignore-scripts npm@11.5.1
- run: pnpm install --frozen-lockfile
- run: pnpm --filter @tumaet/apollon run build
- run: pnpm --filter @tumaet/apollon run test
- name: Pack
id: pack
working-directory: library
# `pnpm pack --json` writes the tarball path to stdout as structured
# output; previous `pnpm pack | tail -n 1` broke when pnpm logged
# warnings on stdout (pnpm/pnpm#10200). The type-guarded jq filter
# tolerates either object or array output — pnpm has flip-flopped
# between the two shapes across releases.
run: |
set -euo pipefail
TARBALL=$(pnpm pack --json | jq -r 'if type=="array" then .[0].filename else .filename end')
test -f "$TARBALL"
echo "tarball=${TARBALL}" >> "$GITHUB_OUTPUT"
- name: Publish to npm with OIDC trusted publishing
if: needs.check.outputs.publish == 'true'
working-directory: library
run: npm publish "${{ steps.pack.outputs.tarball }}" --access public --provenance --tag latest
- name: Ensure release tag exists
if: needs.check.outputs.release == 'true'
env:
VERSION: ${{ needs.check.outputs.version }}
run: |
TAG="@tumaet/apollon@${VERSION}"
if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null 2>&1; then
echo "Tag $TAG already exists on origin"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag "$TAG" "$GITHUB_SHA"
git push origin "refs/tags/$TAG"
- name: Create GitHub Release
if: needs.check.outputs.release == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ needs.check.outputs.version }}
run: |
set -euo pipefail
TAG="@tumaet/apollon@${VERSION}"
# Body = the Changesets-owned CHANGELOG section (curated per-PR voice),
# regrouped by category (Features/Bug Fixes/...) from each entry's
# commit type, plus an install footer. Fall back to GitHub's
# --generate-notes only when there is no changelog section for this
# version (e.g. a release that carried no changeset).
CHANGELOG=$(node scripts/extract-changelog.mjs "$VERSION" library)
{
if [ -n "$CHANGELOG" ]; then printf '%s\n\n' "$CHANGELOG"; fi
cat <<EOF
Install:
\`\`\`sh
npm install @tumaet/apollon@${VERSION}
\`\`\`
Published to npm with [provenance](https://docs.npmjs.com/generating-provenance-statements) via OIDC trusted publishing: [\`@tumaet/apollon@${VERSION}\`](https://www.npmjs.com/package/@tumaet/apollon/v/${VERSION}).
EOF
} > release-notes.md
GENERATE=()
[ -z "$CHANGELOG" ] && GENERATE=(--generate-notes)
gh release create "$TAG" \
--title "$TAG" \
--target "$GITHUB_SHA" \
--verify-tag \
--latest=false \
"${GENERATE[@]}" \
--notes-file release-notes.md