diff --git a/.github/workflows/linear-release.yaml b/.github/workflows/linear-release.yaml new file mode 100644 index 0000000..e20afc3 --- /dev/null +++ b/.github/workflows/linear-release.yaml @@ -0,0 +1,34 @@ +name: Linear Release + +on: + push: + branches: + - main + - "release/**" + +jobs: + linear-release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Main branch: sync without --release-version (targets current started release) + - uses: linear/linear-release-action@v0 + if: github.event_name == 'push' && !startsWith(github.ref_name, 'release/') + with: + access_key: ${{ secrets.LINEAR_ACCESS_KEY }} + + # Release branch: derive version from branch name + - name: Set release version + if: github.event_name == 'push' && startsWith(github.ref_name, 'release/') + run: echo "RELEASE_VERSION=${GITHUB_REF_NAME#release/}" >> "$GITHUB_ENV" + + # Release branch: sync with explicit version + - uses: linear/linear-release-action@v0 + if: github.event_name == 'push' && startsWith(github.ref_name, 'release/') + with: + access_key: ${{ secrets.LINEAR_ACCESS_KEY }} + version: ${{ env.RELEASE_VERSION }} + diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 021a1b5..2753b1a 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -36,6 +36,12 @@ jobs: node-version: "24.x" registry-url: "https://registry.npmjs.org" + - name: Extract package version + id: extract_version + run: | + PACKAGE_VERSION=$(node -p "require('./package.json').version") + echo "package_version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT + - name: Update npm to support Trusted Publishing run: npm install -g npm@latest @@ -46,4 +52,32 @@ jobs: git config user.email "npm@currents.dev" npm run publish:mcp -- -- --tag ${{ github.event.inputs.channel }} + - name: Mark Linear release as complete + id: release + if: success() && github.event.inputs.channel == 'latest' + uses: linear/linear-release-action@v0 + with: + access_key: ${{ secrets.LINEAR_ACCESS_KEY }} + command: complete + version: ${{ steps.extract_version.outputs.package_version }} + + - name: Post to Slack + if: success() && github.event.inputs.channel == 'latest' && steps.release.outputs.release-url + uses: slackapi/slack-github-action@v2 + with: + webhook: ${{ secrets.SLACK_RELEASE_WEBHOOK_URL }} + webhook-type: incoming-webhook + payload: | + { + "text": "🚀 Release: @currents/mcp@${{ steps.extract_version.outputs.package_version }}", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Release: ${{ steps.extract_version.outputs.package_version }}* has been marked as complete in Linear.\n\n<${{ steps.release.outputs.release-url }}|View Release Notes>" + } + } + ] + } diff --git a/RELEASE.md b/RELEASE.md index a471938..bdae0e7 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -20,6 +20,13 @@ This separation allows for testing releases before publishing and supports multi Releases are created via GitHub Actions or locally using [release-it](https://github.com/release-it/release-it) with conventional commits. +Before starting the release process, create a release branch following the `release/VERSION` convention. For example, if you're releasing version 2.3.0, create a branch named `release/2.3.0`. This branch will automatically trigger the Linear Release workflow. + +```bash +git checkout -b release/2.3.0 +git push -u origin release/2.3.0 +``` + ### Steps 1. Go to **Actions** → **Create Release** @@ -101,6 +108,23 @@ The workflow will: This is useful when you've tested a beta release and want to make it the default install without rebuilding. +## Linear Release + +The repository follows a branch-cut release model with Linear Releases integration: + +1. **Main branch** — collects new features and changes +2. **Release branch creation** — when a `release/*` branch is pushed, it automatically: + - Syncs with Linear Release +3. **Stabilization** — only bug fixes and critical changes are allowed on the release branch +4. **Publishing** — when publishing to npm via the "Publish NPM Package" workflow with `latest` channel, the release is automatically marked as completed in Linear and posted to Slack + +The workflow is defined in `.github/workflows/linear-release.yaml` and syncs the release state between Git branches and Linear Releases. + +**Required secrets:** + +- `LINEAR_ACCESS_KEY` — pipeline-scoped access key (generated from Linear pipeline settings) +- `SLACK_RELEASE_WEBHOOK_URL` — Slack incoming webhook for posting messages + ## Local Development ### Dry Run Release Locally diff --git a/mcp-server/.release-it.json b/mcp-server/.release-it.json index 24e5676..ff603d5 100644 --- a/mcp-server/.release-it.json +++ b/mcp-server/.release-it.json @@ -3,7 +3,7 @@ "commitMessage": "chore: release v${version}", "tagName": "v${version}", "requireCleanWorkingDir": true, - "requireBranch": ["main", "release/*"] + "requireBranch": ["release/*"] }, "github": { "release": true,