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
55 changes: 51 additions & 4 deletions .github/workflows/release-pypi.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
name: publish-pypi

on:
release:
types: [published]
push:
tags:
- "v*"

permissions:
contents: read
contents: write
Comment on lines 8 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict contents write access to the release job

This workflow-level grant is inherited by the build job, so checkout, dependency setup, build commands, and third-party actions all run with a token capable of modifying repository contents even though only create-github-release needs that privilege. A compromised dependency or action during a tag build could therefore alter tags or repository content; keep workflow/build access at contents: read and grant contents: write only on the release-creation job.

Useful? React with 👍 / 👎.


jobs:
build:
Expand Down Expand Up @@ -52,9 +50,58 @@ jobs:
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

publish-mcp-registry:
create-github-release:
runs-on: ubuntu-latest
needs: publish-pypi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate release notes before publishing to PyPI

When a pushed tag lacks the exact ## <version> - changelog heading, publish-pypi has already completed before this job runs, so the extractor exits after an immutable PyPI version has been published but before the GitHub Release and MCP Registry entry are created. Correcting the changelog in a later commit will not change the tagged checkout, while rerunning the whole workflow can fail on the duplicate PyPI upload; perform the deterministic changelog extraction/validation before the publish job and pass the generated notes forward.

AGENTS.md reference: AGENTS.md:L170-L179

Useful? React with 👍 / 👎.

steps:
- uses: actions/checkout@v7

- name: Extract changelog section
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
python - <<'PY'
from pathlib import Path
import os

tag = os.environ["RELEASE_TAG"]
version = tag.removeprefix("v")
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8").splitlines()

start = None
end = None
heading = f"## {version} - "
for index, line in enumerate(changelog):
if line.startswith(heading):
start = index
continue
if start is not None and line.startswith("## "):
end = index
break

if start is None:
raise SystemExit(
f"Could not find CHANGELOG.md section for version {version}."
)

if end is None:
end = len(changelog)

section = "\n".join(changelog[start:end]).strip() + "\n"
Path("release-notes.md").write_text(section, encoding="utf-8")
PY

- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
body_path: release-notes.md
generate_release_notes: false

publish-mcp-registry:
runs-on: ubuntu-latest
needs: create-github-release
permissions:
id-token: write # required for GitHub OIDC authentication with MCP Registry
contents: read
Expand Down
35 changes: 29 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,32 @@ not part of `check` itself so the default gate stays fast.

## Release

1. Bump version in `pyproject.toml`, `src/deep_agentic_core_mcp/__init__.py`, and `CHANGELOG.md`
2. Commit: `git commit -am "release: vX.Y.Z"`
3. Tag: create an annotated `vX.Y.Z` tag and use the latest `CHANGELOG.md`
release section as the tag description
4. Push: `git push origin main --tags`
5. Create a GitHub Release — the workflow publishes to PyPI and the MCP Registry
Two phases, split by the merge to `main` — bumping happens before, and the
tag-driven release automation happens after.

**1. Pre-release (on the feature branch, before merge):** Bump version in
`pyproject.toml`, `src/deep_agentic_core_mcp/__init__.py`, and
`CHANGELOG.md` (a dated release section under `[Unreleased]`). Commit as
part of the branch's normal history; goes in with the rest of the PR.

**2. Release (on `main`, once that branch has merged):**

1. Pull the merge commit on `main`.
2. Tag: create an annotated `vX.Y.Z` tag pointing at the merge commit,
using the `CHANGELOG.md` release section for that version as the tag
message:
`git tag -a vX.Y.Z -F <file-with-that-section> --cleanup=verbatim`.
`--cleanup=verbatim` is required — git's default cleanup silently strips
lines starting with `#`, which would eat the changelog's `###` headers.
3. Push the tag: `git push origin vX.Y.Z`.

That tag push is the release trigger. `release-pypi.yml` runs automatically
from the same tag and does all of the following:

- publishes the package to PyPI via Trusted Publishing (OIDC)
- creates the GitHub Release object for `vX.Y.Z`
- publishes the server to the MCP Registry

The GitHub Release title is the tag name, and its body is copied from the
matching `CHANGELOG.md` section so the changelog, tag, PyPI release,
GitHub Releases page, and MCP Registry publish all stay aligned.
16 changes: 16 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,29 @@ Goals:
- surface incident, evaluation, and readiness evidence through one interface
- expose a high-level control surface for the main developer questions:
what happened, what changed, what failed, and is this workflow ready
- define the first Control Tower integration path once
`agenticops-control-tower` ships a real control API, starting with
read-only operator queries and keeping authorization-sensitive write
operations out of scope until audit/auth boundaries are clear

Possible tools:

- `core.compare_runs`
- `core.export_report`
- `core.incident_summary`
- `core.release_check`
- `control_tower.list_agents`
- `control_tower.list_unhealthy_agents`
- `control_tower.capability_summary`

Control Tower integration notes:

- `deep-agentic-core-mcp` should connect to `agenticops-control-tower` as a
control-plane connector, not reimplement control-plane logic locally
- first scope should mirror `agenticops-control-tower`'s planned MCP
connector direction: inventory, health, version, and posture queries
- write-capable Control Tower actions should come only after the sibling
package exposes stable authorization and audit semantics

## Phase 5: Publishing and Adoption

Expand Down
Loading