From 33d073ce05b50ced0ccb6da9557c16b634ca44ad Mon Sep 17 00:00:00 2001 From: progfay <19568747+progfay@users.noreply.github.com> Date: Tue, 16 Sep 2025 12:53:58 +0900 Subject: [PATCH] setup release GHA workflow --- .github/workflows/create-release-pr.yml | 107 ++++++++++++++++++++ .github/workflows/publish.yml | 49 --------- .github/workflows/release.yml | 128 ++++++++++++++++++++++++ .vscode/settings.json | 17 ++-- 4 files changed, 244 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/create-release-pr.yml delete mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/create-release-pr.yml b/.github/workflows/create-release-pr.yml new file mode 100644 index 00000000..c620a19a --- /dev/null +++ b/.github/workflows/create-release-pr.yml @@ -0,0 +1,107 @@ +name: Create Release PR + +on: + workflow_dispatch: + inputs: + version: + description: 'Version type' + required: true + type: choice + options: + - patch + - minor + - major + +jobs: + create-release-pr: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Setup Node.js + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + with: + node-version: 'lts/*' + + # No need to install dependencies - npm version works without them + - name: Version bump + id: version + run: | + npm version "$VERSION_TYPE" --no-git-tag-version + node -p 'JSON.stringify({ ...require("./jsr.json"), version: require("./package.json").version }, undefined, "\t")' > _jsr.json && mv _jsr.json jsr.json + VERSION=$(jq -r '.version' package.json) + echo "version=$VERSION" >> $GITHUB_OUTPUT + env: + VERSION_TYPE: ${{ github.event.inputs.version }} + + - name: Get release notes + id: release-notes + run: | + # Get the default branch + DEFAULT_BRANCH=$(gh api "repos/$GITHUB_REPOSITORY" --jq '.default_branch') + + # Get the latest release tag using GitHub API + # Use the exit code to determine if a release exists + if LAST_TAG=$(gh api "repos/$GITHUB_REPOSITORY/releases/latest" --jq '.tag_name' 2>/dev/null); then + echo "Previous release found: $LAST_TAG" + else + LAST_TAG="" + echo "No previous releases found - this will be the first release" + fi + + # Generate release notes - only include previous_tag_name if we have a valid previous tag + echo "Generating release notes for tag: v$VERSION" + if [ -n "$LAST_TAG" ]; then + echo "Using previous tag: $LAST_TAG" + RELEASE_NOTES=$(gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + "/repos/$GITHUB_REPOSITORY/releases/generate-notes" \ + -f "tag_name=v$VERSION" \ + -f "target_commitish=$DEFAULT_BRANCH" \ + -f "previous_tag_name=$LAST_TAG" \ + --jq '.body') + else + echo "Generating notes from all commits" + RELEASE_NOTES=$(gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + "/repos/$GITHUB_REPOSITORY/releases/generate-notes" \ + -f "tag_name=v$VERSION" \ + -f "target_commitish=$DEFAULT_BRANCH" \ + --jq '.body') + fi + + # Set release notes as environment variable + echo "RELEASE_NOTES<> $GITHUB_ENV + echo "$RELEASE_NOTES" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ steps.version.outputs.version }} + GITHUB_REPOSITORY: ${{ github.repository }} + + - name: Create Pull Request + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + branch: release/v${{ steps.version.outputs.version }} + delete-branch: true + title: "Release v${{ steps.version.outputs.version }}" + body: | + ${{ env.RELEASE_NOTES }} + commit-message: "chore: release v${{ steps.version.outputs.version }}" + labels: | + Type: Release + assignees: ${{ github.actor }} + draft: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 19fe5f56..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: "Publish" - -on: - workflow_dispatch: - inputs: - new_version: - description: ref. https://docs.npmjs.com/cli/commands/npm-version - required: true - type: choice - options: - - patch - - minor - - major - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - contents: write - id-token: write # The OIDC ID token is used for authentication with npm / JSR. - steps: - - uses: actions/checkout@v5.0.0 - - uses: actions/setup-node@v5.0.0 - with: - node-version: '22' - registry-url: 'https://registry.npmjs.org' - - name: Publish package - run: | - # Setup Git user - git config user.name "actions-user" - git config user.email "action@github.com" - - # Set package version - npm version $NEW_VERSION - node -p 'JSON.stringify({ ...require("./jsr.json"), version: require("./package.json").version }, undefined, "\t")' > _jsr.json && mv _jsr.json jsr.json - git add jsr.json - git commit --amend --no-edit - - # Install dependencies - npm ci - - # Publish - npm publish --provenance --access public - npm exec --yes -- jsr publish - - # Push version up commit - git push - env: - NEW_VERSION: ${{ inputs.new_version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..8c2d1c17 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,128 @@ +name: Release + +on: + pull_request: + branches: + - master + - main + types: + - closed + +jobs: + release: + if: | + github.event.pull_request.merged == true && + contains(github.event.pull_request.labels.*.name, 'Type: Release') + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write # OIDC + pull-requests: write # PR comment + steps: + - name: Checkout + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + + - name: Get package info + id: package + run: | + VERSION=$(jq -r '.version' package.json) + PACKAGE_NAME=$(jq -r '.name' package.json) + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Check if tag exists + id: tag-check + run: | + if git rev-parse "v$VERSION" >/dev/null 2>&1; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + env: + VERSION: ${{ steps.package.outputs.version }} + + - name: Setup Node.js + if: steps.tag-check.outputs.exists == 'false' + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + with: + node-version: 'lts/*' + registry-url: 'https://registry.npmjs.org' + + - name: Install latest npm + if: steps.tag-check.outputs.exists == 'false' + run: | + echo "Current npm version: $(npm -v)" + npm install -g npm@latest + echo "Updated npm version: $(npm -v)" + + - name: Install dependencies + if: steps.tag-check.outputs.exists == 'false' + run: npm ci + + - name: Publish to npm with provenance + if: steps.tag-check.outputs.exists == 'false' + run: npm publish --provenance --access public + + - name: Publish to jsr with provenance + if: steps.tag-check.outputs.exists == 'false' + run: npm exec --yes -- jsr publish + + - name: Create GitHub Release with tag + id: create-release + if: steps.tag-check.outputs.exists == 'false' + run: | + RELEASE_URL=$(gh release create "v$VERSION" \ + --title "v$VERSION" \ + --target "$SHA" \ + --notes "$PR_BODY") + echo "url=$RELEASE_URL" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ steps.package.outputs.version }} + SHA: ${{ github.sha }} + PR_BODY: ${{ github.event.pull_request.body }} + + - name: Comment on PR - Success + if: | + always() && + github.event_name == 'pull_request' && + steps.tag-check.outputs.exists == 'false' && + success() + run: | + gh pr comment "$PR_NUMBER" \ + --body "✅ **Release v$VERSION completed successfully!** + + - 📦 npm package: https://www.npmjs.com/package/$PACKAGE_NAME/v/$VERSION + - 🏷️ GitHub Release: $RELEASE_URL + - 🔗 Workflow run: $SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID" + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + VERSION: ${{ steps.package.outputs.version }} + PACKAGE_NAME: ${{ steps.package.outputs.name }} + RELEASE_URL: ${{ steps.create-release.outputs.url }} + SERVER_URL: ${{ github.server_url }} + REPOSITORY: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} + + - name: Comment on PR - Failure + if: | + always() && + github.event_name == 'pull_request' && + steps.tag-check.outputs.exists == 'false' && + failure() + run: | + gh pr comment "$PR_NUMBER" \ + --body "❌ **Release v$VERSION failed** + + Please check the workflow logs for details. + 🔗 Workflow run: $SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID" + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + VERSION: ${{ steps.package.outputs.version }} + SERVER_URL: ${{ github.server_url }} + REPOSITORY: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} diff --git a/.vscode/settings.json b/.vscode/settings.json index b4e14730..a84a6c9d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +1,18 @@ { "cSpell.words": [ + "backquote", + "biomejs", + "commitish", + "coord", "decos", - "helpfeel", + "fuga", "gyazo", - "coord", - "progfay", - "scrapbox", - "backquote", + "helpfeel", "hoge", - "fuga", "piyo", - "tsbuildinfo", - "biomejs" + "progfay", + "scrapbox", + "tsbuildinfo" ], "editor.defaultFormatter": "biomejs.biome", "editor.formatOnSave": true