mirror of
https://github.com/apache/airflow.git
synced 2026-11-04 07:12:48 +00:00
* Add pr-stats skill for open-PR backlog statistics
Companion to the pr-triage skill — read-only aggregation of open
PRs on apache/airflow (or another target repo), producing the two
tables that 'breeze pr stats' prints: 'Triaged PRs — Final State
since <cutoff>' and 'Triaged PRs — Still Open', both grouped by
area:* label with per-area age-bucket histograms.
Shape follows the airflow-translations / pr-triage convention:
- .github/skills/pr-stats/ holds the canonical content — SKILL.md
as entry point plus four topic files (fetch.md, classify.md,
aggregate.md, render.md).
- .claude/skills/pr-stats is a committed symlink so Claude Code
picks up the skill without per-developer setup; .gitignore is
updated to let the symlink through.
- .pre-commit-config.yaml adds pr-stats/SKILL.md to the agentic-
markdown license-header exclusion (same treatment as pr-triage).
Design choices:
- Triage-detection logic is the same as pr-triage's: the canonical
'Pull Request quality criteria' marker authored by any maintainer.
The skill deliberately refers back to pr-triage/classify.md so the
two stay in sync.
- No mutations, no per-PR drill-in, no timeline/trend charts. Single
snapshot, two tables, one legend, one summary line.
- Budget: roughly 10 GraphQL calls regardless of backlog size
(~6 paginated for open PRs, ~2 for closed-since, 1 pre-flight,
1 viewer login). No per-PR REST calls.
* pr-stats: document GitHub search-index lag + Python 3.14 JSON strict-mode
Two gotchas encountered while actually running the skill against
apache/airflow:
- GitHub's search 'issueCount' for closed/merged date predicates
is heavily under-reported compared to the REST /pulls endpoint
(37 vs. ~30/day reality). Free-text search for the triage
marker 'Pull Request quality criteria' is even further behind
(164 PRs matched despite dozens of posts per day). Calling out
that the search-driven path is a biased sample, and suggesting
a REST-plus-aliased-GraphQL hybrid for accurate closed-since
numbers when the maintainer needs them.
- Python 3.14 json.load is strict about control characters in
strings by default, and GitHub comment bodyText routinely
contains raw tabs/newlines. Document strict=False, the
'gh api --jq' alternative, and the save-to-file fallback.
Explicitly warn against replacing control characters
pre-parse — that silently corrupts genuine escape sequences.
* pr-stats: render with Rich (not Markdown), add auto-triage state markers
Two fixes after running the skill end-to-end and seeing the output fall
apart on a real terminal:
- Markdown tables did not survive width. Table 2 has 25 columns; most
Markdown viewers collapsed it into wrapped pipe-delimited prose that
no longer reads as a table. Switch the default render path to
rich.table.Table — same library breeze pr stats and breeze pr
auto-triage use — which computes column widths from the actual
terminal, overflows horizontally, and supports inline colour markup.
Markdown is now a fallback (pipe/emoji mode), used only when the
maintainer asks for shareable output or when stdout is not a tty.
- Add an explicit 'By triage state' panel after Table 2 that slices
the full open-PR set into the same four markers auto-triage uses:
Ready for review / Responded / Waiting for Author / not yet triaged.
Colour scheme mirrors auto-triage exactly (bold green / bright_cyan /
yellow / blue) so the marker vocabulary transfers between skills.
render.md is rewritten to describe the new shape in full: the colour
mapping table, the state-breakdown panel with its counting rules, the
Rich table setup (show_lines, show_footer, TOTAL-row styling that
matches breeze pr stats), and the Markdown-fallback emoji rules for
the cases when Rich colour is unavailable.
* pr-stats: detect triage markers from 'breeze pr auto-triage' staleness path
The breeze pr auto-triage tool has two triage-comment templates:
- Violations path — embeds a visible Markdown link whose anchor text
is 'Pull Request quality criteria' (matches the pr-triage skill).
- Staleness path — ends the body with an HTML comment
'<!-- Pull Request quality criteria -->' as a hidden marker,
but the visible body contains no 'Pull Request quality criteria'
text at all.
GitHub's GraphQL exposes two fields: bodyText strips HTML comments,
body preserves them. The previous skill fetch used bodyText, so any
PR that was only auto-triaged via the staleness path was invisible
to the classifier. On a 40-PR sample from apache/airflow, ~10% of
triaged-marker comments were HTML-comment-only.
Changes:
- fetch.md: switch the comments subfield from bodyText to body in
both the open-PR query and the closed-since query. Add a new
'Why body, not bodyText' section explaining the breeze staleness
case with the exact template shape so future edits don't revert.
- classify.md: rewrite the 'Triage marker' rule to specify the
body field explicitly, and add a table enumerating the three
marker-producing paths (pr-triage skill, breeze violations,
breeze staleness) so both forms of the marker are recognised
as legitimate triage.
* pr-stats: collapse Table 2 age buckets from 6 to 4
The six-bucket split (<1d, 1-3d, 3-7d, 1-2w, 2-4w, >4w) was exposing
a distinction that doesn't map to different maintainer decisions. In
practice an author who replied 2 days ago vs. 5 days ago is in the
same state — actively iterating — and the next question is whether
they're inside the review week at all. Same for 2-4w vs >4w: both
mean 'stale enough to nudge'.
New four-bucket split:
<1d fresh push / just active
1-7d within the current review week
1-4w inside the triage-response window
>4w stale; needs maintainer intervention
That drops eight columns from Table 2 (two from Drafted, two from
Author resp, each of which appeared twice in the column set), taking
the open-PR table from 25 columns down to 21. Rich can still render
it horizontally, but the noise-to-signal ratio improves — every
remaining bucket maps to a distinct intervention.
* pr-stats: make hybrid REST+GraphQL the default path for Table 1
The search-based path was returning 28 triaged+closed PRs over a six-
week apache/airflow window. The real count (verified by scanning every
non-bot closed/merged PR's comments) is 204 — a 7.3x undercount.
The hybrid path documented earlier in fetch.md is now the default:
1. Enumerate the closed/merged set via REST /pulls?state=closed&sort=
updated, paginate until closed_at crosses the cutoff, filter bots.
2. Batch-fetch comments in aliased GraphQL queries of 30 PRs each
(each alias pulls the last 25 comments of one PR). Budget on
apache/airflow: ~20 REST + ~54 GraphQL calls, about 60 seconds
end-to-end for a six-week window.
Keep the free-text-search path as an explicit fast-closed opt-in
that prints a caveat above Table 1 so a maintainer who takes the
fast path knows the numbers are under-reported.
* pr-stats: contributor-only counts in Table 2, Contrib. right after Total
Reorder and rescope Table 2 so the columns answer 'how is the
contributor queue doing', not 'how many open PRs exist in this area
mixed together'. Concretely:
- Move Contrib. and %Contrib. to the second and third columns, right
after Total. They describe the area composition — that belongs up
front so every subsequent column reads as 'of the contributor work'.
- Make every counter below Contrib. contributor-only: Draft, Non-Draft,
Triaged, Responded, Ready, Drafted by triager, age-bucket histograms.
Total is kept as a reference-only column but does not feed any
denominator except %Contrib.
- %Draft, %Ready and the age-bucket semantics switch to the contributor
denominator, so a 35% draft rate means 35% of contributor work in
the area is in draft — not 35% of the area including maintainer PRs.
aggregate.md now documents scope per field (all-PR vs contributor-only)
plus invariants (contributors == drafts + non_drafts, etc.) and a
compact percentage-rules section. render.md lists the new column order
with an explicit denominator column, and a one-line rationale
explaining why contributor-scoping keeps the percentages meaningful.
* fixup! pr-stats: contributor-only counts in Table 2, Contrib. right after Total
* Remove `breeze pr stats`, replaced by the `pr-stats` skill
The new `pr-stats` skill is a drop-in replacement for `breeze pr stats`
— same two tables (Triaged Final State, Triaged Still Open), same
area grouping, same colour scheme, just produced by a Claude Code
skill instead of a Python click command. With this PR's earlier
commits removing `breeze pr auto-triage`, that leaves the `breeze pr`
group with no subcommands, so the entire group is removed.
Code removal:
- `dev/breeze/src/airflow_breeze/commands/pr_commands.py` (1,176 lines)
and `pr_commands_config.py` deleted.
- `dev/breeze/src/airflow_breeze/utils/pr_cache.py`,
`pr_models.py`, `pr_vault.py` deleted (used only by the removed
command).
- `dev/breeze/tests/test_pr_cache.py`, `test_pr_models.py`,
`test_pr_vault.py`, `test_author_cache.py` deleted.
- `dev/breeze/src/airflow_breeze/breeze.py` no longer imports
`pr_group`.
- `dev/breeze/src/airflow_breeze/configure_rich_click.py` no longer
references `PR_COMMANDS` / `PR_PARAMETERS` and the "PR commands"
group is dropped from the breeze help layout.
- `dev/breeze/doc/images/output_pr{,_stats}.{svg,txt}` deleted; the
top-level help images (`output-commands.svg`,
`output_setup_check-all-params-in-groups.{svg,txt}`,
`output_setup_regenerate-command-images.{svg,txt}`) regenerate to
drop the `pr` row.
Documentation:
- `dev/breeze/doc/13_pr_tasks.rst` deleted (no breeze pr commands
remain). Index entries in `dev/breeze/doc/README.rst` and the
"Next step" pointer in `dev/breeze/doc/12_issues_tasks.rst` are
updated to skip straight to advanced breeze topics.
- `contributing-docs/25_maintainer_pr_triage.md` adds a "Backlog
statistics — the `pr-stats` skill" section that introduces the
skill, lists the recognised invocation phrasings, and notes that
the legacy HTML-comment markers left by the removed breeze command
are still detected.
- `contributing-docs/README.rst` entry expanded to mention both
skills.
- `.github/skills/pr-stats/{SKILL,render,classify,fetch}.md` updated
to describe `breeze pr stats` and `breeze pr auto-triage` in past
tense ("now-removed", "predecessor", "legacy"), since they no
longer exist as commands.
Validation: 727 breeze tests pass; prek pre-commit and manual stages
green; `breeze` CLI no longer registers a `pr` subcommand group.
60 lines
3.3 KiB
ReStructuredText
60 lines
3.3 KiB
ReStructuredText
.. Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
.. http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
.. Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
|
|
.. raw:: html
|
|
|
|
<div align="center">
|
|
<img src="images/AirflowBreeze_logo.png"
|
|
alt="Airflow Breeze - Development and Test Environment for Apache Airflow">
|
|
</div>
|
|
|
|
Airflow Breeze CI environment
|
|
=============================
|
|
|
|
Airflow Breeze is an easy-to-use development and test environment using
|
|
`Docker Compose <https://docs.docker.com/compose/>`_.
|
|
The environment is available for local use and is also used in Airflow's CI tests.
|
|
|
|
We call it *Airflow Breeze* as **It's a Breeze to contribute to Airflow**.
|
|
|
|
The advantages and disadvantages of using the Breeze environment vs. other ways of testing Airflow
|
|
are described in
|
|
`Integration test development environments </contributing-docs/06_development_environments.rst>`_.
|
|
|
|
You can use the Breeze environment to run Airflow's tests locally and reproduce CI failures.
|
|
|
|
The following documents describe how to use the Breeze environment:
|
|
|
|
* `Installation <01_installation.rst>`_ - describes how to install the Breeze environment on your machine.
|
|
* `Customizing <02_customizing.rst>`_ - describes how to customize the Breeze environment.
|
|
* `Developer tasks <03_developer_tasks.rst>`_ - describes how to use Breeze for regular developer tasks.
|
|
* `Troubleshooting <04_troubleshooting.rst>`_ - describes how to troubleshoot the Breeze environment.
|
|
* `Test commands <05_test_commands.rst>`_ - describes how to run Airflow's tests (and reproduce CI failures) using the Breeze environment.
|
|
* `Managing Docker images <06_managing_docker_images.rst>`_ - describes how to manage the Breeze images.
|
|
* `Breeze maintenance tasks <07_breeze_maintenance_tasks.rst>`_ - describes how to perform maintenance tasks when you develop Breeze itself.
|
|
* `CI tasks <08_ci_tasks.rst>`_ - describes how Breeze commands are used in our CI.
|
|
* `Release management tasks <09_release_management_tasks.rst>`_ - describes how to use Breeze for release management tasks.
|
|
* `UI tasks <10_ui_tasks.rst>`_ - describes how Breeze commands are used to support Apache Airflow project UI.
|
|
* `Registry tasks <11_registry_tasks.rst>`_ - describes how to use Breeze for provider registry data extraction.
|
|
* `Issues tasks <12_issues_tasks.rst>`_ - describes how Breeze commands are used to manage GitHub issues.
|
|
* `Advanced Breeze topics <14_advanced_breeze_topics.rst>`_ - describes advanced Breeze topics/internals of Breeze.
|
|
|
|
You can also learn more context and Architecture Decisions taken when developing Breeze in the
|
|
`Architecture Decision Records <adr>`_.
|
|
|
|
Next step: Follow the `Installation <01_installation.rst>`__ instructions to install the Breeze environment.
|