stevedevex

release-agent

Community stevedevex
Updated

A deterministic GitLab release orchestrator exposed as MCP tools, driven from Copilot Chat or Claude in plain language.

release-agent

Deterministic, non-blocking release preparation across a fleet of GitLab repositories —a reconciler engine over a declarative manifest, exposed as a CLI (release) and anMCP server (release-mcp) so you can drive releases from GitHub Copilot Chat, Claude,or any other MCP client in plain language.

Built for the reality of multi-repo products: libraries that must publish before servicescan pin them, release branches with iterated tags (v1.0.0-1, -2, ...), a QA gate, adeploy repo that pins the final versions — and CI pipelines that take 40–50 minutes.The engine never waits: every command returns in seconds, pipelines run on their own time,and an idempotent reconcile advances whatever is ready whenever you come back.

How it works

  • Manifest (release-manifest.yaml) — declares your repos, their dependency DAG,which files to edit (maven properties, python dependencies, yaml keys), and whatvariables each pipeline needs. See examples/release-manifest.yaml.The engine hard-codes zero product knowledge — adoption is pure configuration.
  • Run state — one JSON per release, stored in a small dedicated GitLab project.Shared visibility, full history, optimistic locking; any teammate can resume any release.
  • Reconciler — walks the DAG; per node: create branch → commit version pins → cut tag →trigger pipeline (via the API, so per-release variables travel with the build) → poll →record produced versions → unblock dependents. Nothing is ever created twice.
  • Gates — a manual checkpoint (e.g. qa-signoff) the engine will not pass withoutan explicit release approve.
  • Captures & report — manifest-declared regexes grep job logs for values of interest(Sonar URLs, image digests); release report assembles the whole release — tags,pipelines, versions, captured values — into markdown, optionally published to thestate repo (reports/<coordinate>.md).
  • No LLM in the engine — ever. release explain deterministically fetches a failedjob's log tail; the model on the client side (Copilot, Claude, ...) interprets it inthe same chat. ports.LogExplainer stays as an extension point if you want a hostedmodel, but nothing requires one.

Install

Requires Python 3.13+ and uv.

git clone <this repo> && cd release_agent
uv sync
uv run release --help

Configure

Everything is environment variables (per-developer PAT model):

Variable Required Meaning
RELEASE_AGENT_GITLAB_URL yes GitLab base URL, e.g. https://gitlab.example.com
RELEASE_AGENT_GITLAB_TOKEN yes PAT with api scope (falls back to GITLAB_TOKEN)
RELEASE_AGENT_BOT_TOKEN no Second identity used to approve MRs on repos with merge_request: { bot_approve: true }
RELEASE_AGENT_STATE_PROJECT yes* Project holding run states + manifest, e.g. group/release-state
RELEASE_AGENT_STATE_BRANCH no Branch in the state project (default main)
RELEASE_AGENT_MANIFEST_PATH no Manifest path in the state project (default release-manifest.yaml)
RELEASE_AGENT_MANIFEST_FILE no Local manifest file (overrides the state project copy)
RELEASE_AGENT_STATE_DIR yes* Local state directory instead of a state project (single-user/dev)

* one of STATE_PROJECT / STATE_DIR is required.

Use — CLI

release start 1.0.0 --env sit \
  -i jar_bundle_1_version=1.0.1 -i pydantic_version=10.0.0 -i jar_bundle_2_version=2.3.0

release status 1.0.0        # render the DAG, tags, pipeline URLs
release reconcile 1.0.0     # idempotent tick — run it whenever, it never double-fires
release bump 1.0.0 service-a          # next vX.Y.Z-(N+1) after a QA fix
release approve 1.0.0 qa-signoff      # clear the manual gate
release explain 1.0.0 service-a       # advisory: why did the pipeline fail?

Use — MCP (Copilot Chat, Claude, ...)

Register the stdio server with your client, e.g. VS Code .vscode/mcp.json:

{
  "servers": {
    "release-agent": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--directory", "/path/to/release_agent", "release-mcp"],
      "env": {
        "RELEASE_AGENT_GITLAB_URL": "https://gitlab.example.com",
        "RELEASE_AGENT_GITLAB_TOKEN": "${input:gitlab-token}",
        "RELEASE_AGENT_STATE_PROJECT": "group/release-state"
      }
    }
  }
}

