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
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ Every link in `README.md` must be absolute: `https://github.com/modern-python/<r
or `.../tree/main/<path>` for a directory. Never a relative path: `README.md` is also the PyPI long
description, and PyPI does not rewrite relative links, so a relative one 404s on the package page.

[`skills/release-scope/SKILL.md`](skills/release-scope/SKILL.md) describes the CLI flags, exit codes, and report fields
for agents, and pins the minor version it describes. Update it, and its version range, in the same change as any of those.

## Agent skills

### Issue tracker
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,20 @@ jobs of a finished pipeline keyed by its `updated_at`, so a retried job invalida
the run collected, entries it did not use are dropped; other projects keep theirs, so one cache file serves both
group and `--jira` runs. A missing, corrupt, or older-schema cache is ignored with a warning; the cache only saves
requests and never changes the report.

## Agent skill

[`skills/release-scope`](https://github.com/modern-python/release-scope/tree/main/skills/release-scope) is an agent
skill that runs `release-scope` through `uvx` and answers release questions from the report. Ask your coding agent
what in the current repository has not reached production, what a group will ship with the next tag, or whether a
Jira issue is released and which services it touches. For the current repository the skill takes `--project` from
the git remote. It keeps the report and cache outside the repository and never writes to GitLab or Jira.

Install it with [skills](https://github.com/vercel-labs/skills):

```sh
npx skills add modern-python/release-scope
```

The agent reads the same environment variables as the CLI, so set them first as described under Configuration.
The skill runs `release-scope>=0.3,<0.4`, the range whose flags and report schema it describes.
100 changes: 100 additions & 0 deletions skills/release-scope/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
name: release-scope
description: >
Run the release-scope CLI through uvx to find what sits between production and the default branch of GitLab
services: pending merge requests and commits, tags, environments, failed jobs, and Jira issues with their status.
Use when the user asks what is not in production yet, what will ship with the next release or tag, whether a Jira
issue is released or which services it touches, or wants a release page for a GitLab wiki, for the current
repository, a GitLab group, or a list of projects, even if they do not name release-scope.
---

# release-scope

`release-scope` is a read-only CLI on PyPI. It never writes to GitLab or Jira, so it needs no approval to run.
Always run it through uvx with this version range; it matches the flags and report schema described here:

```bash
uvx --from 'release-scope>=0.3,<0.4' release-scope --help
```

## Check the settings

Every setting is an environment variable. List which ones are set without printing their values:

```bash
env | cut -d= -f1 | grep -E '^(RELEASE_SCOPE_|GITLAB_TOKEN$|JIRA_TOKEN$)' | sort
```

| Variable | Needed for |
|---|---|
| `RELEASE_SCOPE_GITLAB__ENDPOINT` | Any run; defaults to `https://gitlab.com` |
| `RELEASE_SCOPE_GITLAB__TOKEN` or `GITLAB_TOKEN` | Any run; `read_api` scope |
| `RELEASE_SCOPE_ENVIRONMENTS` | Environments to show, a JSON list such as `'["prod", "preview"]'` |
| `RELEASE_SCOPE_PRODUCTION_ENVIRONMENT` | The environment whose deployment starts the range; defaults to `production` |
| `RELEASE_SCOPE_JIRA_ENDPOINT` and `RELEASE_SCOPE_JIRA_TOKEN` (or `JIRA_TOKEN`) | Jira summaries and statuses; required for `--jira` |

If a required variable is missing, tell the user which one and stop; do not guess a value or ask them to paste a
token into the chat. Never echo a token.

## Choose the scope

- The current repository: pass its GitLab path as `--project`. Take it from `git remote get-url origin`, drop the
host and the trailing `.git`: `git@gitlab.example.com:team/backend/shop.git` and
`https://gitlab.example.com/team/backend/shop.git` both give `team/backend/shop`. If the remote host is not the
host of `RELEASE_SCOPE_GITLAB__ENDPOINT`, say so and ask for the project path.
- Groups or projects the user names: `--group` and `--project`, both repeatable and combinable.
`--include-subgroups` also collects subgroups of each group.
- Jira issue keys: `--jira KEY`, repeatable. It collects only the projects the issues link to, from production up to
the latest linked change. It cannot be combined with `--group` or `--project`.

## Collect and render

Keep the files outside the repository so they never land in its git tree. One cache file serves every run and only
saves requests:

```bash
out="${XDG_CACHE_HOME:-$HOME/.cache}/release-scope"
mkdir -p "$out"
uvx --from 'release-scope>=0.3,<0.4' release-scope collect --project team/backend/shop \
--output "$out/report.json" --cache "$out/cache.json"; \
uvx --from 'release-scope>=0.3,<0.4' release-scope render "$out/report.json" --output "$out/report.md"
```

Chain with `;`, not `&&`: `render` should still run when `collect` exits `1`.

Exit codes of `collect`:

- `0`: every service collected.
- `1`: the report is written, but some service failed or a Jira request failed or a `--jira` key does not exist.
The messages are on stderr and in the report; summarize the rest and name what failed.
- `2`: a configuration or usage error, such as a missing token or bad flags.
- `3`: GitLab rejected the token.
- `4`: a GitLab request for a group or project passed on the command line failed, for example one the token cannot see.

For `2` to `4` nothing was written; show the message and stop.

## Summarize the report

Read `report.json` and answer the user's question from it, briefly. Point to `report.md` for the full page; it is
Markdown for a GitLab wiki, and publishing it is the user's call.

- `services[]`: `project`, `environments` (what each environment runs), `rows` (newest first, from the default
branch head down to production), `warnings`, `error`.
- A row is one merged merge request or a direct commit: `merge_requests`, `commits`, `tags` pointing into it,
`environments` already running it, `jira_keys`, and `main_pipeline` with `failed_jobs`. Tag pipelines carry their
own `failed_jobs`.
- A service with no rows is up to date with production.
- `jira.issues` by key: `summary`, `status`, `status_category` (anything but `done` is not done), `links` to GitLab
merge requests and commits. `jira.missing` lists keys Jira did not return; `jira.error` a failed request. `jira` is
`null` without a Jira token.
- In a `--jira` report, `jira_scope` lists the issues, rows with `linked: true` are the ones the issues point to, and
each service has a `release`:
- `pending` with `tag`: that tag ships the issue; without `tag`, a new tag is needed.
- `in_production`: every linked merge request is already deployed.
- `not_merged`: only open merge requests link to it.
- `not_found`: the linked change is not on the default branch within the range.
- `pending_merge_requests`: open or merged-elsewhere merge requests, listed in every state.

Lead with what needs attention: failed services, failed jobs without `allow_failure`, Jira issues that are not done,
and releases that need a new tag or are not merged. Deployment data comes from GitLab environments; it shows what was
deployed, not proof of what serves traffic.
Loading