chore: version packages (#784) #27
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 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 |