Skip to content

feat: collect pending changes between production and the default branch - #1

Merged
lesnik512 merged 7 commits into
mainfrom
feat/mvp-collector
Sep 28, 2026
Merged

lesnik512 merged 7 commits into
mainfrom
feat/mvp-collector

Conversation

@lesnik512

@lesnik512 lesnik512 commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

First version of release-scope collect: for each selected GitLab service it writes one JSON report of everything between the commit running in production and the head of the default branch. Jira lookups (summary, status, "Release" notes, related services) are not included yet.

What a row is

The range is <production deployment sha>..<default branch> with first_parent=true, newest first. Each row is one merged MR or one direct commit:

  • merge-commit and squash repos: the merge or squash commit is matched to its MR from a single listing of merged MRs (updated_after = the oldest commit date in the range);
  • fast-forward/rebase repos: commits the listing doesn't match go through commits/:sha/merge_requests, keeping only merged MRs into the default branch. Commits of the same MR end up in the same row.

A row lists the tags pointing at its commits (each with its latest tag pipeline), the environments running one of its commits, the Jira keys found in the MR title, branch and description (or the commit message for direct commits), and the latest push pipeline on the default branch for its newest commit. Failed jobs include both jobs and bridges; allow_failure is reported rather than filtered out.

Design choices

  • Range starts at the deployed SHA, not a tag or badge (ADR-0002).
  • The cache holds only settled facts: commit to MR membership, and failed jobs of finished pipelines keyed by updated_at. It is pruned to what the run used, written atomically, and dropped on a schema mismatch (ADR-0001). When a service fails, its previous cache entries are kept.
  • Jira key regex: (?<![A-Za-z0-9])[A-Z][A-Z0-9]+-\d+(?![A-Z0-9]). Unlike a \b pattern, it catches keys in branch names like feature/ABC-1_x. An optional project-key allowlist drops false positives such as UTF-8.
  • Bridges come from the bridges route. trigger_jobs replaces it only from GitLab 19.2, and self-managed instances are often older.
  • There is no instance-specific default anywhere. Endpoint, environments and Jira settings all come from RELEASE_SCOPE_* env vars.
  • Exit code 1 when any service failed; the report is still written. Auth failures stop the whole run (exit 3).

Not in this PR

  • Jira batch lookup (JQL key in (...)) for summary, status and the "Release" section.
  • Related services via group MR search.
  • Following child pipelines behind a failed bridge; the downstream pipeline URL is reported instead.
  • Collecting projects in parallel.
  • The org profile row (MD1) and the PyPI Trusted Publisher, which need manual setup.

Checks

just lint-ci, just adr-check and just test-ci (100% line coverage) pass locally on 3.14. The suite also passes on 3.11 and at the declared dependency floors (uv pip compile --resolution lowest-direct then --no-build install, as the floors job does).

Review follow-ups

  • ADRs removed; the rationale above stays here instead.
  • Tests mock GitLab only with static respx routes through pytest-httpx2. There is no hand-rolled transport, no stateful fake and no callbacks, apart from respx's own sequential side_effect list for the multi-page test. The happy-path tests keep respx's assert_all_called; tests that stop early opt out one by one.
  • --version no longer falls back to "0" when package metadata is missing. Because of that, the floors job adds uv pip install --no-deps -e . after the org-standard install. The dependency floors are unchanged; the package just has to be installed for its metadata to exist. This is the one place this repo's _checks.yml differs from the org's floors snippet.
  • pydantic floors are per interpreter (2.0 / 2.0.2 / 2.8.2 / 2.12 for 3.11 / 3.12 / 3.13 / 3.14+), each the first release with pydantic-core wheels on both Linux x86_64 and macOS arm64.
  • pytest-httpx2 1.0.0 defines its httpx2 marker in a pytest_configure that the package never exports, so the marker is registered in pyproject.toml.

Comment thread docs/adr/0002-range-starts-at-the-deployed-sha.md Outdated
Comment thread tests/conftest.py Outdated
@lesnik512
lesnik512 merged commit f77b17a into main Sep 28, 2026
12 checks passed
@lesnik512
lesnik512 deleted the feat/mvp-collector branch September 28, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant