release-scope 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {release_scope-0.3.0 → release_scope-0.3.1}/PKG-INFO +33 -2
  2. {release_scope-0.3.0 → release_scope-0.3.1}/README.md +32 -1
  3. {release_scope-0.3.0 → release_scope-0.3.1}/pyproject.toml +1 -1
  4. {release_scope-0.3.0 → release_scope-0.3.1}/pyproject.toml.orig +1 -1
  5. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_gitlab.py +1 -0
  6. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_render.py +16 -2
  7. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_report.py +1 -0
  8. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_use_case.py +1 -0
  9. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/__init__.py +0 -0
  10. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/__main__.py +0 -0
  11. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_cache.py +0 -0
  12. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_errors.py +0 -0
  13. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_files.py +0 -0
  14. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_jira.py +0 -0
  15. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_jira_keys.py +0 -0
  16. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_links.py +0 -0
  17. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_messages.py +0 -0
  18. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_rows.py +0 -0
  19. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/_settings.py +0 -0
  20. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/ioc.py +0 -0
  21. {release_scope-0.3.0 → release_scope-0.3.1}/release_scope/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: release-scope
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Collect what sits between production and the default branch across GitLab services: tags, MRs, Jira keys, failed jobs
5
5
  Keywords: release,gitlab,jira,deployments,merge-requests,ci,cli,python
6
6
  Author: Artur Shiriev
@@ -31,11 +31,24 @@ Project-URL: Issues, https://github.com/modern-python/release-scope/issues
31
31
  Project-URL: Changelog, https://github.com/modern-python/release-scope/releases
32
32
  Description-Content-Type: text/markdown
33
33
 
