2121Jira issues, failed jobs.
2222
2323For every service it reads the latest successful production deployment, walks the default branch down to that
24- commit, and writes one JSON report: a row per merge request or direct commit, newest first, with the tags that
24+ commit, and writes a static site with one JSON report: a row per merge request or direct commit, newest first, with the tags that
2525point into it, the environments running it, the Jira keys its MR mentions, and the failed jobs of its main-branch
2626and tag pipelines. With a Jira token, it also reads the summary and status of every key in one batched search,
2727and the GitLab merge requests and commits linked to each issue. GitLab's Jira integration adds those links to the
@@ -32,13 +32,14 @@ issue's Web links whenever a commit or MR mentions it; a link counts only if it
3232
3333``` sh
3434export RELEASE_SCOPE_GITLAB__ENDPOINT=https://gitlab.example.com
35- export RELEASE_SCOPE_GITLAB__TOKEN=glpat-... # read_api scope; api for publish
35+ export RELEASE_SCOPE_GITLAB__TOKEN=glpat-... # read_api scope
3636export RELEASE_SCOPE_ENVIRONMENTS=' ["prod", "preview"]'
3737export RELEASE_SCOPE_PRODUCTION_ENVIRONMENT=prod
3838
39- uvx release-scope collect --group team/backend --output report.json --cache cache.json
39+ uvx release-scope collect --group team/backend --output public --cache cache.json
4040```
4141
42+ ` --output ` is a directory: ` collect ` writes ` report.json ` there, next to the page that shows it (see Site).
4243` --group ` and ` --project ` are repeatable and can be mixed. The command exits ` 1 ` when any service failed to
4344collect; the report is still written and names the error on that service. A service GitLab denies access to fails
4445alone, and its error lists the project settings and member page to check. A project with CI/CD or Environments
@@ -51,11 +52,13 @@ and also exits `1`; the GitLab part is still written.
5152` --jira ` scopes the report to Jira issues instead of groups or projects, and needs the Jira settings:
5253
5354``` sh
54- uvx release-scope collect --jira SHOP-140 --jira SHOP-141 --output report.json --cache cache.json
55+ uvx release-scope collect --jira SHOP-140 --jira SHOP-141 --output public --cache cache.json
5556```
5657
57- It reads the issues and their GitLab links, then collects every project they link to. In each project the rows run
58- from the production baseline up to the latest linked change, so they show everything that ships with the issues. The service
58+ It reads the issues and their GitLab links, then collects every project they link to. In each project the rows from
59+ the production baseline up to the latest linked change are in scope: they show everything that ships with the issues.
60+ Rows above that change are kept with ` in_scope: false ` , so their tags can still be picked, but their Jira keys are
61+ neither looked up nor counted as tasks of a release. The service
5962records the release state: ` pending ` with the nearest tag at or above that change (or none, when a new tag is
6063needed), ` in_production ` when every linked merge request is already deployed, ` not_merged ` when only open merge
6164requests link to it, or ` not_found ` . Open merge requests and merges into other branches are listed either way.
@@ -81,9 +84,10 @@ Every setting is an environment variable; nothing about a GitLab or Jira instanc
8184
8285The report is versioned by ` schema_version ` ; the models live in
8386[ ` release_scope/_report.py ` ] ( https://github.com/modern-python/release-scope/blob/main/release_scope/_report.py ) .
84- Top-level ` jira ` is ` null ` without a Jira token; otherwise it holds ` issues ` by key (summary, status, status
85- category, issue type, linked GitLab changes), the ` missing ` keys Jira did not return, and an ` error ` if a Jira
86- request failed. One row, trimmed:
87+ Top-level ` jira ` is ` null ` without a Jira token; otherwise it holds ` issues ` by key (summary, status, status category,
88+ issue type, linked GitLab changes), the ` missing ` keys Jira did not return, and an ` error ` if a Jira request failed.
89+ Each service lists its ` candidates ` : the tags a release could ship, newest first, each with its pipeline, the number of
90+ rows it ships, the in-scope Jira keys of those rows, and the compare link from production. One row, trimmed:
8791
8892``` json
8993{
@@ -97,60 +101,55 @@ request failed. One row, trimmed:
97101}
98102```
99103
100- ## Page
104+ ## Site
101105
102- ` render ` turns a report into a Markdown page for a GitLab wiki, without calling GitLab:
106+ Besides ` report.json ` , ` collect ` writes ` index.html ` and its script into the output directory. They come from the
107+ installed package and change only with it, so the page always matches the report schema. The page loads
108+ ` report.json ` from next to itself; it needs a web server, not a ` file:// ` URL.
103109
104- ``` sh
105- uvx release-scope collect --group team/backend --output report.json --cache cache.json; \
106- uvx release-scope render report.json --output report.md
107- ```
108-
109- The page opens with a table of the services that have pending changes or problems, with the ref each environment runs
110- and a GitLab compare link from production to the newest pending tag (to the release tag in a ` --jira ` report);
111- services already up to date collapse into one expandable table. Each service with changes then has a collapsible table
112- of its rows: the tag linked to its pipeline, the merge requests or direct commit, Jira keys with summary and status,
113- the other services its Jira issues link to, where the change is deployed, and the failed jobs of its main-branch
114- and tag pipelines. With Jira issues, the summary table also counts the issues per service whose status is not done.
115- A ` --jira ` report names its issues at the top, shows the tag to release per service, and marks the rows linked to
116- the issues.
117-
118- Chain the two commands with ` ; ` , not ` && ` : ` collect ` exits ` 1 ` when a service failed, which is exactly when the page
119- should show it. Alert on the exit code of ` collect ` , not on whether to render. ` render ` fails only when it cannot
120- read the report or write the page.
110+ ** Services** lists every service with a production deployment, and every service that failed to collect, as one
111+ line: what production runs, the picked tag, how many merge requests or commits and Jira tasks it ships, failed jobs,
112+ and a mark when the range was cut at ` RELEASE_SCOPE_MAX_COMMITS ` . Opening a line shows the service's environments,
113+ warnings, merge requests that are not merged yet, and its rows with tags and their pipelines, merge requests or
114+ commits, Jira keys, environments, and failed jobs; rows out of scope are dimmed. Each tag has a ** pick** button:
115+ picking it highlights the rows it ships and closes the line again. A ` --jira ` report starts with each service's
116+ release tag picked. Services without a production deployment are left out of the page.
121117
122- ## Wiki
118+ ** Release** at the bottom turns the picked tags into three lists, each with a copy button and a text box to copy from
119+ by hand, since browsers allow the copy button only over HTTPS:
123120
124- ` publish ` replaces the content of an existing page in a project wiki with a rendered page:
121+ - ** Jira tasks** : the keys of every in-scope row from each picked tag down to production, without duplicates, with
122+ summary and status, flagging issues that are not done. Copy them one per line or as a JQL ` key in (...) ` clause,
123+ each in its own box.
124+ - ** Tag pipelines** : the pipeline of each picked tag, as a Markdown list.
125+ - ** Compare** : a GitLab compare link per service from production to the picked tag, as a Markdown list.
125126
126- ``` sh
127- uvx release-scope publish report.md --project team/docs --page releases/backend
128- ```
127+ ## GitLab Pages
129128
130- ` --page ` is the page slug, as in its URL after ` /-/wikis/ ` . The page must already exist; ` publish ` never creates
131- one, so create it once in GitLab. It keeps the page title and format, and skips the write when the content is
132- unchanged, so a scheduled run does not add a page version every time. Publishing needs a token with the ` api ` scope
133- whose user has at least the Developer role in the wiki's project; a denied token exits ` 3 ` , a missing page or any
134- other failed request exits ` 4 ` . GitLab rejects pages larger than its wiki page size limit, 5 MB by default; the error
135- then names the size of the page.
136-
137- A scheduled GitLab CI job keeps the page current. It publishes even when a service failed, then fails the job:
129+ A scheduled pipeline publishes the site with [ GitLab Pages] ( https://docs.gitlab.com/user/project/pages/ ) . Keep it in
130+ a project of its own, such as ` team/release-report ` : Pages serves only the site of the project that runs the job,
131+ and its members are who can view it. ` collect ` reads the services through the API, so they need no change.
138132
139133``` yaml
140- release-page :
141- image : python:3 .13-slim
134+ release-report :
135+ image : ghcr.io/astral-sh/uv:python3 .13-trixie -slim
142136 rules :
143137 - if : $CI_PIPELINE_SOURCE == "schedule"
144138 script :
145- - pip install 'release-scope>=0.4,<0.5'
146- - release-scope collect --group team/backend --output report.json || status=$?
147- - release-scope render report.json --output report.md
148- - release-scope publish report.md --project team/docs --page releases/backend
149- - exit "${status:-0}"
139+ - uvx --from 'release-scope>=0.5,<0.6' release-scope collect --group team/backend --output public || [ $? -eq 1 ]
140+ pages : true
150141` ` `
151142
152- Set ` RELEASE_SCOPE_GITLAB__ENDPOINT` and a masked `RELEASE_SCOPE_GITLAB__TOKEN` as CI/CD variables of the project
153- that runs the job, along with the other settings.
143+ ` || [ $? -eq 1 ]` keeps the job green when only some services failed: the page shows their errors, and GitLab deploys
144+ Pages only from a successful job. A configuration error, a rejected token, or an unreachable group still fails the
145+ job and keeps the previous site. `pages : true` needs GitLab 17.6 and publishes `public` as the job artifact from 17.10;
146+ on older versions name the job `pages` and add `artifacts : {paths: [public]}`.
147+
148+ Set `RELEASE_SCOPE_GITLAB__ENDPOINT` and a masked `RELEASE_SCOPE_GITLAB__TOKEN` as CI/CD variables of the project,
149+ along with the other settings, then add a pipeline schedule. Without [Pages access
150+ control](https://docs.gitlab.com/administration/pages/#access-control), which an administrator of a self-managed
151+ instance turns on, a Pages site is public to anyone who can reach it, even for a private project. With it, set
152+ **Settings > General > Visibility > Pages** to *Only project members*.
154153
155154# # Cache
156155
@@ -167,8 +166,7 @@ requests and never changes the report.
167166skill that runs `release-scope` through `uvx` and answers release questions from the report. Ask your coding agent
168167what in the current repository has not reached production, what a group will ship with the next tag, or whether a
169168Jira issue is released and which services it touches. For the current repository the skill takes `--project` from
170- the git remote. It keeps the report and cache outside the repository, and publishes to a wiki page only when you ask
171- for it and name the page.
169+ the git remote. It keeps the report and cache outside the repository.
172170
173171Install it with [skills](https://github.com/vercel-labs/skills) :
174172
@@ -177,4 +175,4 @@ npx skills add modern-python/release-scope
177175` ` `
178176
179177The agent reads the same environment variables as the CLI, so set them first as described under Configuration.
180- The skill runs `release-scope>=0.4 ,<0.5 `, the range whose flags and report schema it describes.
178+ The skill runs `release-scope>=0.5 ,<0.6 `, the range whose flags and report schema it describes.
0 commit comments