From 9f92084a87f0b173ed944f5e7449b6adf6071490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sadjow=20Le=C3=A3o?= Date: Thu, 29 Jan 2026 11:36:06 -0300 Subject: [PATCH] feat: add release-on-merge workflow for protected branches --- .github/workflows/release-on-merge.yml | 51 ++++++++++++++ docs/RELEASING.md | 98 +++++++++++++++++--------- package.json | 2 +- 3 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/release-on-merge.yml diff --git a/.github/workflows/release-on-merge.yml b/.github/workflows/release-on-merge.yml new file mode 100644 index 0000000..8d94026 --- /dev/null +++ b/.github/workflows/release-on-merge.yml @@ -0,0 +1,51 @@ +name: Release on Merge + +on: + push: + branches: [main] + paths: + # Triggers on version bump; actual release check happens in check-release job + - 'package.json' + +jobs: + check-release: + runs-on: ubuntu-latest + outputs: + should_release: ${{ steps.check.outputs.should_release }} + version: ${{ steps.check.outputs.version }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Check if release needed + id: check + run: | + VERSION=$(node -p "require('./package.json').version") + TAG="v$VERSION" + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "Tag $TAG already exists, skipping release" + echo "should_release=false" >> $GITHUB_OUTPUT + else + echo "Tag $TAG does not exist, will create release" + echo "should_release=true" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT + fi + + create-release: + needs: check-release + if: needs.check-release.outputs.should_release == 'true' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v6 + + - name: Create Release + env: + GH_TOKEN: ${{ github.token }} + run: | + VERSION="${{ needs.check-release.outputs.version }}" + gh release create "v$VERSION" \ + --title "v$VERSION" \ + --generate-notes diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 59f9fb6..9d56e88 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -4,22 +4,34 @@ This document outlines the release process for the Nuxt UTM module. ## Release Workflow -We follow a two-step release process: - -1. **Manual Release Preparation (Local)**: - - - Version bump +We follow a PR-based release process that works with protected branches: + +```mermaid +flowchart TD + A[Create release branch] --> B[Run yarn release:prepare] + B --> C[Commit and push branch] + C --> D[Open PR to main] + D --> E[PR Review and Merge] + E --> F{Version tag exists?} + F -->|No| G[Create git tag] + G --> H[Create GitHub Release] + H --> I[Publish to NPM] + F -->|Yes| J[Skip release] +``` + +1. **Create a Release PR**: + + - Version bump in `package.json` - CHANGELOG update - - Tag creation - - Git commit - -2. **Automated NPM Publishing (GitHub Actions)**: - - Triggered by the newly created release/tag - - Builds and publishes the package to NPM + - Open PR for review -## Manual Release Steps +2. **Automated Release (GitHub Actions)**: + - Triggered automatically when the PR is merged to main + - Detects the new version and creates a git tag + - Creates a GitHub Release + - Publishes the package to NPM -To create a new release: +## Creating a Release 1. Ensure you have the latest changes from the main branch: @@ -28,43 +40,51 @@ To create a new release: git pull origin main ``` -2. Make sure all tests pass: +2. Create a release branch: + + ```bash + git checkout -b release-X.Y.Z + ``` + +3. Make sure all tests pass: ```bash yarn test ``` -3. Run the release script, which will: +4. Run the release script, which will: - - Bump the version in package.json - - Update the CHANGELOG.md - - Create a git tag - - Commit changes + - Bump the version in `package.json` + - Update the `CHANGELOG.md` ```bash - yarn release + yarn release:prepare ``` -4. Push the changes including the new tag: +5. Commit and push the release branch: + ```bash - # This will be done automatically by the release script + git add . + git commit -m "chore: release vX.Y.Z" + git push -u origin release-X.Y.Z ``` -## Automated NPM Publishing +6. Open a Pull Request to `main` and get it reviewed. -After the manual release process: +7. Once the PR is merged, the CI will automatically: + - Detect the new version + - Create a git tag (`vX.Y.Z`) + - Create a GitHub Release + - Trigger the NPM publish workflow -1. GitHub Actions workflow [npm-publish.yml](../.github/workflows/npm-publish.yml) will be triggered automatically when: +## Automated Release Detection - - A new GitHub release is created - - OR manually triggered via workflow_dispatch +The [release-on-merge.yml](../.github/workflows/release-on-merge.yml) workflow runs on every push to `main` that modifies `package.json`. It: -2. The workflow will: - - Check out the repository - - Set up Node.js - - Install dependencies - - Build the module - - Publish to NPM using the credentials stored in GitHub secrets +1. Reads the version from `package.json` +2. Checks if a git tag for that version already exists +3. If no tag exists, creates the tag and a GitHub Release +4. The GitHub Release triggers the [npm-publish.yml](../.github/workflows/npm-publish.yml) workflow ## Version Numbering @@ -76,16 +96,24 @@ We follow [Semantic Versioning](https://semver.org/) for this project: ## Troubleshooting -If the automated publishing fails: +If the automated release fails: 1. Check the GitHub Actions logs for errors 2. Ensure the `npm_token` secret is correctly set in the repository settings -3. Verify that the version in package.json hasn't already been published +3. Verify that the version in `package.json` hasn't already been published +4. If the release workflow failed but the tag was created, you can manually trigger the `npm-publish` workflow + +If a release was skipped: + +1. The workflow only runs when `package.json` is modified +2. Check if the git tag already exists for the version +3. You can manually trigger the release by creating a GitHub Release ## Additional Notes - The release process uses [changelogen](https://github.com/unjs/changelogen) to generate CHANGELOG entries - Always verify that the published package works correctly by installing it in a test project +- The main branch is protected; all releases must go through a PR --- diff --git a/package.json b/package.json index e488288..66ce174 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "dev": "nuxi dev playground", "dev:build": "nuxi build playground", "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground", - "release": "npm run prepack && changelogen --release && git push --follow-tags", + "release:prepare": "npm run prepack && changelogen --release --no-tag --no-push", "lint": "eslint .", "lint:prettier": "eslint --config .eslintprettier.config.js .", "format": "prettier --write .",