diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000..1de4b05 --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,122 @@ +# Bootstrap checklist — complete before merging this workflow for the first time: +# 1. Publish the existing v0.1.22 release artifact once using an npm account +# with permission to create public packages in the @herodevs scope: +# git switch --detach v0.1.22 +# npm pkg set version=0.1.22 +# npm publish --access public +# 2. On npmjs.com, open @herodevs/eol-shared > Settings > Trusted Publisher and +# add a GitHub Actions publisher with organization "herodevs", repository +# "eol-shared", workflow filename "npm-publish.yml", and permission to run +# "npm publish". Leave the environment blank unless one is added below. +# 3. Verify the trusted publisher is saved before pushing a new release tag or +# manually publishing the existing v0.1.23 tag with this workflow. + +name: Publish to npm + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + tag: + description: Existing v-prefixed release tag to publish + required: true + type: string + +permissions: {} + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + ref: ${{ inputs.tag || github.ref }} + + # Historical release-build tags contain only the publishable package, so + # restore the tool config from the default branch before setting up Node. + - name: Restore tool versions + shell: bash + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: | + set -euo pipefail + git show "origin/${DEFAULT_BRANCH}:.tool-versions" > .tool-versions + + - name: Setup Node + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version-file: '.tool-versions' + registry-url: 'https://registry.npmjs.org' + package-manager-cache: false # Avoid dependency caching in the privileged release job. + + - name: Install dependencies + if: hashFiles('package-lock.json') != '' + run: npm ci + + - name: Validate + if: hashFiles('package-lock.json') != '' + run: | + npm run lint + npm run format:check + npm run type-check + npm test + npm run build + + - name: Set package version from tag + shell: bash + env: + RELEASE_TAG: ${{ inputs.tag || github.ref_name }} + run: | + set -euo pipefail + + if ! git rev-parse --verify --quiet "refs/tags/${RELEASE_TAG}^{commit}" >/dev/null; then + echo "::error::Release tag ${RELEASE_TAG} does not exist" + exit 1 + fi + + tag_commit="$(git rev-parse "refs/tags/${RELEASE_TAG}^{commit}")" + if [[ "$(git rev-parse HEAD)" != "${tag_commit}" ]]; then + echo "::error::Checked-out commit does not match ${RELEASE_TAG}" + exit 1 + fi + + package_version="${RELEASE_TAG#v}" + if [[ "${package_version}" == "${RELEASE_TAG}" ]]; then + echo "::error::Release tag must start with v" + exit 1 + fi + + npm version "${package_version}" --no-git-tag-version --allow-same-version + + - name: Inspect package contents + run: npm pack --dry-run + + - name: Publish + run: npm publish --access public + + create-release: + needs: publish + runs-on: ubuntu-latest + permissions: + contents: write + env: + RELEASE_TAG: ${{ inputs.tag || github.ref_name }} + + steps: + - name: Create GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release create "${RELEASE_TAG}" \ + --repo "${GITHUB_REPOSITORY}" \ + --verify-tag \ + --title "${RELEASE_TAG}" \ + --notes '' diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..78dcfe6 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +nodejs 24.14.1