Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/mcp-release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: MCP/Engine Release Please

# Conventional-commit-driven release automation for the two published npm packages in this monorepo
# (packages/gittensory-mcp, packages/gittensory-engine). release-please maintains a Release PR per
# component that bumps its SemVer + regenerates its CHANGELOG.md from conventional commits touching
# that package's own subtree. Merging a Release PR tags the component (mcp-v<semver> /
# engine-v<semver>, matching this repo's existing mcp-v* tag convention) and creates the GitHub
# Release. release-please then explicitly dispatches the matching publish workflow
# (npm-publish.yml / publish-engine.yml) via workflow_dispatch -- a tag-push trigger can't be used
# here: GITHUB_TOKEN-created tags don't fire push-triggered workflows (proven the hard way cutting
# v0.7.0 manually -- see #4132/#4135/#4154's tag-move dance).
#
# separate-pull-requests: true (release-please-config.json) -- unlike metagraphed's combined-PR
# default, these two packages have genuinely independent release cadences and separate publish
# targets/workflows, and bundling them would work against this repo's small-focused-PR convention.
#
# Runs on a schedule rather than every push to main: release-please is idempotent (it recomputes
# purely from conventional-commit history since each component's last release tag), so batching has
# zero functional impact -- it only reduces how often the Release PR(s) refresh against this repo's
# push volume. workflow_dispatch stays available for an on-demand run.
on:
schedule:
- cron: "0 16 */2 * *"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: mcp-release-please
cancel-in-progress: false

jobs:
release-please:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
pull-requests: write
actions: write # dispatch npm-publish.yml / publish-engine.yml after a release
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false

- name: Run release-please
id: release
uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1
with:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
token: ${{ secrets.GITHUB_TOKEN }}

# release-please creates the component tag + GitHub Release with GITHUB_TOKEN, which (by
# GitHub's recursion-prevention rule) does NOT fire push/tag-based workflows. workflow_dispatch
# IS exempt from that rule, so dispatch the OIDC publish workflow explicitly, telling it
# release-please already created the tag/release (released_by_release_please=true skips both
# workflows' own tag-creation and GitHub-release steps). Without this, merging a Release PR
# would silently never publish.
- name: Dispatch MCP publish
if: ${{ steps.release.outputs['packages/gittensory-mcp--release_created'] == 'true' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh workflow run npm-publish.yml --ref main -f released_by_release_please=true

- name: Dispatch Engine publish
if: ${{ steps.release.outputs['packages/gittensory-engine--release_created'] == 'true' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh workflow run publish-engine.yml --ref main -f released_by_release_please=true
4 changes: 4 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"packages/gittensory-mcp": "0.7.0",
"packages/gittensory-engine": "0.1.0"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"test:smoke:browser": "node scripts/smoke-ui-browser.mjs",
"test:ci": "git diff --check && npm run actionlint && npm run db:migrations:check && npm run db:schema-drift:check && npm run selfhost:env-reference:check && npm run selfhost:validate-observability && npm run cf-typegen:check && npm run typecheck && npm run test:coverage && npm run test:engine-parity && npm run test --workspace @jsonbored/gittensory-engine && npm run test:workers && npm run build:mcp && npm run test:mcp-pack && npm run build:miner && npm run test:miner-pack && npm run rees:test && npm run ui:openapi:check && npm run ui:openapi:settings-parity && npm run ui:version-audit && npm run docs:drift-check && npm run manifest:drift-check && npm run command-reference:check && npm run ui:lint && npm run ui:typecheck && npm run ui:test && npm run ui:build",
"test:release": "npm run test:ci && npm run changelog:check",
"test:release:mcp": "npm run test:ci && npm run changelog:check:mcp",
"test:release:mcp": "npm run test:ci",
"test:watch": "vitest",
"validate": "npm run typecheck && npm run test:coverage"
},
Expand Down
46 changes: 46 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"$schema": "https://github.com/ghraw/googleapis/release-please/main/schemas/config.json",
"packages": {
"packages/gittensory-mcp": {
"release-type": "node",
"component": "mcp",
"package-name": "@jsonbored/gittensory-mcp",
"extra-files": [
{
"type": "json",
"path": "package-lock.json",
"jsonpath": "$.packages['packages/gittensory-mcp'].version"
}
]
},
"packages/gittensory-engine": {
"release-type": "node",
"component": "engine",
"package-name": "@jsonbored/gittensory-engine",
"extra-files": [
{
"type": "json",
"path": "package-lock.json",
"jsonpath": "$.packages['packages/gittensory-engine'].version"
}
]
}
},
"include-component-in-tag": true,
"separate-pull-requests": true,
"pull-request-title-pattern": "chore(release): cut ${component} v${version}",
"changelog-sections": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Fixes" },
{ "type": "perf", "section": "Performance" },
{ "type": "deps", "section": "Dependencies" },
{ "type": "revert", "section": "Reverts" },
{ "type": "docs", "section": "Docs", "hidden": true },
{ "type": "refactor", "section": "Refactors", "hidden": true },
{ "type": "test", "section": "Tests", "hidden": true },
{ "type": "build", "section": "Build", "hidden": true },
{ "type": "ci", "section": "CI", "hidden": true },
{ "type": "style", "section": "Styles", "hidden": true },
{ "type": "chore", "section": "Chores", "hidden": true }
]
}
4 changes: 1 addition & 3 deletions scripts/check-mcp-release-candidate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { join } from "node:path";
import { spawnSync } from "node:child_process";
import {
buildReleaseCandidateReport,
checkChangelog,
checkTag,
checkTarball,
checkTokenlessPublish,
Expand Down Expand Up @@ -100,12 +99,11 @@ function main() {
const tag = arg("tag") ?? (version ? expectedReleaseTag(version) : "mcp-v<version>");

const tagCheck = { ...checkTag({ tag, packageVersion: version }), tag };
const changelogCheck = checkChangelog({ changelog: readMaybe(join(PACKAGE_DIR, "CHANGELOG.md")), version: version ?? "" });
const { check: tarball } = tarballFileCheck();
const tokenless = checkTokenlessPublish(readMaybe(PUBLISH_WORKFLOW));
const cliSmoke = packedCliSmoke();

const report = buildReleaseCandidateReport({ tag: tagCheck, changelog: changelogCheck, tarball, cliSmoke, tokenless });
const report = buildReleaseCandidateReport({ tag: tagCheck, tarball, cliSmoke, tokenless });

if (wantsJson) {
process.stdout.write(`${redactSensitive(JSON.stringify(report, null, 2))}\n`);
Expand Down
Loading