34
+ <p align="center">
35
+ <picture>
36
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/modern-python/.github/main/brand/projects/release-scope/lockup-dark.svg">
37
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/modern-python/.github/main/brand/projects/release-scope/lockup-light.svg">
38
+ <img alt="release-scope" src="https://raw.githubusercontent.com/modern-python/.github/main/brand/projects/release-scope/lockup.png" width="420">
39
+ </picture>
40
+ </p>
41
+
34
42
  [![PyPI version](https://img.shields.io/pypi/v/release-scope.svg)](https://pypi.org/project/release-scope/)
35
43
  [![Supported Python versions](https://img.shields.io/pypi/pyversions/release-scope.svg)](https://pypi.org/project/release-scope/)
44
+ [![Downloads](https://static.pepy.tech/badge/release-scope/month)](https://pepy.tech/projects/release-scope)
36
45
  [![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](https://github.com/modern-python/release-scope/actions/workflows/ci.yml)
37
46
  [![CI](https://github.com/modern-python/release-scope/actions/workflows/ci.yml/badge.svg)](https://github.com/modern-python/release-scope/actions/workflows/ci.yml)
38
47
  [![License](https://img.shields.io/github/license/modern-python/release-scope.svg)](https://github.com/modern-python/release-scope/blob/main/LICENSE)
48
+ [![GitHub stars](https://img.shields.io/github/stars/modern-python/release-scope)](https://github.com/modern-python/release-scope/stargazers)
49
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
50
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
51
+ [![ty](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json)](https://github.com/astral-sh/ty)
39
52
 
40
53
  `release-scope` collects what sits between production and the default branch across GitLab services: tags, MRs,
41
54
  Jira issues, failed jobs.
@@ -126,7 +139,8 @@ uvx release-scope collect --group team/backend --output report.json --cache cach
126
139
  uvx release-scope render report.json --output report.md
127
140
  ```
128
141
 
129
- The page opens with a table of the services that have pending changes or problems, with the ref each environment runs;
142
+ The page opens with a table of the services that have pending changes or problems, with the ref each environment runs
143
+ and a GitLab compare link from production to the newest pending tag (to the release tag in a `--jira` report);
130
144
  services already up to date collapse into one expandable table. Each service with changes then has a collapsible table
131
145
  of its rows: the tag linked to its pipeline, the merge requests or direct commit, Jira keys with summary and status,
132
146
  the other services its Jira issues link to, where the change is deployed, and the failed jobs of its main-branch
@@ -146,3 +160,20 @@ jobs of a finished pipeline keyed by its `updated_at`, so a retried job invalida
146
160
  the run collected, entries it did not use are dropped; other projects keep theirs, so one cache file serves both
147
161
  group and `--jira` runs. A missing, corrupt, or older-schema cache is ignored with a warning; the cache only saves
148
162
  requests and never changes the report.
163
+
164
+ ## Agent skill
165
+
166
+ [`skills/release-scope`](https://github.com/modern-python/release-scope/tree/main/skills/release-scope) is an agent
167
+ skill that runs `release-scope` through `uvx` and answers release questions from the report. Ask your coding agent
168
+ what in the current repository has not reached production, what a group will ship with the next tag, or whether a
169
+ Jira 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 never writes to GitLab or Jira.
171
+
172
+ Install it with [skills](https://github.com/vercel-labs/skills):
173
+
174
+ ```sh
175
+ npx skills add modern-python/release-scope
176
+ ```
177
+
178
+ The agent reads the same environment variables as the CLI, so set them first as described under Configuration.
179
+ The skill runs `release-scope>=0.3,<0.4`, the range whose flags and report schema it describes.
@@ -1,8 +1,21 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/modern-python/.github/main/brand/projects/release-scope/lockup-dark.svg">
4
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/modern-python/.github/main/brand/projects/release-scope/lockup-light.svg">
5
+ <img alt="release-scope" src="https://raw.githubusercontent.com/modern-python/.github/main/brand/projects/release-scope/lockup.png" width="420">
6
+ </picture>
7
+ </p>
8
+
1
9
  [![PyPI version](https://img.shields.io/pypi/v/release-scope.svg)](https://pypi.org/project/release-scope/)
2
10
  [![Supported Python versions](https://img.shields.io/pypi/pyversions/release-scope.svg)](https://pypi.org/project/release-scope/)
11
+ [![Downloads](https://static.pepy.tech/badge/release-scope/month)](https://pepy.tech/projects/release-scope)
3
12
  [![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](https://github.com/modern-python/release-scope/actions/workflows/ci.yml)
4
13
  [![CI](https://github.com/modern-python/release-scope/actions/workflows/ci.yml/badge.svg)](https://github.com/modern-python/release-scope/actions/workflows/ci.yml)
5
14
  [![License](https://img.shields.io/github/license/modern-python/release-scope.svg)](https://github.com/modern-python/release-scope/blob/main/LICENSE)
15
+ [![GitHub stars](https://img.shields.io/github/stars/modern-python/release-scope)](https://github.com/modern-python/release-scope/stargazers)
16
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
17
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
18
+ [![ty](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json)](https://github.com/astral-sh/ty)
6
19
 
7
20
  `release-scope` collects what sits between production and the default branch across GitLab services: tags, MRs,
8
21
  Jira issues, failed jobs.
@@ -93,7 +106,8 @@ uvx release-scope collect --group team/backend --output report.json --cache cach
93
106
  uvx release-scope render report.json --output report.md
94
107
  ```
95
108
 
96
- The page opens with a table of the services that have pending changes or problems, with the ref each environment runs;
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);
97
111
  services already up to date collapse into one expandable table. Each service with changes then has a collapsible table
98
112
  of its rows: the tag linked to its pipeline, the merge requests or direct commit, Jira keys with summary and status,
99
113
  the other services its Jira issues link to, where the change is deployed, and the failed jobs of its main-branch
@@ -113,3 +127,20 @@ jobs of a finished pipeline keyed by its `updated_at`, so a retried job invalida
113
127
  the run collected, entries it did not use are dropped; other projects keep theirs, so one cache file serves both
114
128
  group and `--jira` runs. A missing, corrupt, or older-schema cache is ignored with a warning; the cache only saves
115
129
  requests and never changes the report.
130
+
131
+ ## Agent skill
132
+
133
+ [`skills/release-scope`](https://github.com/modern-python/release-scope/tree/main/skills/release-scope) is an agent
134
+ skill that runs `release-scope` through `uvx` and answers release questions from the report. Ask your coding agent
135
+ what in the current repository has not reached production, what a group will ship with the next tag, or whether a
136
+ Jira issue is released and which services it touches. For the current repository the skill takes `--project` from
137
+ the git remote. It keeps the report and cache outside the repository and never writes to GitLab or Jira.
138
+
139
+ Install it with [skills](https://github.com/vercel-labs/skills):
140
+
141
+ ```sh
142
+ npx skills add modern-python/release-scope
143
+ ```
144
+
145
+ The agent reads the same environment variables as the CLI, so set them first as described under Configuration.
146
+ The skill runs `release-scope>=0.3,<0.4`, the range whose flags and report schema it describes.
@@ -25,7 +25,7 @@ classifiers = [
25
25
  "Typing :: Typed",
26
26
  "Topic :: Software Development :: Build Tools",
27
27
  ]
28
- version = "0.3.0"
28
+ version = "0.3.1"
29
29
  dependencies = [
30
30
  "typer>=0.13",
31
31
  "pydantic>=2; python_version < '3.12'",
@@ -17,7 +17,7 @@ classifiers = [
17
17
  "Typing :: Typed",
18
18
  "Topic :: Software Development :: Build Tools",
19
19
  ]
20
- version = "0.3.0"
20
+ version = "0.3.1"
21
21
  dependencies = [
22
22
  "typer>=0.13",
23
23
  # The first release whose pydantic-core ships a wheel for each interpreter.
@@ -28,6 +28,7 @@ class Project(pydantic.BaseModel):
28
28
 
29
29
  class Deployable(pydantic.BaseModel):
30
30
  web_url: str | None = None
31
+ tag: bool = False
31
32
 
32
33
 
33
34
  class Deployment(pydantic.BaseModel):
@@ -2,6 +2,7 @@ import collections.abc
2
2
  import datetime
3
3
  import html
4
4
  import typing
5
+ from urllib.parse import quote
5
6
 
6
7
  from release_scope._report import (
7
8
  EnvironmentState,
@@ -131,11 +132,23 @@ def _not_done(service: Service, issues: dict[str, JiraIssue]) -> str:
131
132
  return f"{count} not done" if count else ""
132
133
 
133
134
 
134
- def _summary_row(service: Service, environments: list[str], jira: JiraState | None) -> list[str]:
135
+ def _compare(service: Service, production: str) -> str:
136
+ start: typing.Final = _environment(service, production)
137
+ release: typing.Final = service.release
138
+ tag: typing.Final = release.tag if release else next((tag for row in service.rows for tag in row.tags), None)
139
+ if start is None or tag is None:
140
+ return ""
141
+ base, label = (start.ref, _cell(start.ref)) if start.tag else (start.sha, f"`{start.sha[:8]}`")
142
+ return _link(f"{label}...{_cell(tag.name)}", f"{service.project_url}/-/compare/{quote(base)}...{quote(tag.name)}")
143
+
144
+
145
+ def _summary_row(service: Service, report: Report, environments: list[str]) -> list[str]:
146
+ jira: typing.Final = report.jira
135
147
  return [
136
148
  _link(_cell(service.project), service.project_url),
137
149
  *(_environment_ref(_environment(service, name)) for name in environments),
138
150
  _pending(service),
151
+ _compare(service, report.production_environment),
139
152
  *([_not_done(service, jira.issues)] if jira else []),
140
153
  _failure_counts(service),
141
154
  ]
@@ -301,10 +314,11 @@ def render_markdown(report: Report) -> str:
301
314
  "Service",
302
315
  *(_cell(name) for name in environments),
303
316
  "Pending",
317
+ "Compare",
304
318
  *(["Jira"] if jira else []),
305
319
  "Failed jobs",
306
320
  ]
307
- lines.extend([*_table(header, (_summary_row(service, environments, jira) for service in attention)), ""])
321
+ lines.extend([*_table(header, (_summary_row(service, report, environments) for service in attention)), ""])
308
322
  else:
309
323
  lines.extend(["All services are up to date.", ""])
310
324
  if up_to_date:
@@ -70,6 +70,7 @@ class EnvironmentState(pydantic.BaseModel):
70
70
  sha: str
71
71
  deployed_at: str
72
72
  deployment_url: str | None
73
+ tag: bool = False
73
74
 
74
75
 
75
76
  class Release(pydantic.BaseModel):
@@ -51,6 +51,7 @@ def _environment_state(name: str, deployment: Deployment) -> EnvironmentState:
51
51
  sha=deployment.sha,
52
52
  deployed_at=deployment.created_at,
53
53
  deployment_url=deployment.deployable.web_url if deployment.deployable else None,
54
+ tag=deployment.deployable.tag if deployment.deployable else False,
54
55
  )
55
56
 
56
57