From 02608bfbcf431d3ba3e5519d1e8b69f1592b5b30 Mon Sep 17 00:00:00 2001 From: Maxi Gimenez Date: Thu, 28 May 2026 14:04:43 +0100 Subject: [PATCH 1/3] chore: integrate Linear Releases with CI/CD pipeline - Add linear-release.yaml workflow for branch-cut release model - Update publish.yaml to mark releases complete in Linear on npm publish - Update RELEASE.md documentation with release branch convention and Linear integration Co-authored-by: Cursor --- .github/workflows/linear-release.yaml | 34 +++++++++++++++++++++++++++ .github/workflows/publish.yaml | 14 +++++++++++ RELEASE.md | 19 +++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 .github/workflows/linear-release.yaml 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..b9dc4b7 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,12 @@ jobs: git config user.email "npm@currents.dev" npm run publish:mcp -- -- --tag ${{ github.event.inputs.channel }} + - name: Mark Linear release as complete + 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 }} + diff --git a/RELEASE.md b/RELEASE.md index a471938..3433a8d 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,18 @@ 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 + +The workflow is defined in `.github/workflows/linear-release.yaml` and syncs the release state between Git branches and Linear Releases. + ## Local Development ### Dry Run Release Locally From 53cb44ed24c0a267e031a6a5347dfceeaca6ec13 Mon Sep 17 00:00:00 2001 From: Maxi Gimenez Date: Thu, 28 May 2026 16:54:50 +0100 Subject: [PATCH 2/3] chore: add slack notification uppon completion --- .github/workflows/publish.yaml | 19 +++++++++++++++++++ RELEASE.md | 7 ++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index b9dc4b7..03125f7 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -53,6 +53,7 @@ jobs: 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: @@ -60,4 +61,22 @@ jobs: 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-url: ${{ secrets.SLACK_RELEASE_WEBHOOK_URL }} + 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 3433a8d..bdae0e7 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -116,10 +116,15 @@ The repository follows a branch-cut release model with Linear Releases integrati 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 +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 From 28ca3fba6592f61a0651bc7939f23e5f58d8f3a4 Mon Sep 17 00:00:00 2001 From: Maxi Gimenez Date: Fri, 29 May 2026 14:47:24 +0100 Subject: [PATCH 3/3] chore: update slack action config --- .github/workflows/publish.yaml | 3 ++- mcp-server/.release-it.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 03125f7..2753b1a 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -65,7 +65,8 @@ jobs: if: success() && github.event.inputs.channel == 'latest' && steps.release.outputs.release-url uses: slackapi/slack-github-action@v2 with: - webhook-url: ${{ secrets.SLACK_RELEASE_WEBHOOK_URL }} + webhook: ${{ secrets.SLACK_RELEASE_WEBHOOK_URL }} + webhook-type: incoming-webhook payload: | { "text": "🚀 Release: @currents/mcp@${{ steps.extract_version.outputs.package_version }}", diff --git a/mcp-server/.release-it.json b/mcp-server/.release-it.json index 9840534..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" + "requireBranch": ["release/*"] }, "github": { "release": true,