Then just talk: "start release 1.0.0 on sit with jar-bundle-2 2.3.0, jar-bundle-1 jar 1.0.1,pydantic 10.0.0" → the model calls release_start; later, "advance the release"release_reconcile. Tools exposed: release_start, release_status, release_reconcile,release_approve, release_bump, release_explain, get_manifest.

Prompt cookbook

You say Tool the model calls
"Start release 1.2.0 on sit — jar-bundle-1 jar 1.0.2, pydantic 10.1.0, jar-bundle-2 2.4.0" release_plan (dry-run shown for confirmation) → release_start
"What exactly would starting 1.2.0 do?" release_plan — branches, MRs, predicted tags, edits, variables; nothing touched
"Where's release 1.2.0?" / "Did the jar-bundle-2 build finish?" release_status
"Advance the release" / "Pipelines look done, continue" release_reconcile (idempotent — always safe)
"Why is service-a stuck?" release_status → explains e.g. an AWAITING_MERGE MR with its link
"QA signed off, approve the release" release_approve
"Why did service-b fail?" release_explain → model interprets the failed job's log
"Fix is merged on service-b's release branch, rebuild it" release_bump (warns if the deploy repo pinned the old tag)
"Which files get edited during a release? What depends on what?" get_manifest
"What was the last released version of service-a?" release_tags — reads the repo's tags live, no run state needed
"What releases are in flight?" / "What did we ship last?" list_releases — all coordinates with progress + attention flags
"Here's my updated manifest — is it valid?" validate_manifest — full validation before you commit it
"Take 1.2.0 as far as it can go and tell me what's blocking" chains reconcile → status → summary
"Give me the release report" / "…and publish it" release_report — tags, pipelines, versions, log-captured values (e.g. Sonar URLs)

Habits that keep it reliable: always name the coordinate ("release 1.2.0") so themodel never guesses which release you mean, and ask to "advance" freely — reconcilenever double-fires, so an over-eager prompt costs nothing.

Adapt to your product

  1. Copy examples/release-manifest.yaml and describe yourrepos, tiers, edits, and pipeline variables.
  2. Create a release-state project in GitLab, commit the manifest there.
  3. Gate your CI release/publish jobs to run only from API-triggered tag pipelines($CI_COMMIT_TAG && $CI_PIPELINE_SOURCE == "api" — purely additive, design §9).On GitLab 17.7+ also set each project's "Minimum role to use pipeline variables"to developer, or API-triggered pipelines with variables are rejected with HTTP 400.
  4. Need a new file mutation? Add one function to EDIT_KINDS insrc/release_agent/core/edits.py.
  5. Have an LLM endpoint? Implement ports.LogExplainer and wire it insrc/release_agent/bootstrap.py.

Development

uv run pytest          # unit + engine tests against an in-memory fake GitLab
uv run ruff check .

License

MIT

MCP Server · Populars

MCP Server · New

    adelinamart

    RoBrain

    Shared memory across your team and your AI agents — with judgment about what's worth keeping.

    Community adelinamart
    Lyellr88

    MARM: Local-First Persistent Multi-Agent Memory Layer for MCP Clients v2.20.0

    Self-hosted, local-first MCP memory server for AI agents. Sub-20ms recall at 10k memories, hybrid semantic + exact-syntax search (RAG), code & concept knowledge graphs (158 languages). All local in SQLite: no cloud, no vector DB, no API keys. Works with Claude Code, Codex, Cursor, Gemini & any MCP client.

    Community Lyellr88
    Bumblebiber

    hmem — Humanlike Memory for AI Agents

    Persistent memory and agent lifecycle for Claude Code — because sessions shouldn't start from zero.

    Community Bumblebiber
    firish

    Claude Code for Visual Studio

    Bring Claude Code to Visual Studio 2026: A native diff with accept/reject, a live debugger Claude can drive autonomously, Roslyn code navigation, and Test Explorer integration. The IDE half of Claude Code's integration protocol. Community-built, unofficial.

    Community firish
    uiNerd16

    @aicanvas/mcp

    Open-source React and Tailwind component marketplace. Install via the shadcn CLI or your AI editor over MCP, with reproduction prompts for Claude Code, Lovable, and V0.

    Community uiNerd16