Auto-approve cheap CI runs of external contributors' PRs (#75455)
* Auto-approve cheap CI runs of external contributors' PRs GitHub holds the workflow runs of fork PRs until a maintainer approves them. With self-hosted runners (AIP-118) the approval gate becomes part of the trust model, so it should cover all external contributors, but approving every push by hand does not scale and makes contributors wait. Runs whose change cannot touch the CI definition and whose CI is cheap are safe to start without a maintainer. Expensive or large changes, and anything that changes how CI or runners are chosen, still get a human look first, which also keeps the load on the shared public runners down. The CI-minutes estimate lets maintainers see what a run will cost before approving it. Generated-by: Claude Opus 5 * Add inline script metadata to the CI-minutes calibration script The script uses only the standard library, so with a PEP 723 block it runs with plain `uv run dev/calibrate_ci_minutes_estimates.py` instead of syncing the whole Breeze environment. Document that invocation in the script and in .github/AGENTS.md. * Keep one PR's API or git error from aborting the approval tick Each PR is now processed in its own try block. A requests.RequestException or subprocess.CalledProcessError for one PR no longer stops the remaining PRs or skips the job summary. The failed PR is recorded with failed=True and shown as "failed" in the summary, keeping its CI-time estimate when one was computed and giving a short, single-line form of the error as the reason. The workflow also tries to add the 'need workflow approval' label to it, so it is not lost once its runs leave the query window. Nothing is approved on failure. approve_workflow_runs exits 1 after writing the summary when any PR failed, so a persistent failure turns the scheduled run red instead of passing silently. * Approve the runs of fork CI pull requests unless they change CI A pull request whose CI runs in the contributor's fork (AIP-120) still gets pull_request runs in apache/airflow, and GitHub holds them until a maintainer approves them. Those runs only execute the fork CI gate, so judging them by the cost and size of project CI left cheap gate-only runs waiting for a maintainer for no benefit, and a gated run that never ran could not be cleaned up by the reconciler. What still needs a maintainer is a change to the files that define CI, since it could remove the gate or add a workflow that does run. Using the reconciler's own list keeps the two decisions consistent, and the author is told why their runs wait instead of only seeing a label. Generated-by: Claude Opus 5 * Keep CI-minutes estimates true to the runs they approve A run selects its tests from the labels the PR had when it started, so approving it on the current labels could start a full-tests run whose label was removed while it waited. Calibrating from self-hosted and all-versions runs, and leaving out the jobs that need no CI image, made the estimate describe runs other than those it is used to approve. Generated-by: Claude Opus 5 --------- Co-authored-by: Shahar Epstein <60007259+shahar1@users.noreply.github.com>
No files matched your search
@@ -0,0 +1,38 @@
|
||||
<!-- SPDX-License-Identifier: Apache-2.0
|
||||
https://www.apache.org/licenses/LICENSE-2.0 -->
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||
|
||||
- [The `.github` folder — Agent Instructions](#the-github-folder--agent-instructions)
|
||||
- [Keep the CI-minutes estimates in sync with the workflows](#keep-the-ci-minutes-estimates-in-sync-with-the-workflows)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# The `.github` folder — Agent Instructions
|
||||
|
||||
## Keep the CI-minutes estimates in sync with the workflows
|
||||
|
||||
`breeze ci approve-workflow-runs` (run by `workflows/auto-approve-workflow-runs.yml`) decides whether
|
||||
to approve an external contributor's CI runs from an estimate of the job-minutes they take. The
|
||||
numbers live in `dev/breeze/src/airflow_breeze/utils/ci_minutes_estimate.py` and are medians
|
||||
measured on recent `Tests (AMD)` PR runs on public runners.
|
||||
|
||||
After you change the CI workflows in a way that adds, removes, splits or resizes jobs (new test
|
||||
groups, a changed matrix, new composite workflows, a move between runner types), refresh the
|
||||
estimates once the change has run on enough PRs, and in any case about once a month:
|
||||
|
||||
1. Run `uv run dev/calibrate_ci_minutes_estimates.py --since <date>`
|
||||
from the repository root with an authenticated `gh` CLI. Pick a date that covers at least a
|
||||
week of runs after the workflow change.
|
||||
2. Copy the medians and fits it prints into the constants of `ci_minutes_estimate.py`, and update
|
||||
the "Last calibrated" line next to them.
|
||||
3. When you add a new job group to the workflows, add a matching group to both
|
||||
`ci_minutes_estimate.py` (with the selective-check output that turns it on) and the
|
||||
`JOB_GROUPS` patterns of the calibration script. Unmatched jobs fall into the base group.
|
||||
4. Run `uv run --project dev/breeze pytest dev/breeze/tests/test_ci_minutes_estimate.py
|
||||
dev/breeze/tests/test_workflow_run_approval.py -xvs`.
|
||||
|
||||
The estimates cover public runners only. Self-hosted (RunsOn) runners need their own set once there
|
||||
is enough data from them.
|
||||
@@ -0,0 +1,68 @@
|
||||
# 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.
|
||||
#
|
||||
---
|
||||
# Approves the waiting workflow runs of external contributors' PRs to main when the change is safe to
|
||||
# run without a maintainer's look, and labels the others "need workflow approval". A PR whose CI runs
|
||||
# in the contributor's fork (AIP-120) is approved unless it changes CI definition files, and then gets
|
||||
# a comment saying why its runs wait. The rules are in
|
||||
# dev/breeze/src/airflow_breeze/utils/workflow_run_approval.py and documented in
|
||||
# contributing-docs/05_pull_requests.rst.
|
||||
#
|
||||
# This workflow runs only trusted code from main. It reads the PR's metadata, changed-file list and
|
||||
# git objects, and never checks out or runs the PR's code. Approving with GITHUB_TOKEN starts the
|
||||
# approved runs right away, and workflow_run workflows that follow them still trigger.
|
||||
name: Auto approve workflow runs
|
||||
on: # yamllint disable-line rule:truthy
|
||||
schedule:
|
||||
- cron: '*/30 * * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
report-only:
|
||||
description: "Only report the decisions and estimates, without approving or labelling"
|
||||
type: boolean
|
||||
default: false
|
||||
permissions:
|
||||
# Approving workflow runs.
|
||||
actions: write
|
||||
# Adding and removing the "need workflow approval" label, and commenting on a fork CI PR whose
|
||||
# CI change keeps its runs waiting.
|
||||
pull-requests: write
|
||||
contents: read
|
||||
concurrency:
|
||||
group: auto-approve-workflow-runs
|
||||
cancel-in-progress: false
|
||||
jobs:
|
||||
approve-workflow-runs:
|
||||
name: "Approve workflow runs of external contributors"
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'apache/airflow'
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: "Checkout main"
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: main
|
||||
- name: "Install Breeze"
|
||||
uses: ./.github/actions/breeze
|
||||
- name: "Approve workflow runs"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
REPORT_ONLY: ${{ inputs.report-only && 'true' || 'false' }}
|
||||
run: breeze ci approve-workflow-runs
|
||||
@@ -242,6 +242,47 @@ is the PMC private list — see the
|
||||
``private@airflow.apache.org``. That document also covers the further steps the project may
|
||||
take when the same behaviour persists across PRs.
|
||||
|
||||
CI workflow runs of external contributors
|
||||
-----------------------------------------
|
||||
|
||||
GitHub does not start the CI workflows of a PR from a fork until a maintainer approves them,
|
||||
for the contributors that the repository's approval setting covers. To keep you from waiting
|
||||
for a maintainer on every push, a scheduled workflow checks the waiting runs every 30 minutes
|
||||
and approves them automatically when all of these hold:
|
||||
|
||||
* The PR targets ``main``. PRs to release branches, such as ``v3-4-test``, always wait for a
|
||||
maintainer.
|
||||
* The PR does not change anything under ``.github/``, ``dev/breeze/`` or ``scripts/ci/``. Those
|
||||
files define the CI workflows and choose the runners they use.
|
||||
* The change does not need the full set of tests, does not change dependencies (``pyproject.toml``,
|
||||
lock files, ``package.json``, ``go.mod``, Gradle build files) and does not add a new provider.
|
||||
* The CI jobs your change selects are estimated to take at most 310 job-minutes, about a quarter of
|
||||
a full CI run. Changes to documentation, to the UI, to the Helm chart, to the language SDKs, to
|
||||
one area of Airflow core or to a small provider usually stay under it. Changes to large providers
|
||||
such as Amazon or Google, to several providers, or to the Task SDK (which runs the tests of all
|
||||
providers) usually do not.
|
||||
* The PR changes at most 100 lines of source code. Tests (including end-to-end tests),
|
||||
documentation, newsfragments, translations and lock files are not counted, so a fix with
|
||||
thorough tests still qualifies. Larger changes are usually new features, and a maintainer looks
|
||||
at them first.
|
||||
|
||||
If your PR's CI runs in your fork (it carries the ``fork ci required`` label), the CI run in
|
||||
``apache/airflow`` only checks that, so none of the rules above apply. Its runs are approved
|
||||
automatically unless the PR changes files that define CI: anything under ``.github/``,
|
||||
``dev/breeze/``, ``scripts/ci/``, ``scripts/docker/`` or ``scripts/in_container/``, a ``Dockerfile``
|
||||
or ``.pre-commit-config.yaml``. Then the runs wait for a maintainer and a comment on the PR explains
|
||||
why. CI in your fork runs either way.
|
||||
|
||||
Each new push is checked again, because approval applies to one commit. Only runs started in the
|
||||
last 24 hours are considered, so older waiting runs stay with maintainers. If your PR does not
|
||||
qualify, it gets the ``need workflow approval`` label and a maintainer approves the runs after
|
||||
looking at the change. That can take a while, so please do not ping maintainers about it; it is
|
||||
not a judgement of your PR. The label is removed when a later commit is approved automatically.
|
||||
|
||||
Maintainers can see each decision, the CI jobs selective checks expect to run and their estimated
|
||||
time in the summary of the ``Auto approve workflow runs`` workflow. The rules are described in
|
||||
more detail in `CI workflows <../dev/breeze/doc/ci/05_workflows.md>`__.
|
||||
|
||||
Gen-AI Assisted contributions
|
||||
-----------------------------
|
||||
|
||||
|
||||
@@ -238,6 +238,7 @@ The triage workflow uses the following labels and states:
|
||||
| Label / State | Meaning |
|
||||
|---|---|
|
||||
| `ready for maintainer review` | PR has passed Stage 1 and is queued for human review. Applied only after the skill has verified that no workflow runs are awaiting approval. |
|
||||
| `need workflow approval` | The PR's CI workflow runs wait for a maintainer, because the `Auto approve workflow runs` workflow did not approve them: a PR to a branch other than `main`, a change to CI definition files, a full-tests or dependency change, a change whose CI jobs are estimated at more than 310 job-minutes, or a change of more than 100 lines of source code (see [Pull Requests](05_pull_requests.rst)). For a PR whose CI runs in the contributor's fork, only a change to CI definition files keeps its runs waiting, and the workflow comments on the PR to say so. The workflow also tries to add the label when processing the PR failed; its run then fails too. Approve the runs after looking at the diff. The workflow removes the label when a later commit is approved automatically. |
|
||||
| `closed because of multiple quality violations` | PR was closed because the author has multiple open PRs with quality issues. |
|
||||
| `suspicious changes detected` | PR (and all open PRs by the same author) was closed because the diff contained suspicious patterns (secret exfiltration, malicious CI modifications, etc.). |
|
||||
| `closed because of open PR limit` | PR was closed in the one-time closure that introduced the [open PR limit](32_open_pull_request_limit.rst). Applied by `dev/close_prs_over_open_pr_limit.py`, never by the triage skill. If the author reopens the PR, triage it like any other. |
|
||||
|
||||
@@ -200,6 +200,26 @@ These are all available flags of ``fork-ci-reconcile`` command:
|
||||
:width: 100%
|
||||
:alt: Breeze ci fork-ci-reconcile
|
||||
|
||||
Approving workflow runs of external contributors
|
||||
------------------------------------------------
|
||||
|
||||
The ``auto-approve-workflow-runs`` workflow runs ``approve-workflow-runs`` every 30 minutes. It approves
|
||||
the waiting workflow runs of external contributors' PRs to ``main`` whose CI jobs are estimated at no more
|
||||
than 310 job-minutes, that change at most 100 lines of source code and that do not touch CI definition files, and labels the other PRs ``need workflow approval``. PRs whose CI runs in
|
||||
the contributor's fork (AIP-120) only run the fork CI gate in ``apache/airflow``, so their runs are
|
||||
approved whatever their size unless they change CI definition files; such a PR also gets a comment
|
||||
explaining that its CI change needs a maintainer. For every PR it also
|
||||
estimates the CI jobs selective checks will run and how long they take, and writes them to the job
|
||||
summary. Use ``--report-only`` to see the decisions without approving runs or changing labels. The rules
|
||||
are described in `CI workflows <ci/05_workflows.md>`_.
|
||||
|
||||
These are all available flags of ``approve-workflow-runs`` command:
|
||||
|
||||
.. image:: ./images/output_ci_approve-workflow-runs.svg
|
||||
:target: https://raw.githubusercontent.com/apache/airflow/main/dev/breeze/images/output_ci_approve-workflow-runs.svg
|
||||
:width: 100%
|
||||
:alt: Breeze ci approve-workflow-runs
|
||||
|
||||
-----
|
||||
|
||||
Next step: Follow the `Release management tasks <09_release_management_tasks.rst>`_ guide to learn how
|
||||
|
||||
@@ -98,6 +98,68 @@ whose CI runs in the contributor's fork (AIP-120), the gate skips `build-info` a
|
||||
everything after it, so the run finishes in seconds; see
|
||||
[Fork CI for external contributors](08_fork_ci_for_external_contributors.md).
|
||||
|
||||
### Approval of pull request runs
|
||||
|
||||
GitHub holds the runs of a fork PR in `action_required` until someone with write access approves
|
||||
them, for the contributors the repository's approval setting covers. The
|
||||
`auto-approve-workflow-runs.yml` workflow runs every 30 minutes on `main` and calls
|
||||
`breeze ci approve-workflow-runs`, which approves the waiting runs of a commit when all of these hold:
|
||||
|
||||
- the PR targets `main`; PRs to release branches (`v3-4-test`, `airflow-ctl/v0-1-test`, ...) run those
|
||||
branches' own workflows and always wait for a maintainer
|
||||
- the PR changes nothing under `.github/`, `dev/breeze/` or `scripts/ci/`, which define the workflows
|
||||
and choose the runners
|
||||
- the PR changes no dependency manifest or lock file (`pyproject.toml`, `uv.lock`, `package.json`,
|
||||
`pnpm-lock.yaml`, `go.mod`, Gradle build files, ...) and adds no new provider (selective checks
|
||||
run from `main`'s tree and do not know it)
|
||||
- selective checks for the PR's merge commit succeed, and do not need the full set of tests, all Python
|
||||
and database versions, a canary build or upgraded dependencies (the estimate does not model them)
|
||||
- the jobs selective checks select are estimated at no more than 310 job-minutes on public runners
|
||||
(about 23% of a full-tests run, just above the cluster of single core areas and the Helm chart)
|
||||
- the PR changes at most 100 lines of source code; tests (including e2e tests), docs, newsfragments,
|
||||
translations, lock files and images are not counted
|
||||
|
||||
A PR to `main` whose CI runs in the contributor's fork (AIP-120: the `Fork CI gate` job would skip
|
||||
project CI for it) is decided by one rule instead, because its `Tests (AMD)` run only executes the
|
||||
gate: its runs are approved whatever its size, cost or dependency changes, unless it changes a file
|
||||
the fork CI reconciler counts as CI-defining (`.github/`, `dev/breeze/`, `scripts/ci/`,
|
||||
`scripts/docker/`, `scripts/in_container/`, `Dockerfile*`, `.pre-commit-config.yaml`). Such a PR gets
|
||||
the `need workflow approval` label and one comment telling the author that the CI change needs a
|
||||
maintainer; see
|
||||
[Approving gated runs](08_fork_ci_for_external_contributors.md#approving-gated-runs).
|
||||
|
||||
Only runs created in the last 24 hours (`--max-run-age-hours`) are considered, so the workflow never
|
||||
approves a backlog of older waiting runs at once; those stay with maintainers. A commit that is the
|
||||
head of several open PRs is never approved automatically, because its runs cannot be told apart by
|
||||
PR, and only runs started after the PR was opened and after its base branch last changed are
|
||||
approved (retargeting a PR does not start new runs). A run selects its jobs from the labels the PR
|
||||
had when it started, while the decision uses the current labels, so for PRs that run project CI a
|
||||
run started before a label that changes which tests run was added or removed
|
||||
(`full tests needed`, `all versions`, `default versions only`, `latest versions only`, `canary`,
|
||||
`upgrade to newer dependencies`, `area:e2e-tests`, `area:kubernetes-tests`) is left for a
|
||||
maintainer, since it still runs the selection it started with; the next push is decided afresh.
|
||||
For a PR whose CI runs in the fork the selection does not matter, but the gate falls back to the
|
||||
labels a run started with when it cannot read the current ones, so a run started before
|
||||
`use fork ci` or `use project ci` was added or removed is left for a maintainer instead. Other PRs get the
|
||||
`need workflow approval` label and wait for a maintainer. When processing a PR fails (for example on
|
||||
a GitHub API error), the workflow tries to add the label to it and the workflow run fails, so the
|
||||
failure stays visible even if the label could not be added. The label is removed when a later commit
|
||||
of the PR is approved automatically.
|
||||
|
||||
The workflow uses only `main`'s code. It reads the PR's metadata and fetches its merge commit as git
|
||||
objects to list the changed files; it never checks out or runs the PR's code. The merge commit must
|
||||
have been built from the head commit whose runs get approved, so a push after the check cannot slip
|
||||
into an approved run. Approving with the workflow's `GITHUB_TOKEN` starts the runs right away, and
|
||||
`workflow_run` workflows that follow them still trigger.
|
||||
|
||||
The estimate comes from `dev/breeze/src/airflow_breeze/utils/ci_minutes_estimate.py`, which turns the
|
||||
selective-check outputs into job groups with job-minutes and a wall-clock estimate, weighting
|
||||
providers by the size of their test suites. The job summary lists every waiting PR with its decision,
|
||||
the expected job groups and the estimated time. The numbers are medians of recent `Tests (AMD)` PR
|
||||
runs on public runners; refresh them with `dev/calibrate_ci_minutes_estimates.py`, as
|
||||
`.github/AGENTS.md` describes. Run `breeze ci approve-workflow-runs --report-only` (or dispatch the
|
||||
workflow with `report-only`) to see the decisions without approving or labelling anything.
|
||||
|
||||
## Fork push run
|
||||
|
||||
These runs are triggered by a push to any branch of a contributor's fork in which the
|
||||
|
||||
@@ -337,6 +337,49 @@ where `*` is any characters except `/`).
|
||||
The `check-ci-workflows-in-sync` prek hook allowlist is extended to permit the `gate` job and
|
||||
the `build-info` dependency to exist only in the AMD workflow.
|
||||
|
||||
### Approving gated runs
|
||||
|
||||
GitHub holds the `pull_request` runs of a fork pull request in `action_required` until someone with
|
||||
write access approves them, for the contributors the repository's approval setting covers. Until
|
||||
then the gate job does not run either. A gated pull request would stay in the maintainers' approval
|
||||
queue even though its project CI run only executes the gate, and the reconciler could not delete a
|
||||
gated run that never ran.
|
||||
|
||||
`breeze ci approve-workflow-runs`, run every 30 minutes by `auto-approve-workflow-runs.yml` (see
|
||||
[CI workflows](05_workflows.md#approval-of-pull-request-runs)), handles them. For a pull request to
|
||||
`main` it calls `fork_ci_gate.decide` with the configuration of its own `main` checkout and the
|
||||
pull request's author, association, creation time, head repository and current labels, the inputs
|
||||
the gate job of the waiting run uses. When the reason is gated (`external`, `pilot` or
|
||||
`label_fork_ci`), the rules for pull requests that run project CI (estimated job-minutes, lines of
|
||||
source code, dependency files, full tests) do not apply, because none of those jobs run. One rule
|
||||
applies instead:
|
||||
|
||||
- The waiting runs of the head commit are approved when the pull request's merge commit changes no
|
||||
file that the reconciler counts as CI-defining: `.github/`, `dev/breeze/`, `scripts/ci/`,
|
||||
`scripts/docker/`, `scripts/in_container/`, `Dockerfile*` and `.pre-commit-config.yaml` (see
|
||||
"Trusting a green fork run"). The approved `ci-amd.yml` run executes only the gate, and the other
|
||||
`pull_request` workflows (CodeQL for the changed languages, the newsfragment check, dependency
|
||||
review) run on GitHub-hosted runners.
|
||||
- Otherwise the runs wait for a maintainer, the pull request is labelled `need workflow approval`,
|
||||
and the workflow posts one comment explaining that the change to the listed CI files needs a
|
||||
maintainer to review it and approve the runs. The comment starts with the marker
|
||||
`<!-- workflow-approval: ci-change -->` and is posted once per pull request; only comments by
|
||||
`github-actions[bot]` with the marker count. A change to `.github/` can remove the gate or add a
|
||||
workflow that does run, so such a run must not start without a review.
|
||||
|
||||
A run started before `use fork ci` or `use project ci` was last added or removed is not approved
|
||||
automatically: the gate falls back to the labels of the run's event when it cannot read the current
|
||||
ones, and those can still send the run to project CI. The next push is decided afresh.
|
||||
|
||||
Both rules use the same list as "Trusting a green fork run", so a gated pull request whose runs are
|
||||
approved automatically is also one whose green fork run is trusted, and one that changes CI is both
|
||||
left waiting for approval and labelled `needs project ci` once its fork run is green. The gate
|
||||
tampering check still applies to every run a maintainer approves by hand.
|
||||
|
||||
The approval reads only API metadata and the git objects of the merge commit; it never checks out or
|
||||
runs the pull request's code. Pull requests to other branches keep the rules for project CI, which
|
||||
leave them to a maintainer.
|
||||
|
||||
## Fork mode CI
|
||||
|
||||
### Trigger
|
||||
@@ -1022,6 +1065,9 @@ as a failed check rather than a crash.
|
||||
see "Trusting a green fork run".
|
||||
- Job statuses carry names from the contributor's workflow under their own `Fork CI job / <name>`
|
||||
prefix, so they cannot post the reconciler's own contexts or `CI passed`; see "Job statuses".
|
||||
- Workflow runs of a gated pull request are approved without a maintainer only when it changes no
|
||||
CI-defining file, so a pull request that edits the gate away still waits for a maintainer before
|
||||
any run starts; see "Approving gated runs".
|
||||
- The reconciler runs on `main` with `pull-requests: write` and never checks out or executes
|
||||
pull request content. Its inputs are API data; its comment templates are static.
|
||||
- Fork runs get the fork's `GITHUB_TOKEN` only. Nothing in project CI trusts a fork run's
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 562.4" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
<defs>
|
||||
<clipPath id="breeze-ci-clip-terminal">
|
||||
<rect x="0" y="0" width="1463.0" height="511.4" />
|
||||
<rect x="0" y="0" width="1463.0" height="584.5999999999999" />
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-line-0">
|
||||
<rect x="0" y="1.5" width="1464" height="24.65"/>
|
||||
@@ -104,9 +104,18 @@
|
||||
<clipPath id="breeze-ci-line-19">
|
||||
<rect x="0" y="465.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-line-20">
|
||||
<rect x="0" y="489.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-line-21">
|
||||
<rect x="0" y="513.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-line-22">
|
||||
<rect x="0" y="538.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="560.4" rx="8"/><text class="breeze-ci-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: ci</text>
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="633.6" rx="8"/><text class="breeze-ci-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: ci</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
@@ -125,18 +134,21 @@
|
||||
</text><text class="breeze-ci-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-ci-line-6)">│</text><text class="breeze-ci-r4" x="24.4" y="166.4" textLength="73.2" clip-path="url(#breeze-ci-line-6)">--help</text><text class="breeze-ci-r6" x="122" y="166.4" textLength="24.4" clip-path="url(#breeze-ci-line-6)">-h</text><text class="breeze-ci-r1" x="170.8" y="166.4" textLength="329.4" clip-path="url(#breeze-ci-line-6)">Show this message and exit.</text><text class="breeze-ci-r5" x="1451.8" y="166.4" textLength="12.2" clip-path="url(#breeze-ci-line-6)">│</text><text class="breeze-ci-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#breeze-ci-line-6)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="190.8" textLength="1464" clip-path="url(#breeze-ci-line-7)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-ci-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-ci-line-7)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="215.2" textLength="24.4" clip-path="url(#breeze-ci-line-8)">╭─</text><text class="breeze-ci-r5" x="24.4" y="215.2" textLength="158.6" clip-path="url(#breeze-ci-line-8)"> CI commands </text><text class="breeze-ci-r5" x="183" y="215.2" textLength="1256.6" clip-path="url(#breeze-ci-line-8)">───────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-ci-r5" x="1439.6" y="215.2" textLength="24.4" clip-path="url(#breeze-ci-line-8)">─╮</text><text class="breeze-ci-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-ci-line-8)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-line-9)">│</text><text class="breeze-ci-r4" x="24.4" y="239.6" textLength="207.4" clip-path="url(#breeze-ci-line-9)">fix-ownership    </text><text class="breeze-ci-r1" x="256.2" y="239.6" textLength="1183.4" clip-path="url(#breeze-ci-line-9)">Fix ownership of source files to be same as host user.                                           </text><text class="breeze-ci-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-line-9)">│</text><text class="breeze-ci-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-line-9)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-ci-line-10)">│</text><text class="breeze-ci-r4" x="24.4" y="264" textLength="207.4" clip-path="url(#breeze-ci-line-10)">free-space       </text><text class="breeze-ci-r1" x="256.2" y="264" textLength="1183.4" clip-path="url(#breeze-ci-line-10)">Free space for jobs run in CI.                                                                   </text><text class="breeze-ci-r5" x="1451.8" y="264" textLength="12.2" clip-path="url(#breeze-ci-line-10)">│</text><text class="breeze-ci-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-ci-line-10)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-ci-line-11)">│</text><text class="breeze-ci-r4" x="24.4" y="288.4" textLength="207.4" clip-path="url(#breeze-ci-line-11)">resource-check   </text><text class="breeze-ci-r1" x="256.2" y="288.4" textLength="1183.4" clip-path="url(#breeze-ci-line-11)">Check if available docker resources are enough.                                                  </text><text class="breeze-ci-r5" x="1451.8" y="288.4" textLength="12.2" clip-path="url(#breeze-ci-line-11)">│</text><text class="breeze-ci-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-ci-line-11)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-line-12)">│</text><text class="breeze-ci-r4" x="24.4" y="312.8" textLength="207.4" clip-path="url(#breeze-ci-line-12)">selective-check  </text><text class="breeze-ci-r1" x="256.2" y="312.8" textLength="1183.4" clip-path="url(#breeze-ci-line-12)">Checks what kind of tests should be run for an incoming commit.                                  </text><text class="breeze-ci-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-line-12)">│</text><text class="breeze-ci-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-line-12)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-line-13)">│</text><text class="breeze-ci-r4" x="24.4" y="337.2" textLength="207.4" clip-path="url(#breeze-ci-line-13)">get-workflow-info</text><text class="breeze-ci-r1" x="256.2" y="337.2" textLength="1183.4" clip-path="url(#breeze-ci-line-13)">Retrieve information about current workflow in the CIand produce github actions output extracted </text><text class="breeze-ci-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-line-13)">│</text><text class="breeze-ci-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-line-13)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-ci-line-14)">│</text><text class="breeze-ci-r1" x="256.2" y="361.6" textLength="1183.4" clip-path="url(#breeze-ci-line-14)">from it.                                                                                         </text><text class="breeze-ci-r5" x="1451.8" y="361.6" textLength="12.2" clip-path="url(#breeze-ci-line-14)">│</text><text class="breeze-ci-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-ci-line-14)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-ci-line-15)">│</text><text class="breeze-ci-r4" x="24.4" y="386" textLength="207.4" clip-path="url(#breeze-ci-line-15)">upgrade          </text><text class="breeze-ci-r1" x="256.2" y="386" textLength="1183.4" clip-path="url(#breeze-ci-line-15)">Perform important upgrade steps of the CI environment. And create a PR                           </text><text class="breeze-ci-r5" x="1451.8" y="386" textLength="12.2" clip-path="url(#breeze-ci-line-15)">│</text><text class="breeze-ci-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-ci-line-15)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-line-16)">│</text><text class="breeze-ci-r4" x="24.4" y="410.4" textLength="207.4" clip-path="url(#breeze-ci-line-16)">set-milestone    </text><text class="breeze-ci-r1" x="256.2" y="410.4" textLength="1183.4" clip-path="url(#breeze-ci-line-16)">Set milestone on a merged PR if it doesn't have one. Used by the milestone-tag-assistant         </text><text class="breeze-ci-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-line-16)">│</text><text class="breeze-ci-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-line-16)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-line-17)">│</text><text class="breeze-ci-r1" x="256.2" y="434.8" textLength="1183.4" clip-path="url(#breeze-ci-line-17)">workflow.                                                                                        </text><text class="breeze-ci-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-line-17)">│</text><text class="breeze-ci-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-line-17)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-line-18)">│</text><text class="breeze-ci-r4" x="24.4" y="459.2" textLength="207.4" clip-path="url(#breeze-ci-line-18)">fork-ci-reconcile</text><text class="breeze-ci-r1" x="256.2" y="459.2" textLength="1183.4" clip-path="url(#breeze-ci-line-18)">Reconcile pull requests whose CI runs in contributor forks (AIP-120). Run on a schedule.         </text><text class="breeze-ci-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-line-18)">│</text><text class="breeze-ci-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-line-18)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-ci-line-19)">│</text><text class="breeze-ci-r4" x="24.4" y="483.6" textLength="207.4" clip-path="url(#breeze-ci-line-19)">audit            </text><text class="breeze-ci-r1" x="256.2" y="483.6" textLength="1183.4" clip-path="url(#breeze-ci-line-19)">Check that your checkout and fork are set up for fork CI (AIP-120), and offer the fixes.         </text><text class="breeze-ci-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-ci-line-19)">│</text><text class="breeze-ci-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-ci-line-19)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="508" textLength="1464" clip-path="url(#breeze-ci-line-20)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-ci-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-ci-line-20)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-line-9)">│</text><text class="breeze-ci-r4" x="24.4" y="239.6" textLength="256.2" clip-path="url(#breeze-ci-line-9)">fix-ownership        </text><text class="breeze-ci-r1" x="305" y="239.6" textLength="1134.6" clip-path="url(#breeze-ci-line-9)">Fix ownership of source files to be same as host user.                                       </text><text class="breeze-ci-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-line-9)">│</text><text class="breeze-ci-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-line-9)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-ci-line-10)">│</text><text class="breeze-ci-r4" x="24.4" y="264" textLength="256.2" clip-path="url(#breeze-ci-line-10)">free-space           </text><text class="breeze-ci-r1" x="305" y="264" textLength="1134.6" clip-path="url(#breeze-ci-line-10)">Free space for jobs run in CI.                                                               </text><text class="breeze-ci-r5" x="1451.8" y="264" textLength="12.2" clip-path="url(#breeze-ci-line-10)">│</text><text class="breeze-ci-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-ci-line-10)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-ci-line-11)">│</text><text class="breeze-ci-r4" x="24.4" y="288.4" textLength="256.2" clip-path="url(#breeze-ci-line-11)">resource-check       </text><text class="breeze-ci-r1" x="305" y="288.4" textLength="1134.6" clip-path="url(#breeze-ci-line-11)">Check if available docker resources are enough.                                              </text><text class="breeze-ci-r5" x="1451.8" y="288.4" textLength="12.2" clip-path="url(#breeze-ci-line-11)">│</text><text class="breeze-ci-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-ci-line-11)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-line-12)">│</text><text class="breeze-ci-r4" x="24.4" y="312.8" textLength="256.2" clip-path="url(#breeze-ci-line-12)">selective-check      </text><text class="breeze-ci-r1" x="305" y="312.8" textLength="1134.6" clip-path="url(#breeze-ci-line-12)">Checks what kind of tests should be run for an incoming commit.                              </text><text class="breeze-ci-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-line-12)">│</text><text class="breeze-ci-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-line-12)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-line-13)">│</text><text class="breeze-ci-r4" x="24.4" y="337.2" textLength="256.2" clip-path="url(#breeze-ci-line-13)">get-workflow-info    </text><text class="breeze-ci-r1" x="305" y="337.2" textLength="1134.6" clip-path="url(#breeze-ci-line-13)">Retrieve information about current workflow in the CIand produce github actions output       </text><text class="breeze-ci-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-line-13)">│</text><text class="breeze-ci-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-line-13)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-ci-line-14)">│</text><text class="breeze-ci-r1" x="305" y="361.6" textLength="1134.6" clip-path="url(#breeze-ci-line-14)">extracted from it.                                                                           </text><text class="breeze-ci-r5" x="1451.8" y="361.6" textLength="12.2" clip-path="url(#breeze-ci-line-14)">│</text><text class="breeze-ci-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-ci-line-14)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-ci-line-15)">│</text><text class="breeze-ci-r4" x="24.4" y="386" textLength="256.2" clip-path="url(#breeze-ci-line-15)">upgrade              </text><text class="breeze-ci-r1" x="305" y="386" textLength="1134.6" clip-path="url(#breeze-ci-line-15)">Perform important upgrade steps of the CI environment. And create a PR                       </text><text class="breeze-ci-r5" x="1451.8" y="386" textLength="12.2" clip-path="url(#breeze-ci-line-15)">│</text><text class="breeze-ci-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-ci-line-15)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-line-16)">│</text><text class="breeze-ci-r4" x="24.4" y="410.4" textLength="256.2" clip-path="url(#breeze-ci-line-16)">set-milestone        </text><text class="breeze-ci-r1" x="305" y="410.4" textLength="1134.6" clip-path="url(#breeze-ci-line-16)">Set milestone on a merged PR if it doesn't have one. Used by the milestone-tag-assistant     </text><text class="breeze-ci-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-line-16)">│</text><text class="breeze-ci-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-line-16)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-line-17)">│</text><text class="breeze-ci-r1" x="305" y="434.8" textLength="1134.6" clip-path="url(#breeze-ci-line-17)">workflow.                                                                                    </text><text class="breeze-ci-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-line-17)">│</text><text class="breeze-ci-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-line-17)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-line-18)">│</text><text class="breeze-ci-r4" x="24.4" y="459.2" textLength="256.2" clip-path="url(#breeze-ci-line-18)">fork-ci-reconcile    </text><text class="breeze-ci-r1" x="305" y="459.2" textLength="1134.6" clip-path="url(#breeze-ci-line-18)">Reconcile pull requests whose CI runs in contributor forks (AIP-120). Run on a schedule.     </text><text class="breeze-ci-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-line-18)">│</text><text class="breeze-ci-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-line-18)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-ci-line-19)">│</text><text class="breeze-ci-r4" x="24.4" y="483.6" textLength="256.2" clip-path="url(#breeze-ci-line-19)">audit                </text><text class="breeze-ci-r1" x="305" y="483.6" textLength="1134.6" clip-path="url(#breeze-ci-line-19)">Check that your checkout and fork are set up for fork CI (AIP-120), and offer the fixes.     </text><text class="breeze-ci-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-ci-line-19)">│</text><text class="breeze-ci-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-ci-line-19)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-ci-line-20)">│</text><text class="breeze-ci-r4" x="24.4" y="508" textLength="256.2" clip-path="url(#breeze-ci-line-20)">approve-workflow-runs</text><text class="breeze-ci-r1" x="305" y="508" textLength="1134.6" clip-path="url(#breeze-ci-line-20)">Approve the waiting workflow runs of external contributors' PRs whose changes are safe to run</text><text class="breeze-ci-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-ci-line-20)">│</text><text class="breeze-ci-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-ci-line-20)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-ci-line-21)">│</text><text class="breeze-ci-r1" x="305" y="532.4" textLength="1134.6" clip-path="url(#breeze-ci-line-21)">without a maintainer's look, and label the others 'need workflow approval'. Used by the      </text><text class="breeze-ci-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-ci-line-21)">│</text><text class="breeze-ci-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-ci-line-21)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-ci-line-22)">│</text><text class="breeze-ci-r1" x="305" y="556.8" textLength="1134.6" clip-path="url(#breeze-ci-line-22)">auto-approve-workflow-runs workflow.                                                         </text><text class="breeze-ci-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-ci-line-22)">│</text><text class="breeze-ci-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-ci-line-22)">
|
||||
</text><text class="breeze-ci-r5" x="0" y="581.2" textLength="1464" clip-path="url(#breeze-ci-line-23)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-ci-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-ci-line-23)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 22 KiB |
@@ -1 +1 @@
|
||||
ceb5f9dfbcb79c72545427568d9b7dbc
|
||||
eb626e1c2737eaba69f91123d1077d16
|
||||
@@ -0,0 +1,142 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 538.0" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Regular"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Fira Code";
|
||||
src: local("FiraCode-Bold"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
|
||||
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
|
||||
font-style: bold;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.breeze-ci-approve-workflow-runs-matrix {
|
||||
font-family: Fira Code, monospace;
|
||||
font-size: 20px;
|
||||
line-height: 24.4px;
|
||||
font-variant-east-asian: full-width;
|
||||
}
|
||||
|
||||
.breeze-ci-approve-workflow-runs-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
.breeze-ci-approve-workflow-runs-r1 { fill: #c5c8c6 }
|
||||
.breeze-ci-approve-workflow-runs-r2 { fill: #d0b344 }
|
||||
.breeze-ci-approve-workflow-runs-r3 { fill: #c5c8c6;font-weight: bold }
|
||||
.breeze-ci-approve-workflow-runs-r4 { fill: #68a0b3;font-weight: bold }
|
||||
.breeze-ci-approve-workflow-runs-r5 { fill: #868887 }
|
||||
.breeze-ci-approve-workflow-runs-r6 { fill: #8d7b39 }
|
||||
.breeze-ci-approve-workflow-runs-r7 { fill: #cc555a }
|
||||
.breeze-ci-approve-workflow-runs-r8 { fill: #8a4346 }
|
||||
.breeze-ci-approve-workflow-runs-r9 { fill: #98a84b;font-weight: bold }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-clip-terminal">
|
||||
<rect x="0" y="0" width="1463.0" height="487.0" />
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-0">
|
||||
<rect x="0" y="1.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-1">
|
||||
<rect x="0" y="25.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-2">
|
||||
<rect x="0" y="50.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-3">
|
||||
<rect x="0" y="74.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-4">
|
||||
<rect x="0" y="99.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-5">
|
||||
<rect x="0" y="123.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-6">
|
||||
<rect x="0" y="147.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-7">
|
||||
<rect x="0" y="172.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-8">
|
||||
<rect x="0" y="196.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-9">
|
||||
<rect x="0" y="221.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-10">
|
||||
<rect x="0" y="245.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-11">
|
||||
<rect x="0" y="269.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-12">
|
||||
<rect x="0" y="294.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-13">
|
||||
<rect x="0" y="318.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-14">
|
||||
<rect x="0" y="343.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-15">
|
||||
<rect x="0" y="367.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-16">
|
||||
<rect x="0" y="391.9" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-17">
|
||||
<rect x="0" y="416.3" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-ci-approve-workflow-runs-line-18">
|
||||
<rect x="0" y="440.7" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="536" rx="8"/><text class="breeze-ci-approve-workflow-runs-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: ci approve-workflow-runs</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
<circle cx="44" cy="0" r="7" fill="#28c840"/>
|
||||
</g>
|
||||
|
||||
<g transform="translate(9, 41)" clip-path="url(#breeze-ci-approve-workflow-runs-clip-terminal)">
|
||||
|
||||
<g class="breeze-ci-approve-workflow-runs-matrix">
|
||||
<text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="20" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-0)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r2" x="12.2" y="44.4" textLength="73.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-1)">Usage:</text><text class="breeze-ci-approve-workflow-runs-r3" x="97.6" y="44.4" textLength="378.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-1)">breeze ci approve-workflow-runs</text><text class="breeze-ci-approve-workflow-runs-r1" x="488" y="44.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-1)">[</text><text class="breeze-ci-approve-workflow-runs-r4" x="500.2" y="44.4" textLength="85.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-1)">OPTIONS</text><text class="breeze-ci-approve-workflow-runs-r1" x="585.6" y="44.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-1)">]</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-1)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-2)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r1" x="12.2" y="93.2" textLength="1427.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-3)">Approve the waiting workflow runs of external contributors' PRs whose changes are safe to run without a maintainer's </text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-3)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r1" x="12.2" y="117.6" textLength="1232.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-4)">look, and label the others 'need workflow approval'. Used by the auto-approve-workflow-runs workflow.</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-4)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="142" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-5)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="166.4" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-6)">╭─</text><text class="breeze-ci-approve-workflow-runs-r5" x="24.4" y="166.4" textLength="195.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-6)"> Approval flags </text><text class="breeze-ci-approve-workflow-runs-r5" x="219.6" y="166.4" textLength="1220" clip-path="url(#breeze-ci-approve-workflow-runs-line-6)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-ci-approve-workflow-runs-r5" x="1439.6" y="166.4" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-6)">─╮</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-6)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-7)">│</text><text class="breeze-ci-approve-workflow-runs-r4" x="24.4" y="190.8" textLength="231.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-7)">--max-run-age-hours</text><text class="breeze-ci-approve-workflow-runs-r1" x="280.6" y="190.8" textLength="1159" clip-path="url(#breeze-ci-approve-workflow-runs-line-7)">Only decide on workflow runs created within this many hours; older waiting runs are left alone.</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="190.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-7)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-7)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-8)">│</text><text class="breeze-ci-approve-workflow-runs-r5" x="280.6" y="215.2" textLength="158.6" clip-path="url(#breeze-ci-approve-workflow-runs-line-8)">[default: 24]</text><text class="breeze-ci-approve-workflow-runs-r6" x="451.4" y="215.2" textLength="244" clip-path="url(#breeze-ci-approve-workflow-runs-line-8)">(INTEGER RANGE x>=1)</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="215.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-8)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-8)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-9)">│</text><text class="breeze-ci-approve-workflow-runs-r4" x="24.4" y="239.6" textLength="231.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-9)">--report-only      </text><text class="breeze-ci-approve-workflow-runs-r1" x="280.6" y="239.6" textLength="1012.6" clip-path="url(#breeze-ci-approve-workflow-runs-line-9)">Only report the decisions and estimates, without approving runs or changing labels.</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-9)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-9)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="264" textLength="1464" clip-path="url(#breeze-ci-approve-workflow-runs-line-10)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-10)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="288.4" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-11)">╭─</text><text class="breeze-ci-approve-workflow-runs-r5" x="24.4" y="288.4" textLength="231.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-11)"> GitHub parameters </text><text class="breeze-ci-approve-workflow-runs-r5" x="256.2" y="288.4" textLength="1183.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-11)">─────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-ci-approve-workflow-runs-r5" x="1439.6" y="288.4" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-11)">─╮</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-11)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">│</text><text class="breeze-ci-approve-workflow-runs-r7" x="24.4" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">*</text><text class="breeze-ci-approve-workflow-runs-r4" x="61" y="312.8" textLength="231.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">--github-token     </text><text class="breeze-ci-approve-workflow-runs-r1" x="366" y="312.8" textLength="707.6" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">GitHub token able to approve workflow runs and label PRs. </text><text class="breeze-ci-approve-workflow-runs-r8" x="1073.6" y="312.8" textLength="122" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">[required]</text><text class="breeze-ci-approve-workflow-runs-r6" x="1207.8" y="312.8" textLength="73.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">(TEXT)</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-12)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">│</text><text class="breeze-ci-approve-workflow-runs-r4" x="61" y="337.2" textLength="231.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">--github-repository</text><text class="breeze-ci-approve-workflow-runs-r9" x="317.2" y="337.2" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">-g</text><text class="breeze-ci-approve-workflow-runs-r1" x="366" y="337.2" textLength="597.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">GitHub repository used to pull, push run images. </text><text class="breeze-ci-approve-workflow-runs-r5" x="963.8" y="337.2" textLength="305" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">[default: apache/airflow]</text><text class="breeze-ci-approve-workflow-runs-r6" x="1281" y="337.2" textLength="73.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">(TEXT)</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-13)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="361.6" textLength="1464" clip-path="url(#breeze-ci-approve-workflow-runs-line-14)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-14)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="386" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-15)">╭─</text><text class="breeze-ci-approve-workflow-runs-r5" x="24.4" y="386" textLength="195.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-15)"> Common options </text><text class="breeze-ci-approve-workflow-runs-r5" x="219.6" y="386" textLength="1220" clip-path="url(#breeze-ci-approve-workflow-runs-line-15)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-ci-approve-workflow-runs-r5" x="1439.6" y="386" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-15)">─╮</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-15)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-16)">│</text><text class="breeze-ci-approve-workflow-runs-r4" x="24.4" y="410.4" textLength="109.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-16)">--verbose</text><text class="breeze-ci-approve-workflow-runs-r9" x="158.6" y="410.4" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-16)">-v</text><text class="breeze-ci-approve-workflow-runs-r1" x="207.4" y="410.4" textLength="585.6" clip-path="url(#breeze-ci-approve-workflow-runs-line-16)">Print verbose information about performed steps.</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-16)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-16)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-17)">│</text><text class="breeze-ci-approve-workflow-runs-r4" x="24.4" y="434.8" textLength="109.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-17)">--dry-run</text><text class="breeze-ci-approve-workflow-runs-r9" x="158.6" y="434.8" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-17)">-D</text><text class="breeze-ci-approve-workflow-runs-r1" x="207.4" y="434.8" textLength="719.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-17)">If dry-run is set, commands are only printed, not executed.</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-17)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-17)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-18)">│</text><text class="breeze-ci-approve-workflow-runs-r4" x="24.4" y="459.2" textLength="109.8" clip-path="url(#breeze-ci-approve-workflow-runs-line-18)">--help   </text><text class="breeze-ci-approve-workflow-runs-r9" x="158.6" y="459.2" textLength="24.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-18)">-h</text><text class="breeze-ci-approve-workflow-runs-r1" x="207.4" y="459.2" textLength="329.4" clip-path="url(#breeze-ci-approve-workflow-runs-line-18)">Show this message and exit.</text><text class="breeze-ci-approve-workflow-runs-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-18)">│</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-18)">
|
||||
</text><text class="breeze-ci-approve-workflow-runs-r5" x="0" y="483.6" textLength="1464" clip-path="url(#breeze-ci-approve-workflow-runs-line-19)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-ci-approve-workflow-runs-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-ci-approve-workflow-runs-line-19)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1 @@
|
||||
485b9682543dc0dd1e1922e32196b2ee
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 1294.3999999999999" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 1318.8" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
<defs>
|
||||
<clipPath id="breeze-setup-check-all-params-in-groups-clip-terminal">
|
||||
<rect x="0" y="0" width="1463.0" height="1243.3999999999999" />
|
||||
<rect x="0" y="0" width="1463.0" height="1267.8" />
|
||||
</clipPath>
|
||||
<clipPath id="breeze-setup-check-all-params-in-groups-line-0">
|
||||
<rect x="0" y="1.5" width="1464" height="24.65"/>
|
||||
@@ -195,9 +195,12 @@
|
||||
<clipPath id="breeze-setup-check-all-params-in-groups-line-49">
|
||||
<rect x="0" y="1197.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-setup-check-all-params-in-groups-line-50">
|
||||
<rect x="0" y="1221.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="1292.4" rx="8"/><text class="breeze-setup-check-all-params-in-groups-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup check-all-params-in-groups</text>
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="1316.8" rx="8"/><text class="breeze-setup-check-all-params-in-groups-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup check-all-params-in-groups</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
@@ -215,49 +218,50 @@
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="142" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-5)">╭─</text><text class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="142" textLength="414.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-5)"> Check all params in groups flags </text><text class="breeze-setup-check-all-params-in-groups-r5" x="439.2" y="142" textLength="1000.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-5)">──────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1439.6" y="142" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-5)">─╮</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="142" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-5)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-6)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="166.4" textLength="109.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-6)">--command</text><text class="breeze-setup-check-all-params-in-groups-r1" x="158.6" y="166.4" textLength="805.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-6)">Command(s) to regenerate images for (optional, might be repeated) </text><text class="breeze-setup-check-all-params-in-groups-r6" x="963.8" y="166.4" textLength="366" clip-path="url(#breeze-setup-check-all-params-in-groups-line-6)">(build-docs | ci | ci-image | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="166.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-6)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-6)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-7)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="190.8" textLength="1134.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-7)">ci-image:build | ci-image:export-mount-cache | ci-image:import-mount-cache | ci-image:load | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="190.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-7)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-7)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="215.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">ci-image:pull | ci-image:save | ci-image:verify | ci:audit | ci:fix-ownership | ci:fork-ci-reconcile | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="239.6" textLength="1207.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">ci:free-space | ci:get-workflow-info | ci:resource-check | ci:selective-check | ci:set-milestone | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="264" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">ci:upgrade | cleanup | doctor | down | exec | generate-migration-file | issues | issues:unassign | k8s | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="264" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="288.4" textLength="1073.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">k8s:build-k8s-image | k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="312.8" textLength="1195.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">k8s:deploy-airflow | k8s:deploy-cluster | k8s:dev | k8s:k9s | k8s:logs | k8s:run-complete-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="337.2" textLength="1268.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">k8s:setup-env | k8s:setup-lang-sdk-test | k8s:shell | k8s:smoke-test-overlay | k8s:status | k8s:tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="361.6" textLength="1110.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">k8s:upload-k8s-image | prod-image | prod-image:build | prod-image:load | prod-image:pull | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="386" textLength="1134.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">prod-image:save | prod-image:verify | registry | registry:backfill | registry:extract-data | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="386" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="410.4" textLength="1098" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">registry:publish-versions | release-management | release-management:add-back-references | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="434.8" textLength="1073.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">release-management:check-release-files | release-management:classify-provider-changes | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="459.2" textLength="1183.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">release-management:clean-old-provider-artifacts | release-management:constraints-version-check | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="483.6" textLength="1122.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">release-management:create-minor-branch | release-management:generate-airflowctl-changelog | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="508" textLength="1195.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">release-management:generate-constraints | release-management:generate-issue-content-airflow-ctl | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="532.4" textLength="1268.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">release-management:generate-issue-content-core | release-management:generate-issue-content-helm-chart | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="556.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">release-management:generate-issue-content-providers | release-management:generate-providers-metadata | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="581.2" textLength="1110.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">release-management:install-provider-distributions | release-management:merge-prod-images | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="605.6" textLength="1159" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">release-management:mirror-base-images | release-management:prepare-airflow-ctl-distributions | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="630" textLength="1207.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">release-management:prepare-airflow-distributions | release-management:prepare-helm-chart-package | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="654.4" textLength="1171.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">release-management:prepare-helm-chart-tarball | release-management:prepare-mypy-distributions | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="678.8" textLength="1268.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">release-management:prepare-provider-distributions | release-management:prepare-provider-documentation | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="703.2" textLength="976" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">release-management:prepare-python-client | release-management:prepare-tarball | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="727.6" textLength="1049.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">release-management:prepare-task-sdk-distributions | release-management:publish-docs | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="752" textLength="1012.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">release-management:publish-docs-to-s3 | release-management:publish-schemas-to-s3 | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="776.4" textLength="988.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">release-management:release-prod-images | release-management:start-beta-process | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="800.8" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">release-management:start-rc-process | release-management:start-release | release-management:tag-providers</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="825.2" textLength="1134.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">| release-management:update-constraints | release-management:update-providers-next-version | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="849.6" textLength="1244.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">release-management:verify-provider-distributions | release-management:verify-rc-by-pmc | run | sbom | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="874" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="874" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">sbom:build-all-airflow-images | sbom:export-dependency-information | sbom:generate-providers-requirements</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="874" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="874" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="898.4" textLength="1183.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">| sbom:update-sbom-information | setup | setup:autocomplete | setup:check-all-params-in-groups | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="922.8" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">setup:config | setup:regenerate-command-images | setup:self-upgrade | setup:synchronize-local-mounts | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="947.2" textLength="1098" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">setup:version | shell | start-airflow | testing | testing:airflow-ctl-integration-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="971.6" textLength="1085.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">testing:airflow-ctl-tests | testing:airflow-e2e-tests | testing:core-integration-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="996" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="996" textLength="890.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">testing:core-tests | testing:docker-compose-tests | testing:helm-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="996" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="996" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1020.4" textLength="1195.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">testing:providers-integration-tests | testing:providers-tests | testing:python-api-client-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1044.8" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">testing:system-tests | testing:task-sdk-integration-tests | testing:task-sdk-tests | testing:ui-e2e-tests</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1069.2" textLength="1061.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">| ui | ui:check-translation-completeness | ui:compile-assets | verify | workflow-run | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1093.6" textLength="1183.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">workflow-run:publish-docs | workflow-run:release-constraints | workflow-run:sync-staging-to-main)</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1118" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-45)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1118" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-45)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1142.4" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-46)">╭─</text><text class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="1142.4" textLength="195.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-46)"> Common options </text><text class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="1142.4" textLength="1220" clip-path="url(#breeze-setup-check-all-params-in-groups-line-46)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1439.6" y="1142.4" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-46)">─╮</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-46)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="1166.8" textLength="109.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">--verbose</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="1166.8" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">-v</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="1166.8" textLength="585.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">Print verbose information about performed steps.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="1191.2" textLength="109.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">--dry-run</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="1191.2" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">-D</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="1191.2" textLength="719.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">If dry-run is set, commands are only printed, not executed.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="1215.6" textLength="109.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">--help   </text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="1215.6" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">-h</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="1215.6" textLength="329.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">Show this message and exit.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1240" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1240" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="215.2" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">ci-image:pull | ci-image:save | ci-image:verify | ci:approve-workflow-runs | ci:audit | ci:fix-ownership </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-8)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="239.6" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">| ci:fork-ci-reconcile | ci:free-space | ci:get-workflow-info | ci:resource-check | ci:selective-check | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-9)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="264" textLength="1220" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">ci:set-milestone | ci:upgrade | cleanup | doctor | down | exec | generate-migration-file | issues | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="264" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-10)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="288.4" textLength="1110.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">issues:unassign | k8s | k8s:build-k8s-image | k8s:configure-cluster | k8s:create-cluster | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-11)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="312.8" textLength="1146.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">k8s:delete-cluster | k8s:deploy-airflow | k8s:deploy-cluster | k8s:dev | k8s:k9s | k8s:logs | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-12)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="337.2" textLength="1268.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">k8s:run-complete-tests | k8s:setup-env | k8s:setup-lang-sdk-test | k8s:shell | k8s:smoke-test-overlay | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-13)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="361.6" textLength="1195.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">k8s:status | k8s:tests | k8s:upload-k8s-image | prod-image | prod-image:build | prod-image:load | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-14)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="386" textLength="1061.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">prod-image:pull | prod-image:save | prod-image:verify | registry | registry:backfill | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="386" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-15)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="410.4" textLength="890.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">registry:extract-data | registry:publish-versions | release-management | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-16)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="434.8" textLength="1000.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">release-management:add-back-references | release-management:check-release-files | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-17)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="459.2" textLength="1183.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">release-management:classify-provider-changes | release-management:clean-old-provider-artifacts | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-18)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="483.6" textLength="1073.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">release-management:constraints-version-check | release-management:create-minor-branch | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-19)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="508" textLength="1134.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">release-management:generate-airflowctl-changelog | release-management:generate-constraints | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-20)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="532.4" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">release-management:generate-issue-content-airflow-ctl | release-management:generate-issue-content-core | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-21)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="556.8" textLength="671" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">release-management:generate-issue-content-helm-chart | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-22)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="581.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">release-management:generate-issue-content-providers | release-management:generate-providers-metadata | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-23)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="605.6" textLength="1110.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">release-management:install-provider-distributions | release-management:merge-prod-images | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-24)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="630" textLength="1159" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">release-management:mirror-base-images | release-management:prepare-airflow-ctl-distributions | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-25)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="654.4" textLength="1207.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">release-management:prepare-airflow-distributions | release-management:prepare-helm-chart-package | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-26)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="678.8" textLength="1171.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">release-management:prepare-helm-chart-tarball | release-management:prepare-mypy-distributions | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-27)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="703.2" textLength="1268.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">release-management:prepare-provider-distributions | release-management:prepare-provider-documentation | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-28)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="727.6" textLength="976" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">release-management:prepare-python-client | release-management:prepare-tarball | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-29)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="752" textLength="1049.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">release-management:prepare-task-sdk-distributions | release-management:publish-docs | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="752" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-30)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="776.4" textLength="1012.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">release-management:publish-docs-to-s3 | release-management:publish-schemas-to-s3 | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-31)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="800.8" textLength="988.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">release-management:release-prod-images | release-management:start-beta-process | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-32)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="825.2" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">release-management:start-rc-process | release-management:start-release | release-management:tag-providers</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-33)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="849.6" textLength="1134.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">| release-management:update-constraints | release-management:update-providers-next-version | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-34)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="874" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="874" textLength="1244.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">release-management:verify-provider-distributions | release-management:verify-rc-by-pmc | run | sbom | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="874" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="874" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-35)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="898.4" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">sbom:build-all-airflow-images | sbom:export-dependency-information | sbom:generate-providers-requirements</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-36)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="922.8" textLength="1183.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">| sbom:update-sbom-information | setup | setup:autocomplete | setup:check-all-params-in-groups | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-37)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="947.2" textLength="1256.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">setup:config | setup:regenerate-command-images | setup:self-upgrade | setup:synchronize-local-mounts | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-38)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="971.6" textLength="1098" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">setup:version | shell | start-airflow | testing | testing:airflow-ctl-integration-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-39)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="996" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="996" textLength="1085.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">testing:airflow-ctl-tests | testing:airflow-e2e-tests | testing:core-integration-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="996" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="996" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-40)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1020.4" textLength="890.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">testing:core-tests | testing:docker-compose-tests | testing:helm-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-41)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1044.8" textLength="1195.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">testing:providers-integration-tests | testing:providers-tests | testing:python-api-client-tests | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-42)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1069.2" textLength="1281" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">testing:system-tests | testing:task-sdk-integration-tests | testing:task-sdk-tests | testing:ui-e2e-tests</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-43)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1093.6" textLength="1061.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">| ui | ui:check-translation-completeness | ui:compile-assets | verify | workflow-run | </text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-44)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1118" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-45)">│</text><text class="breeze-setup-check-all-params-in-groups-r6" x="158.6" y="1118" textLength="1183.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-45)">workflow-run:publish-docs | workflow-run:release-constraints | workflow-run:sync-staging-to-main)</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1118" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-45)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1118" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-45)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1142.4" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-46)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-46)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1166.8" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">╭─</text><text class="breeze-setup-check-all-params-in-groups-r5" x="24.4" y="1166.8" textLength="195.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)"> Common options </text><text class="breeze-setup-check-all-params-in-groups-r5" x="219.6" y="1166.8" textLength="1220" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1439.6" y="1166.8" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">─╮</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-47)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="1191.2" textLength="109.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">--verbose</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="1191.2" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">-v</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="1191.2" textLength="585.6" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">Print verbose information about performed steps.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-48)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="1215.6" textLength="109.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">--dry-run</text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="1215.6" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">-D</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="1215.6" textLength="719.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">If dry-run is set, commands are only printed, not executed.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-49)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1240" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">│</text><text class="breeze-setup-check-all-params-in-groups-r4" x="24.4" y="1240" textLength="109.8" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">--help   </text><text class="breeze-setup-check-all-params-in-groups-r7" x="158.6" y="1240" textLength="24.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">-h</text><text class="breeze-setup-check-all-params-in-groups-r1" x="207.4" y="1240" textLength="329.4" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">Show this message and exit.</text><text class="breeze-setup-check-all-params-in-groups-r5" x="1451.8" y="1240" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">│</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1240" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-50)">
|
||||
</text><text class="breeze-setup-check-all-params-in-groups-r5" x="0" y="1264.4" textLength="1464" clip-path="url(#breeze-setup-check-all-params-in-groups-line-51)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-check-all-params-in-groups-r1" x="1464" y="1264.4" textLength="12.2" clip-path="url(#breeze-setup-check-all-params-in-groups-line-51)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 50 KiB |
@@ -1 +1 @@
|
||||
525c07613a5bcce29aeb394a631aee01
|
||||
f171eb2c2e78f67a3ccd1bf977faf841
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 1416.3999999999999" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class="rich-terminal" viewBox="0 0 1482 1440.8" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Generated with Rich https://www.textualize.io -->
|
||||
<style>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
<defs>
|
||||
<clipPath id="breeze-setup-regenerate-command-images-clip-terminal">
|
||||
<rect x="0" y="0" width="1463.0" height="1365.3999999999999" />
|
||||
<rect x="0" y="0" width="1463.0" height="1389.8" />
|
||||
</clipPath>
|
||||
<clipPath id="breeze-setup-regenerate-command-images-line-0">
|
||||
<rect x="0" y="1.5" width="1464" height="24.65"/>
|
||||
@@ -210,9 +210,12 @@
|
||||
<clipPath id="breeze-setup-regenerate-command-images-line-54">
|
||||
<rect x="0" y="1319.1" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
<clipPath id="breeze-setup-regenerate-command-images-line-55">
|
||||
<rect x="0" y="1343.5" width="1464" height="24.65"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="1414.4" rx="8"/><text class="breeze-setup-regenerate-command-images-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup regenerate-command-images</text>
|
||||
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="1438.8" rx="8"/><text class="breeze-setup-regenerate-command-images-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command: setup regenerate-command-images</text>
|
||||
<g transform="translate(26,22)">
|
||||
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
|
||||
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
|
||||
@@ -231,53 +234,54 @@
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="166.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-6)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="166.4" textLength="146.4" clip-path="url(#breeze-setup-regenerate-command-images-line-6)">--force     </text><text class="breeze-setup-regenerate-command-images-r1" x="195.2" y="166.4" textLength="402.6" clip-path="url(#breeze-setup-regenerate-command-images-line-6)">Forces regeneration of all images</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="166.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-6)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-6)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="190.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-7)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="190.8" textLength="146.4" clip-path="url(#breeze-setup-regenerate-command-images-line-7)">--command   </text><text class="breeze-setup-regenerate-command-images-r1" x="195.2" y="190.8" textLength="805.2" clip-path="url(#breeze-setup-regenerate-command-images-line-7)">Command(s) to regenerate images for (optional, might be repeated) </text><text class="breeze-setup-regenerate-command-images-r6" x="1000.4" y="190.8" textLength="366" clip-path="url(#breeze-setup-regenerate-command-images-line-7)">(build-docs | ci | ci-image | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="190.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-7)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-7)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-8)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="215.2" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-8)">ci-image:build | ci-image:export-mount-cache | ci-image:import-mount-cache | ci-image:load | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-8)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-8)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="239.6" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">ci-image:pull | ci-image:save | ci-image:verify | ci:audit | ci:fix-ownership | ci:fork-ci-reconcile |</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="264" textLength="1207.8" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">ci:free-space | ci:get-workflow-info | ci:resource-check | ci:selective-check | ci:set-milestone | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="264" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="288.4" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">ci:upgrade | cleanup | doctor | down | exec | generate-migration-file | issues | issues:unassign | k8s</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="312.8" textLength="1098" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">| k8s:build-k8s-image | k8s:configure-cluster | k8s:create-cluster | k8s:delete-cluster | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="337.2" textLength="1195.6" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">k8s:deploy-airflow | k8s:deploy-cluster | k8s:dev | k8s:k9s | k8s:logs | k8s:run-complete-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="361.6" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">k8s:setup-env | k8s:setup-lang-sdk-test | k8s:shell | k8s:smoke-test-overlay | k8s:status | k8s:tests </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="386" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">| k8s:upload-k8s-image | prod-image | prod-image:build | prod-image:load | prod-image:pull | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="386" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="410.4" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">prod-image:save | prod-image:verify | registry | registry:backfill | registry:extract-data | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="434.8" textLength="1098" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">registry:publish-versions | release-management | release-management:add-back-references | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="459.2" textLength="1073.6" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">release-management:check-release-files | release-management:classify-provider-changes | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="483.6" textLength="1183.4" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">release-management:clean-old-provider-artifacts | release-management:constraints-version-check | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="508" textLength="1122.4" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">release-management:create-minor-branch | release-management:generate-airflowctl-changelog | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="532.4" textLength="1195.6" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">release-management:generate-constraints | release-management:generate-issue-content-airflow-ctl | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="556.8" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">release-management:generate-issue-content-core | release-management:generate-issue-content-helm-chart </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="581.2" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">| release-management:generate-issue-content-providers | release-management:generate-providers-metadata</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="605.6" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">| release-management:install-provider-distributions | release-management:merge-prod-images | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="630" textLength="1159" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">release-management:mirror-base-images | release-management:prepare-airflow-ctl-distributions | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="654.4" textLength="1207.8" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">release-management:prepare-airflow-distributions | release-management:prepare-helm-chart-package | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="678.8" textLength="1171.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">release-management:prepare-helm-chart-tarball | release-management:prepare-mypy-distributions | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="703.2" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">release-management:prepare-provider-distributions | release-management:prepare-provider-documentation </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="727.6" textLength="1000.4" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">| release-management:prepare-python-client | release-management:prepare-tarball | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="752" textLength="1049.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">release-management:prepare-task-sdk-distributions | release-management:publish-docs | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="776.4" textLength="1012.6" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:publish-docs-to-s3 | release-management:publish-schemas-to-s3 | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="800.8" textLength="988.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">release-management:release-prod-images | release-management:start-beta-process | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="825.2" textLength="890.6" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">release-management:start-rc-process | release-management:start-release | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="849.6" textLength="915" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">release-management:tag-providers | release-management:update-constraints | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="874" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">release-management:update-providers-next-version | release-management:verify-provider-distributions | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="898.4" textLength="1012.6" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">release-management:verify-rc-by-pmc | run | sbom | sbom:build-all-airflow-images | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="922.8" textLength="927.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">sbom:export-dependency-information | sbom:generate-providers-requirements | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="947.2" textLength="1159" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">sbom:update-sbom-information | setup | setup:autocomplete | setup:check-all-params-in-groups | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="971.6" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">setup:config | setup:regenerate-command-images | setup:self-upgrade | setup:synchronize-local-mounts |</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="996" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="996" textLength="1098" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">setup:version | shell | start-airflow | testing | testing:airflow-ctl-integration-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="996" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="996" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1020.4" textLength="1085.8" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">testing:airflow-ctl-tests | testing:airflow-e2e-tests | testing:core-integration-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1044.8" textLength="890.6" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">testing:core-tests | testing:docker-compose-tests | testing:helm-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1069.2" textLength="1195.6" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">testing:providers-integration-tests | testing:providers-tests | testing:python-api-client-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1093.6" textLength="1037" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">testing:system-tests | testing:task-sdk-integration-tests | testing:task-sdk-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1118" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1118" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">testing:ui-e2e-tests | ui | ui:check-translation-completeness | ui:compile-assets | verify | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1118" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1118" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1142.4" textLength="951.6" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">workflow-run | workflow-run:publish-docs | workflow-run:release-constraints | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1166.8" textLength="414.8" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">workflow-run:sync-staging-to-main)</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1191.2" textLength="146.4" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">--check-only</text><text class="breeze-setup-regenerate-command-images-r1" x="195.2" y="1191.2" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">Only check if some images need to be regenerated. Return 0 if no need or 1 if needed. Cannot be used  </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="195.2" y="1215.6" textLength="170.8" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">together with </text><text class="breeze-setup-regenerate-command-images-r4" x="366" y="1215.6" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">--command</text><text class="breeze-setup-regenerate-command-images-r1" x="475.8" y="1215.6" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-49)"> flag or </text><text class="breeze-setup-regenerate-command-images-r4" x="585.6" y="1215.6" textLength="85.4" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">--force</text><text class="breeze-setup-regenerate-command-images-r1" x="671" y="1215.6" textLength="768.6" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">.                                                              </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1240" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1240" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1264.4" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-51)">╭─</text><text class="breeze-setup-regenerate-command-images-r5" x="24.4" y="1264.4" textLength="195.2" clip-path="url(#breeze-setup-regenerate-command-images-line-51)"> Common options </text><text class="breeze-setup-regenerate-command-images-r5" x="219.6" y="1264.4" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-51)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-setup-regenerate-command-images-r5" x="1439.6" y="1264.4" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-51)">─╮</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1264.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-51)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1288.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1288.8" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">--verbose</text><text class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1288.8" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">-v</text><text class="breeze-setup-regenerate-command-images-r1" x="207.4" y="1288.8" textLength="585.6" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">Print verbose information about performed steps.</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1288.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1288.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1313.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1313.2" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">--dry-run</text><text class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1313.2" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">-D</text><text class="breeze-setup-regenerate-command-images-r1" x="207.4" y="1313.2" textLength="719.8" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">If dry-run is set, commands are only printed, not executed.</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1313.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1313.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1337.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1337.6" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">--help   </text><text class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1337.6" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">-h</text><text class="breeze-setup-regenerate-command-images-r1" x="207.4" y="1337.6" textLength="329.4" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">Show this message and exit.</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1337.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1337.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1362" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1362" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="239.6" textLength="1073.6" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">ci-image:pull | ci-image:save | ci-image:verify | ci:approve-workflow-runs | ci:audit | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-9)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="264" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="264" textLength="1232.2" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">ci:fix-ownership | ci:fork-ci-reconcile | ci:free-space | ci:get-workflow-info | ci:resource-check | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="264" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="264" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-10)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="288.4" textLength="1049.2" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">ci:selective-check | ci:set-milestone | ci:upgrade | cleanup | doctor | down | exec | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-11)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="312.8" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">generate-migration-file | issues | issues:unassign | k8s | k8s:build-k8s-image | k8s:configure-cluster</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-12)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="337.2" textLength="1171.2" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">| k8s:create-cluster | k8s:delete-cluster | k8s:deploy-airflow | k8s:deploy-cluster | k8s:dev | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-13)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="361.6" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">k8s:k9s | k8s:logs | k8s:run-complete-tests | k8s:setup-env | k8s:setup-lang-sdk-test | k8s:shell | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-14)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="386" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="386" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">k8s:smoke-test-overlay | k8s:status | k8s:tests | k8s:upload-k8s-image | prod-image | prod-image:build</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="386" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="386" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-15)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="410.4" textLength="1061.4" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">| prod-image:load | prod-image:pull | prod-image:save | prod-image:verify | registry | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-16)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="434.8" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">registry:backfill | registry:extract-data | registry:publish-versions | release-management | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-17)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="459.2" textLength="1000.4" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">release-management:add-back-references | release-management:check-release-files | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-18)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="483.6" textLength="1183.4" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">release-management:classify-provider-changes | release-management:clean-old-provider-artifacts | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-19)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="508" textLength="1073.6" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">release-management:constraints-version-check | release-management:create-minor-branch | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="508" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-20)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="532.4" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">release-management:generate-airflowctl-changelog | release-management:generate-constraints | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-21)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="556.8" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">release-management:generate-issue-content-airflow-ctl | release-management:generate-issue-content-core</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-22)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="581.2" textLength="695.4" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">| release-management:generate-issue-content-helm-chart | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-23)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="605.6" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">release-management:generate-issue-content-providers | release-management:generate-providers-metadata |</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-24)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="630" textLength="1110.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">release-management:install-provider-distributions | release-management:merge-prod-images | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="630" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-25)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="654.4" textLength="1159" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">release-management:mirror-base-images | release-management:prepare-airflow-ctl-distributions | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-26)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="678.8" textLength="1207.8" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">release-management:prepare-airflow-distributions | release-management:prepare-helm-chart-package | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-27)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="703.2" textLength="1171.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">release-management:prepare-helm-chart-tarball | release-management:prepare-mypy-distributions | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-28)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="727.6" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">release-management:prepare-provider-distributions | release-management:prepare-provider-documentation </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-29)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="752" textLength="1000.4" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">| release-management:prepare-python-client | release-management:prepare-tarball | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="752" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-30)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="776.4" textLength="1049.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">release-management:prepare-task-sdk-distributions | release-management:publish-docs | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-31)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="800.8" textLength="1012.6" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">release-management:publish-docs-to-s3 | release-management:publish-schemas-to-s3 | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-32)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="825.2" textLength="988.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">release-management:release-prod-images | release-management:start-beta-process | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-33)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="849.6" textLength="890.6" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">release-management:start-rc-process | release-management:start-release | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-34)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="874" textLength="915" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">release-management:tag-providers | release-management:update-constraints | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="874" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-35)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="898.4" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">release-management:update-providers-next-version | release-management:verify-provider-distributions | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="898.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-36)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="922.8" textLength="1012.6" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">release-management:verify-rc-by-pmc | run | sbom | sbom:build-all-airflow-images | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="922.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-37)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="947.2" textLength="927.2" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">sbom:export-dependency-information | sbom:generate-providers-requirements | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="947.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-38)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="971.6" textLength="1159" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">sbom:update-sbom-information | setup | setup:autocomplete | setup:check-all-params-in-groups | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="971.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-39)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="996" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="996" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">setup:config | setup:regenerate-command-images | setup:self-upgrade | setup:synchronize-local-mounts |</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="996" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="996" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-40)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1020.4" textLength="1098" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">setup:version | shell | start-airflow | testing | testing:airflow-ctl-integration-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1020.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-41)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1044.8" textLength="1085.8" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">testing:airflow-ctl-tests | testing:airflow-e2e-tests | testing:core-integration-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1044.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-42)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1069.2" textLength="890.6" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">testing:core-tests | testing:docker-compose-tests | testing:helm-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1069.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-43)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1093.6" textLength="1195.6" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">testing:providers-integration-tests | testing:providers-tests | testing:python-api-client-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1093.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-44)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1118" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1118" textLength="1037" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">testing:system-tests | testing:task-sdk-integration-tests | testing:task-sdk-tests | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1118" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1118" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-45)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1142.4" textLength="1134.6" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">testing:ui-e2e-tests | ui | ui:check-translation-completeness | ui:compile-assets | verify | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1142.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-46)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1166.8" textLength="951.6" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">workflow-run | workflow-run:publish-docs | workflow-run:release-constraints | </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1166.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-47)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">│</text><text class="breeze-setup-regenerate-command-images-r6" x="195.2" y="1191.2" textLength="414.8" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">workflow-run:sync-staging-to-main)</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1191.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-48)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1215.6" textLength="146.4" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">--check-only</text><text class="breeze-setup-regenerate-command-images-r1" x="195.2" y="1215.6" textLength="1244.4" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">Only check if some images need to be regenerated. Return 0 if no need or 1 if needed. Cannot be used  </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1215.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-49)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1240" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="195.2" y="1240" textLength="170.8" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">together with </text><text class="breeze-setup-regenerate-command-images-r4" x="366" y="1240" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">--command</text><text class="breeze-setup-regenerate-command-images-r1" x="475.8" y="1240" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-50)"> flag or </text><text class="breeze-setup-regenerate-command-images-r4" x="585.6" y="1240" textLength="85.4" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">--force</text><text class="breeze-setup-regenerate-command-images-r1" x="671" y="1240" textLength="768.6" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">.                                                              </text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1240" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1240" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-50)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1264.4" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-51)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1264.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-51)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1288.8" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">╭─</text><text class="breeze-setup-regenerate-command-images-r5" x="24.4" y="1288.8" textLength="195.2" clip-path="url(#breeze-setup-regenerate-command-images-line-52)"> Common options </text><text class="breeze-setup-regenerate-command-images-r5" x="219.6" y="1288.8" textLength="1220" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="breeze-setup-regenerate-command-images-r5" x="1439.6" y="1288.8" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">─╮</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1288.8" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-52)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1313.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1313.2" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">--verbose</text><text class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1313.2" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">-v</text><text class="breeze-setup-regenerate-command-images-r1" x="207.4" y="1313.2" textLength="585.6" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">Print verbose information about performed steps.</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1313.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1313.2" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-53)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1337.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1337.6" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">--dry-run</text><text class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1337.6" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">-D</text><text class="breeze-setup-regenerate-command-images-r1" x="207.4" y="1337.6" textLength="719.8" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">If dry-run is set, commands are only printed, not executed.</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1337.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1337.6" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-54)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1362" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">│</text><text class="breeze-setup-regenerate-command-images-r4" x="24.4" y="1362" textLength="109.8" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">--help   </text><text class="breeze-setup-regenerate-command-images-r7" x="158.6" y="1362" textLength="24.4" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">-h</text><text class="breeze-setup-regenerate-command-images-r1" x="207.4" y="1362" textLength="329.4" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">Show this message and exit.</text><text class="breeze-setup-regenerate-command-images-r5" x="1451.8" y="1362" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">│</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1362" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-55)">
|
||||
</text><text class="breeze-setup-regenerate-command-images-r5" x="0" y="1386.4" textLength="1464" clip-path="url(#breeze-setup-regenerate-command-images-line-56)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="breeze-setup-regenerate-command-images-r1" x="1464" y="1386.4" textLength="12.2" clip-path="url(#breeze-setup-regenerate-command-images-line-56)">
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
@@ -1 +1 @@
|
||||
3588c0e4f1fda167e7f07b6d1b7843de
|
||||
17b27f3a6bfb16a9119e47440e68e7f3
|
||||
@@ -26,6 +26,7 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from collections.abc import Iterable
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, NamedTuple
|
||||
@@ -1797,3 +1798,56 @@ def audit(fix: bool):
|
||||
run_command(shlex.split(command), check=False)
|
||||
failed = [result for result in report() if result.status == CheckStatus.FAIL]
|
||||
sys.exit(1 if failed else 0)
|
||||
|
||||
|
||||
@ci_group.command(
|
||||
name="approve-workflow-runs",
|
||||
help="Approve the waiting workflow runs of external contributors' PRs whose changes are safe "
|
||||
"to run without a maintainer's look, and label the others 'need workflow approval'. "
|
||||
"Used by the auto-approve-workflow-runs workflow.",
|
||||
)
|
||||
@click.option(
|
||||
"--github-token",
|
||||
help="GitHub token able to approve workflow runs and label PRs.",
|
||||
envvar="GITHUB_TOKEN",
|
||||
required=True,
|
||||
)
|
||||
@click.option(
|
||||
"--max-run-age-hours",
|
||||
help="Only decide on workflow runs created within this many hours; older waiting runs are left alone.",
|
||||
type=click.IntRange(min=1),
|
||||
default=24,
|
||||
show_default=True,
|
||||
envvar="MAX_RUN_AGE_HOURS",
|
||||
)
|
||||
@click.option(
|
||||
"--report-only",
|
||||
is_flag=True,
|
||||
help="Only report the decisions and estimates, without approving runs or changing labels.",
|
||||
envvar="REPORT_ONLY",
|
||||
)
|
||||
@option_github_repository
|
||||
@option_verbose
|
||||
@option_dry_run
|
||||
def approve_workflow_runs(
|
||||
github_token: str, max_run_age_hours: int, report_only: bool, github_repository: str
|
||||
):
|
||||
from airflow_breeze.utils.shared_options import get_dry_run
|
||||
from airflow_breeze.utils.workflow_run_approval import (
|
||||
GitHubApi,
|
||||
process_waiting_runs,
|
||||
write_step_summary,
|
||||
)
|
||||
|
||||
api = GitHubApi(
|
||||
github_repository=github_repository,
|
||||
github_token=github_token,
|
||||
report_only=report_only or get_dry_run(),
|
||||
)
|
||||
created_since = datetime.now(UTC) - timedelta(hours=max_run_age_hours)
|
||||
results = process_waiting_runs(api, created_since=created_since)
|
||||
write_step_summary(results, github_repository)
|
||||
failed_prs = [result.pr_number for result in results if result.failed]
|
||||
if failed_prs:
|
||||
console_print(f"[error]Processing failed for PRs: {', '.join(f'#{n}' for n in failed_prs)}[/]")
|
||||
sys.exit(1)
|
||||
@@ -28,6 +28,7 @@ CI_COMMANDS: dict[str, str | list[str]] = {
|
||||
"set-milestone",
|
||||
"fork-ci-reconcile",
|
||||
"audit",
|
||||
"approve-workflow-runs",
|
||||
],
|
||||
}
|
||||
CI_PARAMETERS: dict[str, list[dict[str, str | list[str]]]] = {
|
||||
@@ -140,4 +141,20 @@ CI_PARAMETERS: dict[str, list[dict[str, str | list[str]]]] = {
|
||||
],
|
||||
},
|
||||
],
|
||||
"breeze ci approve-workflow-runs": [
|
||||
{
|
||||
"name": "Approval flags",
|
||||
"options": [
|
||||
"--max-run-age-hours",
|
||||
"--report-only",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "GitHub parameters",
|
||||
"options": [
|
||||
"--github-token",
|
||||
"--github-repository",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
# 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.
|
||||
"""
|
||||
Estimate the GitHub Actions minutes a ``Tests (AMD)`` PR run takes from its selective-check outputs.
|
||||
|
||||
The numbers are medians measured on recent PR runs on GitHub-hosted (public) runners, which is where
|
||||
fork PRs run. They are estimates for deciding whether a change's CI run is cheap enough to approve
|
||||
without a maintainer, not a bill: queueing, retries and cache misses are not modelled.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from airflow_breeze.global_constants import all_selective_core_test_types
|
||||
from airflow_breeze.utils.path_utils import AIRFLOW_ROOT_PATH
|
||||
|
||||
# TODO: refresh these estimates periodically with an agent, and always after changing the CI
|
||||
# workflows (see .github/AGENTS.md). Run ``dev/calibrate_ci_minutes_estimates.py`` and copy the
|
||||
# medians it prints into the constants below.
|
||||
# Last calibrated: 2026-10-23, from 310 successful ``Tests (AMD)`` PR runs of 2026-10-13..2026-10-23,
|
||||
# 224 of which tested a partial set of providers.
|
||||
# TODO: add a second set of estimates for self-hosted (RunsOn) runners once enough runs on them exist
|
||||
# to measure. Their machine sizes differ, so the public-runner numbers do not carry over.
|
||||
|
||||
# Each entry: (job-minutes, minutes the group adds to the run's critical path after the CI image).
|
||||
BASIC_CHECKS_ONLY_ESTIMATE = (6, 3)
|
||||
BASE_ESTIMATE = (47, 17)
|
||||
DOCS_ESTIMATE = (15, 10)
|
||||
# The PROD image waits for constraints, so its tests sit about 26 minutes after the CI image.
|
||||
PROD_IMAGE_ESTIMATE = (51, 26)
|
||||
KUBERNETES_ESTIMATE = (84, 29)
|
||||
HELM_ESTIMATE = (55, 10)
|
||||
KUSTOMIZE_ESTIMATE = (6, 6)
|
||||
INTEGRATION_ESTIMATE = (5, 5)
|
||||
SPECIAL_TESTS_ESTIMATE = (317, 32)
|
||||
TASK_SDK_ESTIMATE = (6, 6)
|
||||
AGENT_FRAMEWORK_ESTIMATE = (11, 5)
|
||||
JAVA_SDK_ESTIMATE = (7, 4)
|
||||
GO_SDK_ESTIMATE = (1, 1)
|
||||
TS_SDK_ESTIMATE = (1, 1)
|
||||
TS_SDK_DOCS_ESTIMATE = (1, 1)
|
||||
# The provider mypy job runs whenever provider code changes, also without provider unit tests.
|
||||
MYPY_PROVIDERS_ESTIMATE = (8, 8)
|
||||
AIRFLOW_CTL_ESTIMATE = (1, 1)
|
||||
|
||||
# Core tests: about 38 job-minutes for the first test type and 61 for each further one, up to
|
||||
# the cost of all core test types.
|
||||
CORE_FIRST_TEST_TYPE_MINUTES = 38
|
||||
CORE_EXTRA_TEST_TYPE_MINUTES = 61
|
||||
CORE_ALL_TEST_TYPES_MINUTES = 222
|
||||
CORE_LONGEST_JOB_MINUTES = {1: 11, 2: 29}
|
||||
CORE_LONGEST_JOB_MINUTES_DEFAULT = 32
|
||||
|
||||
# Provider tests (DB/non-DB, lowest dependencies, compatibility, distributions) scale with the size of
|
||||
# the tested providers' test suites: amazon or google cost far more than a small provider. Fitted on
|
||||
# 224 runs testing 2 to 22 providers, together with the provider mypy job: job-minutes ~= 105 + 0.161
|
||||
# per provider test file, and the longest provider job ~= 16 + 0.015 per test file, both capped at the
|
||||
# cost of testing all providers. The mypy job's median is taken off the base and the all-providers cost.
|
||||
PROVIDERS_BASE_MINUTES = 105 - MYPY_PROVIDERS_ESTIMATE[0]
|
||||
PROVIDERS_MINUTES_PER_TEST_FILE = 0.161
|
||||
PROVIDERS_ALL_MINUTES = 315 - MYPY_PROVIDERS_ESTIMATE[0]
|
||||
PROVIDERS_LONGEST_JOB_BASE_MINUTES = 16
|
||||
PROVIDERS_LONGEST_JOB_MINUTES_PER_TEST_FILE = 0.015
|
||||
PROVIDERS_ALL_LONGEST_JOB_MINUTES = 36
|
||||
|
||||
# Build info, the CI image build, queueing and the final jobs before and after the parallel part.
|
||||
RUN_OVERHEAD_MINUTES = 18
|
||||
|
||||
|
||||
@dataclass
|
||||
class EstimatedJobGroup:
|
||||
name: str
|
||||
job_minutes: int
|
||||
critical_path_minutes: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class CiMinutesEstimate:
|
||||
job_groups: list[EstimatedJobGroup]
|
||||
|
||||
@property
|
||||
def job_minutes(self) -> int:
|
||||
return sum(group.job_minutes for group in self.job_groups)
|
||||
|
||||
@property
|
||||
def wall_clock_minutes(self) -> int:
|
||||
if not self.job_groups:
|
||||
return 0
|
||||
longest = max(group.critical_path_minutes for group in self.job_groups)
|
||||
if self.job_groups[0].name == "Basic checks only":
|
||||
return longest
|
||||
return RUN_OVERHEAD_MINUTES + longest
|
||||
|
||||
|
||||
def estimate_core_job_minutes(core_test_types: int) -> int:
|
||||
if core_test_types == 0:
|
||||
return 0
|
||||
return min(
|
||||
CORE_FIRST_TEST_TYPE_MINUTES + CORE_EXTRA_TEST_TYPE_MINUTES * (core_test_types - 1),
|
||||
CORE_ALL_TEST_TYPES_MINUTES,
|
||||
)
|
||||
|
||||
|
||||
def count_provider_test_files(provider_id: str) -> int:
|
||||
tests_path = AIRFLOW_ROOT_PATH / "providers" / Path(*provider_id.split(".")) / "tests"
|
||||
return sum(1 for _ in tests_path.rglob("test_*.py"))
|
||||
|
||||
|
||||
def find_tested_provider_ids(provider_test_types: list[str]) -> list[str] | None:
|
||||
"""Return the ids of individually tested providers, or None when all providers are tested."""
|
||||
provider_ids = []
|
||||
for test_type in provider_test_types:
|
||||
if not test_type.startswith("Providers[") or test_type.startswith("Providers[-"):
|
||||
return None
|
||||
provider_ids.extend(test_type[len("Providers[") : -1].split(","))
|
||||
return provider_ids
|
||||
|
||||
|
||||
def estimate_providers_group(provider_test_types: list[str]) -> EstimatedJobGroup | None:
|
||||
if not provider_test_types:
|
||||
return None
|
||||
provider_ids = find_tested_provider_ids(provider_test_types)
|
||||
if provider_ids is None:
|
||||
return EstimatedJobGroup(
|
||||
"Provider tests (all providers)", PROVIDERS_ALL_MINUTES, PROVIDERS_ALL_LONGEST_JOB_MINUTES
|
||||
)
|
||||
test_files = sum(count_provider_test_files(provider_id) for provider_id in provider_ids)
|
||||
return EstimatedJobGroup(
|
||||
f"Provider tests ({len(provider_ids)} providers, {test_files} test files)",
|
||||
min(
|
||||
round(PROVIDERS_BASE_MINUTES + PROVIDERS_MINUTES_PER_TEST_FILE * test_files),
|
||||
PROVIDERS_ALL_MINUTES,
|
||||
),
|
||||
min(
|
||||
round(
|
||||
PROVIDERS_LONGEST_JOB_BASE_MINUTES + PROVIDERS_LONGEST_JOB_MINUTES_PER_TEST_FILE * test_files
|
||||
),
|
||||
PROVIDERS_ALL_LONGEST_JOB_MINUTES,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# Jobs that need only build-info, so they also run when no CI image is built. The Java SDK group
|
||||
# includes its docs job.
|
||||
IMAGE_INDEPENDENT_GROUPS = (
|
||||
("run_java_sdk_tests", "Java SDK tests", JAVA_SDK_ESTIMATE),
|
||||
("run_go_sdk_tests", "Go SDK tests", GO_SDK_ESTIMATE),
|
||||
("run_ts_sdk_tests", "TypeScript SDK tests", TS_SDK_ESTIMATE),
|
||||
("run_ts_sdk_docs", "TypeScript SDK docs", TS_SDK_DOCS_ESTIMATE),
|
||||
("run_airflow_ctl_tests", "Airflow CTL tests", AIRFLOW_CTL_ESTIMATE),
|
||||
)
|
||||
|
||||
|
||||
def estimate_image_independent_groups(selective_checks: Any) -> list[EstimatedJobGroup]:
|
||||
return [
|
||||
EstimatedJobGroup(name, *estimate)
|
||||
for flag, name, estimate in IMAGE_INDEPENDENT_GROUPS
|
||||
if getattr(selective_checks, flag)
|
||||
]
|
||||
|
||||
|
||||
def estimate_ci_minutes(selective_checks: Any) -> CiMinutesEstimate:
|
||||
"""Estimate the job groups, job-minutes and wall-clock time of a ``Tests (AMD)`` PR run."""
|
||||
if selective_checks.basic_checks_only:
|
||||
return CiMinutesEstimate(
|
||||
[
|
||||
EstimatedJobGroup("Basic checks only", *BASIC_CHECKS_ONLY_ESTIMATE),
|
||||
*estimate_image_independent_groups(selective_checks),
|
||||
]
|
||||
)
|
||||
groups = [EstimatedJobGroup("CI image, basic tests and static checks", *BASE_ESTIMATE)]
|
||||
if selective_checks.docs_build:
|
||||
groups.append(EstimatedJobGroup("Documentation build", *DOCS_ESTIMATE))
|
||||
if selective_checks.run_unit_tests:
|
||||
core_test_types = len(selective_checks._get_core_test_types_to_run())
|
||||
if core_test_types:
|
||||
all_types = core_test_types >= len(all_selective_core_test_types())
|
||||
groups.append(
|
||||
EstimatedJobGroup(
|
||||
f"Core tests ({'all' if all_types else core_test_types} test types)",
|
||||
estimate_core_job_minutes(core_test_types),
|
||||
CORE_LONGEST_JOB_MINUTES.get(core_test_types, CORE_LONGEST_JOB_MINUTES_DEFAULT),
|
||||
)
|
||||
)
|
||||
groups.append(EstimatedJobGroup("Integration and system tests", *INTEGRATION_ESTIMATE))
|
||||
# Like the provider test jobs of ci-amd.yml, which all need run-unit-tests.
|
||||
if selective_checks.run_unit_tests and not selective_checks.skip_providers_tests:
|
||||
providers_group = estimate_providers_group(
|
||||
selective_checks._get_providers_test_types_to_run(split_to_individual_providers=True)
|
||||
)
|
||||
if providers_group:
|
||||
groups.append(providers_group)
|
||||
if selective_checks.run_mypy_providers:
|
||||
groups.append(EstimatedJobGroup("Provider mypy checks", *MYPY_PROVIDERS_ESTIMATE))
|
||||
if selective_checks.full_tests_needed:
|
||||
groups.append(EstimatedJobGroup("Special tests", *SPECIAL_TESTS_ESTIMATE))
|
||||
optional_groups = (
|
||||
("prod_image_build", "PROD image build and tests", PROD_IMAGE_ESTIMATE),
|
||||
("run_kubernetes_tests", "Kubernetes tests", KUBERNETES_ESTIMATE),
|
||||
("run_helm_tests", "Helm tests", HELM_ESTIMATE),
|
||||
("run_kustomize_overlays_tests", "Kustomize overlays tests", KUSTOMIZE_ESTIMATE),
|
||||
("run_task_sdk_tests", "Task SDK tests", TASK_SDK_ESTIMATE),
|
||||
("run_agent_framework_tests", "Agent framework tests", AGENT_FRAMEWORK_ESTIMATE),
|
||||
)
|
||||
for flag, name, estimate in optional_groups:
|
||||
if getattr(selective_checks, flag):
|
||||
groups.append(EstimatedJobGroup(name, *estimate))
|
||||
groups.extend(estimate_image_independent_groups(selective_checks))
|
||||
return CiMinutesEstimate(groups)
|
||||
@@ -214,6 +214,33 @@ def tamper_close_comment(*, run_url: str) -> str:
|
||||
)
|
||||
|
||||
|
||||
CI_CHANGE_MARKER = "<!-- workflow-approval: ci-change -->"
|
||||
# A long list of contributor-chosen paths would bury the explanation.
|
||||
MAX_LISTED_CI_FILES = 10
|
||||
|
||||
|
||||
def _sanitize_path(path: str) -> str:
|
||||
# File names are the contributor's; a backtick or a line break would end the code span and let
|
||||
# them post Markdown, including mentions, as the bot.
|
||||
return "".join(char if char.isprintable() and char != "`" else "?" for char in path)
|
||||
|
||||
|
||||
def ci_change_approval_comment(*, ci_files: list[str]) -> str:
|
||||
listed = [f"- `{_sanitize_path(path)}`" for path in ci_files[:MAX_LISTED_CI_FILES]]
|
||||
if len(ci_files) > MAX_LISTED_CI_FILES:
|
||||
listed.append(f"- and {len(ci_files) - MAX_LISTED_CI_FILES} more")
|
||||
return (
|
||||
f"{CI_CHANGE_MARKER}\n\n"
|
||||
"**Your CI change needs a maintainer.** CI for this pull request runs in your fork, and the "
|
||||
"workflow runs it starts in apache/airflow are approved automatically while they only run the "
|
||||
"fork CI gate. This pull request changes files that define what CI runs:\n\n"
|
||||
+ "\n".join(listed)
|
||||
+ "\n\nSuch a change can make project CI run on the project's runners, so its workflow runs in "
|
||||
"apache/airflow wait for a maintainer to review the change and approve them. CI in your fork "
|
||||
"is not affected, and its result stays visible on this pull request. " + WHY_FORK_CI + FOOTER
|
||||
)
|
||||
|
||||
|
||||
_STATUS_DESCRIPTIONS = {
|
||||
"setup_required": "Fork CI not set up - see the pull request comment",
|
||||
"awaiting_push": "Fork CI enabled, waiting for a push - see the pull request comment",
|
||||
|
||||
@@ -0,0 +1,793 @@
|
||||
# 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.
|
||||
"""
|
||||
Automatic approval of workflow runs from external contributors' fork PRs.
|
||||
|
||||
GitHub holds the workflow runs of a fork PR in ``action_required`` until someone with write access
|
||||
approves them. This module approves the runs of PRs to ``main`` that do not touch anything that
|
||||
defines CI or chooses runners, do not need the full set of tests or a dependency upgrade, and whose
|
||||
jobs, as selected by selective checks, are estimated to take a limited number of job-minutes.
|
||||
Everything else gets the ``need workflow approval`` label and waits for a maintainer.
|
||||
|
||||
A PR whose CI runs in the contributor's fork (AIP-120) is decided by one rule instead: its project
|
||||
CI run only executes the fork CI gate, so it is approved whatever its size, unless it changes files
|
||||
that define CI, in which case it waits for a maintainer and the author gets a comment saying why.
|
||||
|
||||
Only API metadata and git objects of the PR are read. The PR's code is never checked out or run:
|
||||
selective checks come from the trusted ``main`` checkout and only see the list of changed files
|
||||
and the PR's ``pyproject.toml`` contents through ``git show``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
from rich.markup import escape
|
||||
|
||||
from airflow_breeze.global_constants import GithubEvents
|
||||
from airflow_breeze.utils.ci_minutes_estimate import CiMinutesEstimate, estimate_ci_minutes
|
||||
from airflow_breeze.utils.console import console_print
|
||||
from airflow_breeze.utils.fork_ci_gate import (
|
||||
GATED_REASONS,
|
||||
LABEL_USE_FORK_CI,
|
||||
LABEL_USE_PROJECT_CI,
|
||||
GateConfig,
|
||||
GateEvent,
|
||||
decide,
|
||||
load_config,
|
||||
parse_github_datetime,
|
||||
)
|
||||
from airflow_breeze.utils.fork_ci_messages import CI_CHANGE_MARKER, ci_change_approval_comment
|
||||
from airflow_breeze.utils.fork_ci_reconcile import changes_ci_definition
|
||||
from airflow_breeze.utils.path_utils import AIRFLOW_ROOT_PATH
|
||||
from airflow_breeze.utils.run_utils import run_command
|
||||
from airflow_breeze.utils.selective_checks import (
|
||||
ALL_VERSIONS_LABEL,
|
||||
AREA_E2E_TESTS_LABEL,
|
||||
AREA_KUBERNETES_TESTS_LABEL,
|
||||
CANARY_LABEL,
|
||||
DEFAULT_VERSIONS_ONLY_LABEL,
|
||||
FULL_TESTS_NEEDED_LABEL,
|
||||
LATEST_VERSIONS_ONLY_LABEL,
|
||||
UPGRADE_TO_NEWER_DEPENDENCIES_LABEL,
|
||||
)
|
||||
|
||||
NEED_WORKFLOW_APPROVAL_LABEL = "need workflow approval"
|
||||
|
||||
# Only PRs to main are approved automatically. PRs to release branches (``v3-4-test``,
|
||||
# ``airflow-ctl/v0-1-test``, ...) run those branches' own, older workflows and always need a maintainer.
|
||||
AUTO_APPROVABLE_BASE_BRANCH = "main"
|
||||
|
||||
MAX_ERROR_TEXT_LENGTH = 200
|
||||
|
||||
# Changes here can change which runner a job uses (``runs-on:``, ``runner-type`` computed by
|
||||
# selective checks, the scripts build-info runs) or what the workflows do, so they always need a
|
||||
# maintainer's look.
|
||||
CI_DEFINITION_PATH_PREFIXES = (".github/", "dev/breeze/", "scripts/ci/")
|
||||
|
||||
# Dependency manifests and lock files. Selective checks only switch to dependency-upgrade mode for
|
||||
# pyproject.toml, but a changed lock file or JS / Go / Java manifest also changes what CI installs.
|
||||
DEPENDENCY_FILE_PATTERN = re.compile(
|
||||
r"(^|/)(pyproject\.toml|uv\.lock|requirements[^/]*\.txt|package\.json|pnpm-lock\.yaml"
|
||||
r"|package-lock\.json|yarn\.lock|go\.mod|go\.sum|build\.gradle(\.kts)?|settings\.gradle(\.kts)?"
|
||||
r"|gradle\.lockfile|libs\.versions\.toml|pom\.xml"
|
||||
r"|gradle-wrapper\.(properties|jar)|maven-wrapper\.(properties|jar)|gradlew(\.bat)?|mvnw(\.cmd)?)$"
|
||||
)
|
||||
|
||||
# About 23% of a full-tests run (~1330 job-minutes on public runners), just above the cluster of
|
||||
# single core areas and the Helm chart (274-301). Changes to large providers (amazon 364, google 374)
|
||||
# and anything bigger wait for a maintainer, to keep the load on the shared public runners down.
|
||||
MAX_AUTO_APPROVED_JOB_MINUTES = 310
|
||||
|
||||
# Larger changes to non-test code are features or behaviour changes rather than fixes, and get a
|
||||
# maintainer's look even when their CI is cheap. 100 lines is the 90th percentile of the PRs that
|
||||
# pass the other rules; above it the distribution thins out into feature-sized changes.
|
||||
MAX_AUTO_APPROVED_SOURCE_LINES = 100
|
||||
|
||||
# Files that are not counted as source: tests (including e2e tests), docs, newsfragments,
|
||||
# translations, lock files and images.
|
||||
NON_SOURCE_FILE_PATTERN = re.compile(
|
||||
r"(^|/)(tests?|test_utils|testing|[^/]*e2e[^/]*)/"
|
||||
r"|(^|/)test_[^/]*$|_test\.(py|go)$|\.test\.(ts|tsx|js)$|\.spec\.(ts|tsx)$|Test\.java$"
|
||||
r"|\.(md|rst|txt)$|(^|/)newsfragments/|(^|/)docs?/"
|
||||
r"|/i18n/locales/|uv\.lock$|pnpm-lock\.yaml$|package-lock\.json$|go\.sum$"
|
||||
r"|\.(svg|png|jpg|snap)$"
|
||||
)
|
||||
|
||||
GITHUB_API_URL = "https://api.github.com"
|
||||
|
||||
# Labels with which selective checks select a different set of tests or versions. Selective checks
|
||||
# read the labels of the run's event, so a run started before one was added or removed still runs
|
||||
# the selection of the labels it started with, which the current labels do not show.
|
||||
TEST_SELECTION_LABELS = frozenset(
|
||||
{
|
||||
ALL_VERSIONS_LABEL,
|
||||
AREA_E2E_TESTS_LABEL,
|
||||
AREA_KUBERNETES_TESTS_LABEL,
|
||||
CANARY_LABEL,
|
||||
DEFAULT_VERSIONS_ONLY_LABEL,
|
||||
FULL_TESTS_NEEDED_LABEL,
|
||||
LATEST_VERSIONS_ONLY_LABEL,
|
||||
UPGRADE_TO_NEWER_DEPENDENCIES_LABEL,
|
||||
}
|
||||
)
|
||||
|
||||
# Labels that move a PR between project CI and fork CI. The gate reads them when it runs, but falls
|
||||
# back to the labels of the run's event when it cannot, so a run started before one changed could
|
||||
# still run project CI.
|
||||
GATE_OVERRIDE_LABELS = frozenset({LABEL_USE_FORK_CI, LABEL_USE_PROJECT_CI})
|
||||
|
||||
# Read from the trusted main checkout, which is also the base branch whose gate job decides the
|
||||
# PRs that are approved automatically.
|
||||
FORK_CI_GATE_CONFIG_PATH = AIRFLOW_ROOT_PATH / ".github" / "fork-ci-gate.toml"
|
||||
|
||||
|
||||
@dataclass
|
||||
class ChangedFile:
|
||||
path: str
|
||||
changed_lines: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class ApprovalDecision:
|
||||
approve: bool
|
||||
reasons: list[str] = field(default_factory=list)
|
||||
estimate: CiMinutesEstimate | None = None
|
||||
# Posted on the PR once, when the runs are left for a maintainer.
|
||||
comment: str | None = None
|
||||
# The labels the decision depends on: runs started before one of them changed are not approved.
|
||||
decision_labels: frozenset[str] = TEST_SELECTION_LABELS
|
||||
|
||||
|
||||
def count_source_lines(changed_files: list[ChangedFile]) -> int:
|
||||
return sum(file.changed_lines for file in changed_files if not NON_SOURCE_FILE_PATTERN.search(file.path))
|
||||
|
||||
|
||||
def find_ci_definition_files(files: list[str]) -> list[str]:
|
||||
return [file for file in files if file.startswith(CI_DEFINITION_PATH_PREFIXES)]
|
||||
|
||||
|
||||
def find_dependency_files(files: list[str]) -> list[str]:
|
||||
return [file for file in files if DEPENDENCY_FILE_PATTERN.search(file)]
|
||||
|
||||
|
||||
def find_new_provider_files(files: list[str]) -> list[str]:
|
||||
"""
|
||||
Return provider.yaml files that the trusted checkout does not have.
|
||||
|
||||
Selective checks run from main's tree and do not know a provider the PR adds, so they cannot
|
||||
estimate its tests.
|
||||
"""
|
||||
return [
|
||||
file
|
||||
for file in files
|
||||
if file.startswith("providers/")
|
||||
and file.endswith("/provider.yaml")
|
||||
and not (AIRFLOW_ROOT_PATH / file).exists()
|
||||
]
|
||||
|
||||
|
||||
def is_gated_to_fork_ci(*, pr: dict[str, Any], github_repository: str, config: GateConfig) -> bool:
|
||||
"""Whether the PR's ``Tests (AMD)`` run only executes the fork CI gate (AIP-120)."""
|
||||
event = GateEvent(
|
||||
event_name="pull_request",
|
||||
repository=github_repository,
|
||||
ref="",
|
||||
head_repository=pr["head"]["repo"]["full_name"] if pr["head"].get("repo") else "",
|
||||
author_login=(pr.get("user") or {}).get("login") or "",
|
||||
author_association=pr.get("author_association") or "",
|
||||
created_at=parse_github_datetime(pr["created_at"]),
|
||||
labels=tuple(label["name"] for label in pr.get("labels", [])),
|
||||
)
|
||||
return decide(event, config).reason in GATED_REASONS
|
||||
|
||||
|
||||
def find_fork_ci_definition_files(files: list[str]) -> list[str]:
|
||||
"""The files the fork CI reconciler counts as defining CI, so both decide alike."""
|
||||
return [file for file in files if changes_ci_definition([file], file_count=1)]
|
||||
|
||||
|
||||
def decide_gated_approval(*, changed_files: list[ChangedFile]) -> ApprovalDecision:
|
||||
"""
|
||||
Decide on the runs of a PR whose CI runs in the contributor's fork.
|
||||
|
||||
Its project CI run only executes the gate, so its cost and size do not matter. A change to the CI
|
||||
definition could remove the gate or add a workflow that does run, so it still needs a maintainer,
|
||||
and the author is told why.
|
||||
"""
|
||||
ci_files = find_fork_ci_definition_files([file.path for file in changed_files])
|
||||
if ci_files:
|
||||
return ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[f"its CI runs in the fork, but it changes CI definition files: {', '.join(ci_files)}"],
|
||||
comment=ci_change_approval_comment(ci_files=ci_files),
|
||||
)
|
||||
return ApprovalDecision(
|
||||
approve=True,
|
||||
reasons=["its CI runs in the contributor's fork, so its project CI run only executes the gate"],
|
||||
decision_labels=GATE_OVERRIDE_LABELS,
|
||||
)
|
||||
|
||||
|
||||
def decide_approval(
|
||||
*,
|
||||
base_branch: str,
|
||||
changed_files: list[ChangedFile],
|
||||
selective_checks: Any,
|
||||
) -> ApprovalDecision:
|
||||
"""Decide whether the workflow runs of a fork PR commit can be approved without a maintainer."""
|
||||
try:
|
||||
full_tests_needed = selective_checks.full_tests_needed
|
||||
all_versions = selective_checks.all_versions
|
||||
is_canary_run = selective_checks._is_canary_run()
|
||||
upgrade_to_newer_dependencies = selective_checks.upgrade_to_newer_dependencies
|
||||
estimate = estimate_ci_minutes(selective_checks)
|
||||
except (SystemExit, Exception):
|
||||
# Selective checks exit when a PR changes a suspended provider without the label allowing it,
|
||||
# and raise on malformed PR content such as an invalid pyproject.toml. Either way, fail closed.
|
||||
return ApprovalDecision(approve=False, reasons=["selective checks fail for this change"])
|
||||
if base_branch != AUTO_APPROVABLE_BASE_BRANCH:
|
||||
return ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[f"it targets {base_branch}, not {AUTO_APPROVABLE_BASE_BRANCH}"],
|
||||
estimate=estimate,
|
||||
)
|
||||
paths = [file.path for file in changed_files]
|
||||
ci_files = find_ci_definition_files(paths)
|
||||
if ci_files:
|
||||
return ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[f"it changes CI definition files: {', '.join(ci_files)}"],
|
||||
estimate=estimate,
|
||||
)
|
||||
dependency_files = find_dependency_files(paths)
|
||||
if dependency_files:
|
||||
return ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[f"it changes dependency files: {', '.join(dependency_files)}"],
|
||||
estimate=estimate,
|
||||
)
|
||||
new_provider_files = find_new_provider_files(paths)
|
||||
if new_provider_files:
|
||||
return ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[f"it adds a new provider: {', '.join(new_provider_files)}"],
|
||||
estimate=estimate,
|
||||
)
|
||||
if full_tests_needed:
|
||||
return ApprovalDecision(approve=False, reasons=["it needs the full set of tests"], estimate=estimate)
|
||||
if is_canary_run:
|
||||
# The canary label adds special tests and integration jobs that the estimate does not model.
|
||||
return ApprovalDecision(approve=False, reasons=["it runs as a canary build"], estimate=estimate)
|
||||
if all_versions:
|
||||
# The estimate models the default Python and database versions only.
|
||||
return ApprovalDecision(
|
||||
approve=False, reasons=["it runs all Python and database versions"], estimate=estimate
|
||||
)
|
||||
if upgrade_to_newer_dependencies:
|
||||
return ApprovalDecision(approve=False, reasons=["it changes dependencies"], estimate=estimate)
|
||||
if estimate.job_minutes > MAX_AUTO_APPROVED_JOB_MINUTES:
|
||||
return ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[
|
||||
f"its jobs take an estimated {estimate.job_minutes} job-minutes "
|
||||
f"(more than {MAX_AUTO_APPROVED_JOB_MINUTES})"
|
||||
],
|
||||
estimate=estimate,
|
||||
)
|
||||
source_lines = count_source_lines(changed_files)
|
||||
if source_lines > MAX_AUTO_APPROVED_SOURCE_LINES:
|
||||
return ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[
|
||||
f"it changes {source_lines} lines of source code "
|
||||
f"(more than {MAX_AUTO_APPROVED_SOURCE_LINES}, tests and docs not counted)"
|
||||
],
|
||||
estimate=estimate,
|
||||
)
|
||||
return ApprovalDecision(
|
||||
approve=True,
|
||||
reasons=[
|
||||
f"its jobs take an estimated {estimate.job_minutes} job-minutes "
|
||||
f"(at most {MAX_AUTO_APPROVED_JOB_MINUTES}) and it changes {source_lines} lines of source code"
|
||||
],
|
||||
estimate=estimate,
|
||||
)
|
||||
|
||||
|
||||
def parse_github_time(value: str) -> datetime:
|
||||
return datetime.fromisoformat(value.replace("Z", "+00:00"))
|
||||
|
||||
|
||||
class GitHubApi:
|
||||
def __init__(self, *, github_repository: str, github_token: str, report_only: bool):
|
||||
self.github_repository = github_repository
|
||||
self.report_only = report_only
|
||||
self._timelines: dict[int, list[dict[str, Any]]] = {}
|
||||
self._session = requests.Session()
|
||||
self._session.headers.update(
|
||||
{
|
||||
"Accept": "application/vnd.github+json",
|
||||
"Authorization": f"Bearer {github_token}",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
}
|
||||
)
|
||||
|
||||
def _get_paginated(self, path: str, *, item_key: str | None = None) -> list[dict[str, Any]]:
|
||||
items: list[dict[str, Any]] = []
|
||||
url: str | None = f"{GITHUB_API_URL}/repos/{self.github_repository}/{path}"
|
||||
while url:
|
||||
response = self._session.get(url, timeout=60)
|
||||
response.raise_for_status()
|
||||
payload = response.json()
|
||||
items.extend(payload[item_key] if item_key else payload)
|
||||
url = response.links.get("next", {}).get("url")
|
||||
return items
|
||||
|
||||
def get_runs_waiting_for_approval(self, created_since: datetime) -> list[dict[str, Any]]:
|
||||
created = created_since.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
return self._get_paginated(
|
||||
f"actions/runs?status=action_required&event=pull_request&per_page=100&created=%3E%3D{created}",
|
||||
item_key="workflow_runs",
|
||||
)
|
||||
|
||||
def get_open_pull_requests(self) -> list[dict[str, Any]]:
|
||||
return self._get_paginated("pulls?state=open&per_page=100")
|
||||
|
||||
def approve_run(self, run_id: int) -> None:
|
||||
if self.report_only:
|
||||
console_print(f"[info]Report only: would approve workflow run {run_id}[/]")
|
||||
return
|
||||
response = self._session.post(
|
||||
f"{GITHUB_API_URL}/repos/{self.github_repository}/actions/runs/{run_id}/approve", timeout=60
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
def add_label(self, pr_number: int, label: str) -> None:
|
||||
if self.report_only:
|
||||
console_print(f"[info]Report only: would add label '{label}' to PR #{pr_number}[/]")
|
||||
return
|
||||
response = self._session.post(
|
||||
f"{GITHUB_API_URL}/repos/{self.github_repository}/issues/{pr_number}/labels",
|
||||
json={"labels": [label]},
|
||||
timeout=60,
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
def has_bot_comment(self, pr_number: int, marker: str) -> bool:
|
||||
comments = self._get_paginated(f"issues/{pr_number}/comments?per_page=100")
|
||||
# Only the workflow's own comments count; anyone can post a comment containing the marker.
|
||||
return any(
|
||||
(comment.get("user") or {}).get("login") == "github-actions[bot]" and marker in comment["body"]
|
||||
for comment in comments
|
||||
)
|
||||
|
||||
def create_comment(self, pr_number: int, body: str) -> None:
|
||||
if self.report_only:
|
||||
console_print(f"[info]Report only: would comment on PR #{pr_number}[/]")
|
||||
return
|
||||
response = self._session.post(
|
||||
f"{GITHUB_API_URL}/repos/{self.github_repository}/issues/{pr_number}/comments",
|
||||
json={"body": body},
|
||||
timeout=60,
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
def _get_timeline(self, pr_number: int) -> list[dict[str, Any]]:
|
||||
if pr_number not in self._timelines:
|
||||
self._timelines[pr_number] = self._get_paginated(f"issues/{pr_number}/timeline?per_page=100")
|
||||
return self._timelines[pr_number]
|
||||
|
||||
def get_last_base_change(self, pr_number: int) -> datetime | None:
|
||||
changes = [
|
||||
parse_github_time(event["created_at"])
|
||||
for event in self._get_timeline(pr_number)
|
||||
if event.get("event") == "base_ref_changed"
|
||||
]
|
||||
return max(changes, default=None)
|
||||
|
||||
def get_last_label_change(self, pr_number: int, labels: frozenset[str]) -> datetime | None:
|
||||
"""When one of ``labels`` was last added to or removed from the PR."""
|
||||
changes = [
|
||||
parse_github_time(event["created_at"])
|
||||
for event in self._get_timeline(pr_number)
|
||||
if event.get("event") in ("labeled", "unlabeled")
|
||||
and (event.get("label") or {}).get("name") in labels
|
||||
]
|
||||
return max(changes, default=None)
|
||||
|
||||
def remove_label(self, pr_number: int, label: str) -> None:
|
||||
if self.report_only:
|
||||
console_print(f"[info]Report only: would remove label '{label}' from PR #{pr_number}[/]")
|
||||
return
|
||||
response = self._session.delete(
|
||||
f"{GITHUB_API_URL}/repos/{self.github_repository}/issues/{pr_number}/labels/{label}",
|
||||
timeout=60,
|
||||
)
|
||||
if response.status_code != 404:
|
||||
response.raise_for_status()
|
||||
|
||||
|
||||
def is_shallow_repository() -> bool:
|
||||
result = run_command(
|
||||
["git", "rev-parse", "--is-shallow-repository"],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
dry_run_override=False,
|
||||
)
|
||||
return result.stdout.strip() == "true"
|
||||
|
||||
|
||||
def fetch_merge_commit(*, github_repository: str, pr_number: int, head_sha: str) -> str | None:
|
||||
"""
|
||||
Fetch the PR's merge commit (what the CI run tests) and return its sha.
|
||||
|
||||
Return None when there is no merge commit or it was not built from ``head_sha``, so the result
|
||||
is always tied to the commit whose runs get approved.
|
||||
"""
|
||||
ref = f"refs/remotes/auto-approve/pull/{pr_number}/merge"
|
||||
# Only the merge commit and its parents are needed. Limit the depth only in an already shallow
|
||||
# checkout (CI): in a full clone, --depth would record shallow boundaries and truncate history.
|
||||
depth = ["--depth=2"] if is_shallow_repository() else []
|
||||
result = run_command(
|
||||
[
|
||||
"git",
|
||||
"fetch",
|
||||
"--no-tags",
|
||||
*depth,
|
||||
f"https://github.com/{github_repository}.git",
|
||||
f"+refs/pull/{pr_number}/merge:{ref}",
|
||||
],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
dry_run_override=False,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
return None
|
||||
parents = run_command(
|
||||
["git", "rev-list", "--parents", "-n", "1", ref],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
dry_run_override=False,
|
||||
)
|
||||
if parents.returncode != 0:
|
||||
return None
|
||||
merge_sha, *parent_shas = parents.stdout.split()
|
||||
if len(parent_shas) != 2 or parent_shas[1] != head_sha:
|
||||
return None
|
||||
return merge_sha
|
||||
|
||||
|
||||
NUMSTAT_RECORD = re.compile(r"(\d+|-)\t(\d+|-)\t(.+)", re.DOTALL)
|
||||
|
||||
|
||||
def get_changed_files(merge_sha: str) -> list[ChangedFile]:
|
||||
"""
|
||||
List the files the merge commit changes, with their changed line counts.
|
||||
|
||||
Paths must be literal for the CI-definition and source checks: without ``-z`` git C-quotes unusual
|
||||
file names, and rename detection reports ``old => new`` instead of both paths.
|
||||
"""
|
||||
result = run_command(
|
||||
[
|
||||
"git",
|
||||
"-c",
|
||||
"core.quotePath=false",
|
||||
"diff",
|
||||
"--no-renames",
|
||||
"--numstat",
|
||||
"-z",
|
||||
f"{merge_sha}^1",
|
||||
merge_sha,
|
||||
],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
dry_run_override=False,
|
||||
)
|
||||
changed_files = []
|
||||
for record in result.stdout.split("\0"):
|
||||
if not record:
|
||||
continue
|
||||
match = NUMSTAT_RECORD.fullmatch(record)
|
||||
if match is None:
|
||||
raise ValueError(f"Unexpected git numstat record: {record!r}")
|
||||
added, deleted, path = match.groups()
|
||||
# Binary files report "-" for both counts; count them over the limit so they never pass.
|
||||
changed_lines = int(added) + int(deleted) if added != "-" else MAX_AUTO_APPROVED_SOURCE_LINES + 1
|
||||
changed_files.append(ChangedFile(path=path, changed_lines=changed_lines))
|
||||
return changed_files
|
||||
|
||||
|
||||
def build_selective_checks(
|
||||
*, merge_sha: str, changed_files: list[ChangedFile], pr_labels: tuple[str, ...], base_branch: str
|
||||
):
|
||||
from airflow_breeze.utils.selective_checks import SelectiveChecks
|
||||
|
||||
# Release-branch PRs select different jobs (no provider tests, for example), so selective checks
|
||||
# must see the branch the PR targets.
|
||||
return SelectiveChecks(
|
||||
files=tuple(file.path for file in changed_files),
|
||||
default_branch=base_branch,
|
||||
commit_ref=merge_sha,
|
||||
pr_labels=pr_labels,
|
||||
github_event=GithubEvents.PULL_REQUEST,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class PullRequestResult:
|
||||
pr_number: int
|
||||
head_sha: str
|
||||
run_ids: list[int]
|
||||
decision: ApprovalDecision
|
||||
failed: bool = False
|
||||
|
||||
|
||||
def process_waiting_runs(api: GitHubApi, *, created_since: datetime) -> list[PullRequestResult]:
|
||||
"""
|
||||
Decide on the runs created since ``created_since``.
|
||||
|
||||
Older waiting runs are left alone, so the workflow never approves a backlog of stale runs at once.
|
||||
"""
|
||||
runs = api.get_runs_waiting_for_approval(created_since)
|
||||
if not runs:
|
||||
console_print(
|
||||
f"[info]No workflow runs created since {created_since:%Y-%m-%d %H:%M} UTC wait for approval.[/]"
|
||||
)
|
||||
return []
|
||||
runs_by_head: dict[tuple[str, str, str], list[dict[str, Any]]] = {}
|
||||
for run in runs:
|
||||
head_repository = (run.get("head_repository") or {}).get("full_name", "")
|
||||
if head_repository == api.github_repository:
|
||||
continue
|
||||
runs_by_head.setdefault((head_repository, run["head_branch"], run["head_sha"]), []).append(run)
|
||||
# The runs of fork PRs do not list their pull request, so match them by head repository, branch
|
||||
# and commit.
|
||||
pull_requests: dict[tuple[str, str, str], list[dict[str, Any]]] = {}
|
||||
for pr in api.get_open_pull_requests():
|
||||
head_repository = pr["head"]["repo"]["full_name"] if pr["head"].get("repo") else ""
|
||||
pull_requests.setdefault((head_repository, pr["head"]["ref"], pr["head"]["sha"]), []).append(pr)
|
||||
results = []
|
||||
for (head_repository, head_branch, head_sha), head_runs in runs_by_head.items():
|
||||
run_ids = [run["id"] for run in head_runs]
|
||||
matching_prs = pull_requests.get((head_repository, head_branch, head_sha), [])
|
||||
if not matching_prs:
|
||||
console_print(
|
||||
f"[warning]No open PR has head {escape(head_repository)}:{escape(head_branch)}@{head_sha}; "
|
||||
f"leaving runs {run_ids} alone[/]"
|
||||
)
|
||||
continue
|
||||
for pr in matching_prs:
|
||||
failed = False
|
||||
decision: ApprovalDecision | None = None
|
||||
try:
|
||||
if len(matching_prs) > 1:
|
||||
# The runs cannot be told apart by PR, so one PR's decision must not approve them all.
|
||||
decision = ApprovalDecision(
|
||||
approve=False, reasons=["its head commit is the head of several open PRs"]
|
||||
)
|
||||
else:
|
||||
decision = decide_for_pull_request(api=api, pr=pr)
|
||||
pr_run_ids = run_ids
|
||||
if decision.approve:
|
||||
pr_run_ids = find_runs_started_for_current_pr(
|
||||
api=api, pr=pr, runs=head_runs, decision_labels=decision.decision_labels
|
||||
)
|
||||
if not pr_run_ids:
|
||||
decision = ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[
|
||||
"its waiting runs started before the PR was opened, retargeted "
|
||||
"or changed a label its decision depends on"
|
||||
],
|
||||
estimate=decision.estimate,
|
||||
)
|
||||
pr_run_ids = run_ids
|
||||
apply_decision(api=api, pr=pr, run_ids=pr_run_ids, decision=decision)
|
||||
except (requests.RequestException, subprocess.CalledProcessError) as e:
|
||||
# One failing PR must not stop the others; the failure is reported through ``failed``.
|
||||
failed = True
|
||||
console_print(f"[warning]PR #{pr['number']}: processing failed: {escape(str(e))}[/]")
|
||||
pr_run_ids = run_ids
|
||||
# Without the label a PR that keeps failing drops out of the query window unnoticed.
|
||||
try:
|
||||
if not has_need_workflow_approval_label(pr):
|
||||
api.add_label(pr["number"], NEED_WORKFLOW_APPROVAL_LABEL)
|
||||
except requests.RequestException as label_error:
|
||||
console_print(
|
||||
f"[warning]PR #{pr['number']}: adding the label failed: {escape(str(label_error))}[/]"
|
||||
)
|
||||
decision = ApprovalDecision(
|
||||
approve=False,
|
||||
reasons=[build_failure_reason(e)],
|
||||
estimate=decision.estimate if decision else None,
|
||||
)
|
||||
results.append(
|
||||
PullRequestResult(
|
||||
pr_number=pr["number"],
|
||||
head_sha=head_sha,
|
||||
run_ids=pr_run_ids,
|
||||
decision=decision,
|
||||
failed=failed,
|
||||
)
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def find_runs_started_for_current_pr(
|
||||
*,
|
||||
api: GitHubApi,
|
||||
pr: dict[str, Any],
|
||||
runs: list[dict[str, Any]],
|
||||
decision_labels: frozenset[str] = TEST_SELECTION_LABELS,
|
||||
) -> list[int]:
|
||||
"""
|
||||
Return the runs started after the PR was opened and after its base branch last changed.
|
||||
|
||||
Retargeting a PR does not start new runs, and a closed PR can leave runs with the same head behind.
|
||||
Such runs were started for another base branch, so the decision about the current PR must not
|
||||
approve them.
|
||||
|
||||
:param decision_labels: the labels the decision depends on. It is made from the current labels,
|
||||
while a run can act on those of its event: with ``full tests needed`` removed, or
|
||||
``default versions only`` added to a run of all versions, the estimate is smaller than the
|
||||
run, and without ``use fork ci`` in its event a run can fall back to project CI.
|
||||
"""
|
||||
started_after = parse_github_time(pr["created_at"])
|
||||
changes = [
|
||||
api.get_last_base_change(pr["number"]),
|
||||
api.get_last_label_change(pr["number"], decision_labels),
|
||||
]
|
||||
started_after = max([started_after, *(change for change in changes if change is not None)])
|
||||
return [run["id"] for run in runs if parse_github_time(run["created_at"]) >= started_after]
|
||||
|
||||
|
||||
def decide_for_pull_request(*, api: GitHubApi, pr: dict[str, Any]) -> ApprovalDecision:
|
||||
merge_sha = fetch_merge_commit(
|
||||
github_repository=api.github_repository, pr_number=pr["number"], head_sha=pr["head"]["sha"]
|
||||
)
|
||||
if merge_sha is None:
|
||||
return ApprovalDecision(
|
||||
approve=False, reasons=["its merge commit is missing or was not built from the PR's head commit"]
|
||||
)
|
||||
try:
|
||||
changed_files = get_changed_files(merge_sha)
|
||||
except ValueError:
|
||||
return ApprovalDecision(approve=False, reasons=["its changed files could not be listed"])
|
||||
if pr["base"]["ref"] == AUTO_APPROVABLE_BASE_BRANCH and is_gated_to_fork_ci(
|
||||
pr=pr, github_repository=api.github_repository, config=load_config(FORK_CI_GATE_CONFIG_PATH)
|
||||
):
|
||||
return decide_gated_approval(changed_files=changed_files)
|
||||
pr_labels = tuple(label["name"] for label in pr.get("labels", []))
|
||||
return decide_approval(
|
||||
base_branch=pr["base"]["ref"],
|
||||
changed_files=changed_files,
|
||||
selective_checks=build_selective_checks(
|
||||
merge_sha=merge_sha,
|
||||
changed_files=changed_files,
|
||||
pr_labels=pr_labels,
|
||||
base_branch=pr["base"]["ref"],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def build_failure_reason(error: Exception) -> str:
|
||||
text = " ".join(str(error).split())
|
||||
if len(text) > MAX_ERROR_TEXT_LENGTH:
|
||||
# The end of a failed git command holds its exit status, so keep both ends.
|
||||
half = (MAX_ERROR_TEXT_LENGTH - len("...")) // 2
|
||||
text = f"{text[:half]}...{text[-half:]}"
|
||||
reason = f"processing failed with {type(error).__name__}"
|
||||
return f"{reason}: {text}" if text else reason
|
||||
|
||||
|
||||
def has_need_workflow_approval_label(pr: dict[str, Any]) -> bool:
|
||||
return any(label["name"] == NEED_WORKFLOW_APPROVAL_LABEL for label in pr.get("labels", []))
|
||||
|
||||
|
||||
def apply_decision(
|
||||
*, api: GitHubApi, pr: dict[str, Any], run_ids: list[int], decision: ApprovalDecision
|
||||
) -> None:
|
||||
pr_number = pr["number"]
|
||||
has_label = has_need_workflow_approval_label(pr)
|
||||
console_print(f"[info]PR #{pr_number}: {format_estimate(decision.estimate)}[/]")
|
||||
if decision.approve:
|
||||
console_print(
|
||||
f"[success]Approving runs {run_ids} of PR #{pr_number}: {escape('; '.join(decision.reasons))}[/]"
|
||||
)
|
||||
for run_id in run_ids:
|
||||
api.approve_run(run_id)
|
||||
if has_label:
|
||||
api.remove_label(pr_number, NEED_WORKFLOW_APPROVAL_LABEL)
|
||||
return
|
||||
# Reasons can contain contributor-chosen file names, which must not be read as Rich markup.
|
||||
console_print(f"[warning]PR #{pr_number} needs a maintainer: {escape('; '.join(decision.reasons))}[/]")
|
||||
if not has_label:
|
||||
api.add_label(pr_number, NEED_WORKFLOW_APPROVAL_LABEL)
|
||||
# Once per PR: every later push would otherwise repeat it while the change stays.
|
||||
if decision.comment is not None and not api.has_bot_comment(pr_number, CI_CHANGE_MARKER):
|
||||
api.create_comment(pr_number, decision.comment)
|
||||
|
||||
|
||||
MARKDOWN_SPECIAL_CHARACTERS = re.compile(r"([\\`*_{}\[\]()<>#+!|~])")
|
||||
|
||||
|
||||
def escape_markdown(text: str) -> str:
|
||||
"""Escape Markdown in contributor-controlled text, such as file names, for the job summary."""
|
||||
return MARKDOWN_SPECIAL_CHARACTERS.sub(r"\\\1", text)
|
||||
|
||||
|
||||
def format_estimate(estimate: CiMinutesEstimate | None) -> str:
|
||||
if estimate is None:
|
||||
return "n/a"
|
||||
return f"~{estimate.job_minutes} job-min, ~{estimate.wall_clock_minutes} min wall clock"
|
||||
|
||||
|
||||
def write_step_summary(results: list[PullRequestResult], github_repository: str) -> None:
|
||||
summary_path = os.environ.get("GITHUB_STEP_SUMMARY")
|
||||
if not summary_path:
|
||||
return
|
||||
lines = [
|
||||
"## Workflow run approval",
|
||||
"",
|
||||
"Estimates are for `Tests (AMD)` on public runners.",
|
||||
"",
|
||||
"| PR | Head | Decision | Estimated CI time | Reasons |",
|
||||
"|---|---|---|---|---|",
|
||||
]
|
||||
for result in results:
|
||||
if result.failed:
|
||||
decision = "failed"
|
||||
elif result.decision.approve:
|
||||
decision = "approved"
|
||||
else:
|
||||
decision = f"`{NEED_WORKFLOW_APPROVAL_LABEL}`"
|
||||
lines.append(
|
||||
f"| [#{result.pr_number}](https://github.com/{github_repository}/pull/{result.pr_number}) "
|
||||
f"| `{result.head_sha[:10]}` | {decision} | {format_estimate(result.decision.estimate)} "
|
||||
f"| {escape_markdown('; '.join(result.decision.reasons))} |"
|
||||
)
|
||||
for result in results:
|
||||
estimate = result.decision.estimate
|
||||
if estimate is None:
|
||||
continue
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
f"### #{result.pr_number}: expected jobs",
|
||||
"",
|
||||
"| Job group | Estimated job-minutes | Critical path (min) |",
|
||||
"|---|---|---|",
|
||||
*(
|
||||
f"| {group.name} | {group.job_minutes} | {group.critical_path_minutes} |"
|
||||
for group in estimate.job_groups
|
||||
),
|
||||
f"| **Total** | **{estimate.job_minutes}** | **~{estimate.wall_clock_minutes} wall clock** |",
|
||||
]
|
||||
)
|
||||
with open(summary_path, "a") as summary_file:
|
||||
summary_file.write("\n".join(lines) + "\n")
|
||||
@@ -0,0 +1,101 @@
|
||||
# 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.
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from airflow_breeze.utils.path_utils import AIRFLOW_ROOT_PATH
|
||||
|
||||
# The script is standalone (run with `uv run`), so it is loaded from its path.
|
||||
SCRIPT_PATH = AIRFLOW_ROOT_PATH / "dev" / "calibrate_ci_minutes_estimates.py"
|
||||
_spec = importlib.util.spec_from_file_location("calibrate_ci_minutes_estimates", SCRIPT_PATH)
|
||||
assert _spec is not None
|
||||
assert _spec.loader is not None
|
||||
calibrate = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(calibrate)
|
||||
|
||||
JOBS = [
|
||||
{
|
||||
"name": "Basic tests / Static checks",
|
||||
"conclusion": "success",
|
||||
"started_at": "2026-10-22T10:00:00Z",
|
||||
"completed_at": "2026-10-22T10:06:00Z",
|
||||
},
|
||||
{
|
||||
"name": "MyPy providers checks",
|
||||
"conclusion": "success",
|
||||
"started_at": "2026-10-22T10:00:00Z",
|
||||
"completed_at": "2026-10-22T10:08:00Z",
|
||||
},
|
||||
{
|
||||
"name": "TypeScript SDK docs",
|
||||
"conclusion": "success",
|
||||
"started_at": "2026-10-22T10:00:00Z",
|
||||
"completed_at": "2026-10-22T10:01:00Z",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def _cache_run(cache_dir, run_id, *, runner_type='["ubuntu-22.04"]', all_versions="false"):
|
||||
(cache_dir / f"{run_id}.jobs.json").write_text(json.dumps(JOBS))
|
||||
(cache_dir / f"{run_id}.build-info.log").write_text(
|
||||
"2026-10-22T10:00:00Z full-tests-needed = false\n"
|
||||
f"2026-10-22T10:00:00Z runner-type = {runner_type}\n"
|
||||
f"2026-10-22T10:00:00Z all-versions = {all_versions}\n"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("runner_type", "all_versions", "counted"),
|
||||
[
|
||||
pytest.param('["ubuntu-22.04"]', "false", True, id="public runners, default versions"),
|
||||
pytest.param(
|
||||
"runs-on=1/family=m7a/image=ubuntu22-full-x64/volume=150gb/cpu={0}/ram={1}",
|
||||
"false",
|
||||
False,
|
||||
id="self-hosted runners",
|
||||
),
|
||||
pytest.param('["ubuntu-22.04"]', "true", False, id="all versions"),
|
||||
],
|
||||
)
|
||||
def test_build_rows_counts_only_the_runs_the_estimate_models(tmp_path, runner_type, all_versions, counted):
|
||||
_cache_run(tmp_path, 1, runner_type=runner_type, all_versions=all_versions)
|
||||
|
||||
rows = calibrate.build_rows([1], tmp_path)
|
||||
|
||||
assert len(rows) == int(counted)
|
||||
|
||||
|
||||
def test_build_rows_groups_ts_sdk_docs_separately(tmp_path):
|
||||
_cache_run(tmp_path, 1)
|
||||
|
||||
(row,) = calibrate.build_rows([1], tmp_path)
|
||||
|
||||
assert row["minutes"]["ts-sdk-docs"] == 1
|
||||
assert "ts-sdk" not in row["minutes"]
|
||||
|
||||
|
||||
def test_build_rows_groups_provider_mypy_separately(tmp_path):
|
||||
_cache_run(tmp_path, 1)
|
||||
|
||||
(row,) = calibrate.build_rows([1], tmp_path)
|
||||
|
||||
assert row["minutes"]["mypy-providers"] == 8
|
||||
assert "providers" not in row["minutes"]
|
||||
@@ -0,0 +1,229 @@
|
||||
# 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.
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from airflow_breeze.utils.ci_minutes_estimate import (
|
||||
BASE_ESTIMATE,
|
||||
BASIC_CHECKS_ONLY_ESTIMATE,
|
||||
CORE_ALL_TEST_TYPES_MINUTES,
|
||||
MYPY_PROVIDERS_ESTIMATE,
|
||||
PROVIDERS_ALL_LONGEST_JOB_MINUTES,
|
||||
PROVIDERS_ALL_MINUTES,
|
||||
RUN_OVERHEAD_MINUTES,
|
||||
TS_SDK_DOCS_ESTIMATE,
|
||||
estimate_ci_minutes,
|
||||
estimate_core_job_minutes,
|
||||
estimate_providers_group,
|
||||
find_tested_provider_ids,
|
||||
)
|
||||
from airflow_breeze.utils.selective_checks import SelectiveChecks
|
||||
|
||||
OPTIONAL_FLAGS = (
|
||||
"docs_build",
|
||||
"run_unit_tests",
|
||||
"full_tests_needed",
|
||||
"prod_image_build",
|
||||
"run_kubernetes_tests",
|
||||
"run_helm_tests",
|
||||
"run_kustomize_overlays_tests",
|
||||
"run_task_sdk_tests",
|
||||
"run_agent_framework_tests",
|
||||
"run_java_sdk_tests",
|
||||
"run_go_sdk_tests",
|
||||
"run_ts_sdk_tests",
|
||||
"run_ts_sdk_docs",
|
||||
"run_airflow_ctl_tests",
|
||||
"run_mypy_providers",
|
||||
)
|
||||
|
||||
|
||||
def _selective_checks(
|
||||
*, core_test_types=(), provider_test_types=(), basic_checks_only=False, **flags
|
||||
) -> mock.MagicMock:
|
||||
selective_checks = mock.MagicMock(spec=SelectiveChecks)
|
||||
selective_checks.basic_checks_only = basic_checks_only
|
||||
selective_checks.skip_providers_tests = not provider_test_types
|
||||
for flag in OPTIONAL_FLAGS:
|
||||
setattr(selective_checks, flag, flags.get(flag, False))
|
||||
selective_checks._get_core_test_types_to_run.return_value = list(core_test_types)
|
||||
selective_checks._get_providers_test_types_to_run.return_value = list(provider_test_types)
|
||||
return selective_checks
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("core_test_types", "expected"),
|
||||
[(0, 0), (1, 38), (2, 99), (3, 160), (6, CORE_ALL_TEST_TYPES_MINUTES)],
|
||||
)
|
||||
def test_estimate_core_job_minutes(core_test_types, expected):
|
||||
assert estimate_core_job_minutes(core_test_types) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("provider_test_types", "expected"),
|
||||
[
|
||||
(["Providers[amazon]", "Providers[google]"], ["amazon", "google"]),
|
||||
(["Providers[common.compat,fab]"], ["common.compat", "fab"]),
|
||||
(["Providers[-amazon,google]", "Providers[amazon]"], None),
|
||||
(["Providers"], None),
|
||||
],
|
||||
)
|
||||
def test_find_tested_provider_ids(provider_test_types, expected):
|
||||
assert find_tested_provider_ids(provider_test_types) == expected
|
||||
|
||||
|
||||
@mock.patch("airflow_breeze.utils.ci_minutes_estimate.count_provider_test_files", autospec=True)
|
||||
def test_estimate_providers_group_weights_providers_by_test_files(mock_count):
|
||||
mock_count.side_effect = lambda provider_id: {"fab": 50, "amazon": 500}[provider_id]
|
||||
|
||||
small = estimate_providers_group(["Providers[fab]"])
|
||||
large = estimate_providers_group(["Providers[amazon]"])
|
||||
|
||||
assert small.name == "Provider tests (1 providers, 50 test files)"
|
||||
assert small.job_minutes < large.job_minutes
|
||||
assert small.critical_path_minutes < large.critical_path_minutes
|
||||
|
||||
|
||||
def test_estimate_providers_group_for_all_providers():
|
||||
group = estimate_providers_group(["Providers"])
|
||||
|
||||
assert (group.job_minutes, group.critical_path_minutes) == (
|
||||
PROVIDERS_ALL_MINUTES,
|
||||
PROVIDERS_ALL_LONGEST_JOB_MINUTES,
|
||||
)
|
||||
|
||||
|
||||
def test_estimate_providers_group_without_providers():
|
||||
assert estimate_providers_group([]) is None
|
||||
|
||||
|
||||
def test_estimate_basic_checks_only():
|
||||
estimate = estimate_ci_minutes(_selective_checks(basic_checks_only=True))
|
||||
|
||||
assert [group.name for group in estimate.job_groups] == ["Basic checks only"]
|
||||
assert estimate.job_minutes == BASIC_CHECKS_ONLY_ESTIMATE[0]
|
||||
assert estimate.wall_clock_minutes == BASIC_CHECKS_ONLY_ESTIMATE[1]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("flags", "expected_groups"),
|
||||
[
|
||||
pytest.param(
|
||||
{"run_ts_sdk_docs": True}, ["Basic checks only", "TypeScript SDK docs"], id="ts-sdk docs"
|
||||
),
|
||||
pytest.param(
|
||||
{"run_java_sdk_tests": True, "run_go_sdk_tests": True, "run_airflow_ctl_tests": True},
|
||||
["Basic checks only", "Java SDK tests", "Go SDK tests", "Airflow CTL tests"],
|
||||
id="sdk tests",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_estimate_basic_checks_only_counts_jobs_that_need_no_ci_image(flags, expected_groups):
|
||||
estimate = estimate_ci_minutes(_selective_checks(basic_checks_only=True, **flags))
|
||||
|
||||
assert [group.name for group in estimate.job_groups] == expected_groups
|
||||
|
||||
|
||||
def test_estimate_counts_ts_sdk_docs_with_the_ci_image():
|
||||
estimate = estimate_ci_minutes(_selective_checks(run_ts_sdk_docs=True))
|
||||
|
||||
assert estimate.job_groups[-1].name == "TypeScript SDK docs"
|
||||
assert estimate.job_minutes == BASE_ESTIMATE[0] + TS_SDK_DOCS_ESTIMATE[0]
|
||||
|
||||
|
||||
@mock.patch("airflow_breeze.utils.ci_minutes_estimate.count_provider_test_files", return_value=100)
|
||||
def test_estimate_lists_the_job_groups_that_run(mock_count):
|
||||
estimate = estimate_ci_minutes(
|
||||
_selective_checks(
|
||||
core_test_types=["Always"],
|
||||
provider_test_types=["Providers[http]"],
|
||||
docs_build=True,
|
||||
run_unit_tests=True,
|
||||
prod_image_build=True,
|
||||
run_helm_tests=True,
|
||||
)
|
||||
)
|
||||
|
||||
assert [group.name for group in estimate.job_groups] == [
|
||||
"CI image, basic tests and static checks",
|
||||
"Documentation build",
|
||||
"Core tests (1 test types)",
|
||||
"Integration and system tests",
|
||||
"Provider tests (1 providers, 100 test files)",
|
||||
"PROD image build and tests",
|
||||
"Helm tests",
|
||||
]
|
||||
assert estimate.job_minutes == sum(group.job_minutes for group in estimate.job_groups)
|
||||
assert estimate.wall_clock_minutes == RUN_OVERHEAD_MINUTES + max(
|
||||
group.critical_path_minutes for group in estimate.job_groups
|
||||
)
|
||||
|
||||
|
||||
def test_estimate_full_tests_adds_special_tests_and_all_core_types():
|
||||
estimate = estimate_ci_minutes(
|
||||
_selective_checks(
|
||||
core_test_types=["API", "Always", "CLI", "Core", "Other", "Serialization"],
|
||||
provider_test_types=["Providers"],
|
||||
run_unit_tests=True,
|
||||
full_tests_needed=True,
|
||||
)
|
||||
)
|
||||
|
||||
names = [group.name for group in estimate.job_groups]
|
||||
assert "Core tests (all test types)" in names
|
||||
assert "Provider tests (all providers)" in names
|
||||
assert "Special tests" in names
|
||||
|
||||
|
||||
def test_estimate_without_unit_tests_has_only_base_group():
|
||||
estimate = estimate_ci_minutes(_selective_checks())
|
||||
|
||||
assert estimate.job_minutes == BASE_ESTIMATE[0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("run_unit_tests", "expected_groups"),
|
||||
[
|
||||
pytest.param(
|
||||
False, ["CI image, basic tests and static checks", "Provider mypy checks"], id="metadata only"
|
||||
),
|
||||
pytest.param(
|
||||
True,
|
||||
[
|
||||
"CI image, basic tests and static checks",
|
||||
"Integration and system tests",
|
||||
"Provider tests (1 providers, 100 test files)",
|
||||
"Provider mypy checks",
|
||||
],
|
||||
id="with unit tests",
|
||||
),
|
||||
],
|
||||
)
|
||||
@mock.patch("airflow_breeze.utils.ci_minutes_estimate.count_provider_test_files", return_value=100)
|
||||
def test_estimate_charges_provider_tests_only_with_unit_tests(mock_count, run_unit_tests, expected_groups):
|
||||
estimate = estimate_ci_minutes(
|
||||
_selective_checks(
|
||||
provider_test_types=["Providers[google]"], run_unit_tests=run_unit_tests, run_mypy_providers=True
|
||||
)
|
||||
)
|
||||
|
||||
assert [group.name for group in estimate.job_groups] == expected_groups
|
||||
if not run_unit_tests:
|
||||
assert estimate.job_minutes == BASE_ESTIMATE[0] + MYPY_PROVIDERS_ESTIMATE[0]
|
||||
@@ -25,12 +25,15 @@ from airflow_breeze.utils.fork_ci_messages import (
|
||||
_STATE_TEXTS,
|
||||
_STATUS_DESCRIPTIONS,
|
||||
BEHIND_WARNING_COMMITS,
|
||||
CI_CHANGE_MARKER,
|
||||
CI_PASSED_DESCRIPTION,
|
||||
CI_PASSED_REVOKED_DESCRIPTION,
|
||||
FOOTER,
|
||||
JOB_NAME_MAX_LENGTH,
|
||||
JOB_STATUS_CONTEXT_PREFIX,
|
||||
MAX_LISTED_CI_FILES,
|
||||
Marker,
|
||||
ci_change_approval_comment,
|
||||
inactivity_close_comment,
|
||||
job_status_context,
|
||||
nudge_comment,
|
||||
@@ -143,3 +146,18 @@ def test_status_descriptions_fit_github_limit():
|
||||
)
|
||||
def test_job_status_context(name, expected):
|
||||
assert job_status_context(name) == f"{JOB_STATUS_CONTEXT_PREFIX}{expected}"
|
||||
|
||||
|
||||
def test_ci_change_approval_comment_lists_the_files():
|
||||
paths = [f".github/workflows/w{i}.yml" for i in range(MAX_LISTED_CI_FILES + 2)]
|
||||
comment = ci_change_approval_comment(
|
||||
ci_files=["dev/breeze/`evil`.py", ".github/a\n\n@someone.yml", *paths]
|
||||
)
|
||||
|
||||
assert comment.startswith(CI_CHANGE_MARKER)
|
||||
assert comment.endswith(FOOTER)
|
||||
assert "- `dev/breeze/?evil?.py`" in comment
|
||||
assert "- `.github/a??@someone.yml`" in comment
|
||||
assert "\n@someone" not in comment
|
||||
assert "- and 4 more" in comment
|
||||
assert f"`{paths[-1]}`" not in comment
|
||||
@@ -0,0 +1,270 @@
|
||||
#!/usr/bin/env python3
|
||||
# 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.
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# ///
|
||||
"""
|
||||
Measure the numbers behind ``dev/breeze/src/airflow_breeze/utils/ci_minutes_estimate.py``.
|
||||
|
||||
Downloads recent successful ``Tests (AMD)`` PR runs, their job timings and the selective-check outputs
|
||||
their ``Build info`` job printed, then prints the medians and fits to copy into the estimate module.
|
||||
Only runs on public runners with the default versions are counted, as the estimate models them.
|
||||
Downloads are cached in ``--cache-dir``, so re-runs only fetch new runs.
|
||||
|
||||
Needs an authenticated ``gh`` CLI. Run from the repository root:
|
||||
|
||||
uv run dev/calibrate_ci_minutes_estimates.py --since 2026-09-10
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import statistics
|
||||
import subprocess
|
||||
from collections import defaultdict
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
REPOSITORY = "apache/airflow"
|
||||
WORKFLOW = "ci-amd.yml"
|
||||
ANSI_ESCAPE = re.compile(r"\x1b\[[0-9;]*m")
|
||||
# What ci_minutes_estimate.py models: jobs on GitHub's public AMD runners, default versions only.
|
||||
# Self-hosted (RunsOn) runs and all-versions runs take different times and would skew the medians.
|
||||
PUBLIC_AMD_RUNNERS = '["ubuntu-22.04"]'
|
||||
|
||||
# Job-name patterns for each job group of ci_minutes_estimate.py; the first match wins.
|
||||
JOB_GROUPS = [
|
||||
("docs", r"^CI image checks / (Build documentation|Publish documentation)"),
|
||||
("core", r"^(MySQL|Postgres|Sqlite|Non-DB) tests: core|^Low dep tests:core"),
|
||||
("special", r"^Special tests"),
|
||||
("mypy-providers", r"^MyPy providers checks"),
|
||||
("providers", r"^Provider distributions tests|tests: providers|^Low dep tests: providers"),
|
||||
("prod", r"^Build PROD images|^Additional PROD image tests"),
|
||||
("kubernetes", r"^Kubernetes tests"),
|
||||
("helm", r"^Helm tests"),
|
||||
("kustomize", r"^Kustomize"),
|
||||
("integration", r"^Integration and System Tests"),
|
||||
("task-sdk", r"^Task SDK tests"),
|
||||
("agent-framework", r"^Agent framework tests"),
|
||||
("java-sdk", r"^Java SDK"),
|
||||
("go-sdk", r"^Go SDK"),
|
||||
("ts-sdk-docs", r"^TypeScript SDK docs"),
|
||||
("ts-sdk", r"^TypeScript SDK"),
|
||||
("airflow-ctl", r"^Airflow CTL"),
|
||||
("base", r".*"),
|
||||
]
|
||||
|
||||
|
||||
def gh_api(path: str, *extra: str) -> str:
|
||||
for _ in range(3):
|
||||
result = subprocess.run(["gh", "api", *extra, path], capture_output=True, text=True, check=False)
|
||||
if result.returncode == 0:
|
||||
return result.stdout
|
||||
raise RuntimeError(f"gh api {path} failed: {result.stderr.strip()}")
|
||||
|
||||
|
||||
def list_runs(since: str) -> list[int]:
|
||||
run_ids: list[int] = []
|
||||
for page in range(1, 11):
|
||||
payload = json.loads(
|
||||
gh_api(
|
||||
f"repos/{REPOSITORY}/actions/workflows/{WORKFLOW}/runs?event=pull_request"
|
||||
f"&status=success&per_page=100&page={page}&created=>={since}"
|
||||
)
|
||||
)
|
||||
run_ids.extend(run["id"] for run in payload["workflow_runs"])
|
||||
if len(payload["workflow_runs"]) < 100:
|
||||
break
|
||||
return run_ids
|
||||
|
||||
|
||||
def fetch_run(run_id: int, cache_dir: Path) -> None:
|
||||
jobs_file = cache_dir / f"{run_id}.jobs.json"
|
||||
log_file = cache_dir / f"{run_id}.build-info.log"
|
||||
try:
|
||||
if not jobs_file.exists():
|
||||
jobs = json.loads(
|
||||
gh_api(f"repos/{REPOSITORY}/actions/runs/{run_id}/jobs?per_page=100", "--paginate", "--slurp")
|
||||
)
|
||||
jobs_file.write_text(json.dumps([job for page in jobs for job in page["jobs"]]))
|
||||
if not log_file.exists():
|
||||
build_info = next(job for job in json.loads(jobs_file.read_text()) if job["name"] == "Build info")
|
||||
log_file.write_text(
|
||||
gh_api(f"repos/{REPOSITORY}/actions/jobs/{build_info['id']}/logs", "--allow-escape-sequences")
|
||||
)
|
||||
except (RuntimeError, StopIteration) as error:
|
||||
print(f"skipping run {run_id}: {error}")
|
||||
|
||||
|
||||
def is_incomplete_json(value: str) -> bool:
|
||||
if not value.startswith(("[", "{")):
|
||||
return False
|
||||
try:
|
||||
json.loads(value)
|
||||
except json.JSONDecodeError:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def read_outputs(log_file: Path) -> dict[str, str]:
|
||||
# Rich wraps long JSON values over several log lines; glue continuation lines onto the value only
|
||||
# until it parses, so diagnostics printed after it are not appended.
|
||||
outputs: dict[str, str] = {}
|
||||
key = None
|
||||
for line in log_file.read_text(errors="replace").splitlines():
|
||||
text = ANSI_ESCAPE.sub("", line).split(" ", 1)[-1]
|
||||
match = re.match(r"^([a-z0-9-]+) = (.*)$", text)
|
||||
if match:
|
||||
key = match.group(1)
|
||||
outputs[key] = match.group(2)
|
||||
elif key and text and is_incomplete_json(outputs[key]):
|
||||
outputs[key] += text
|
||||
else:
|
||||
key = None
|
||||
return outputs
|
||||
|
||||
|
||||
def get_test_types(outputs: dict[str, str], name: str) -> list[str]:
|
||||
value = outputs.get(name)
|
||||
if not value or value in ("null", "[]"):
|
||||
return []
|
||||
return sorted({test_type for group in json.loads(value) for test_type in group["test_types"].split()})
|
||||
|
||||
|
||||
def count_provider_test_files(provider_id: str) -> int:
|
||||
tests_path = Path("providers", *provider_id.split("."), "tests")
|
||||
return sum(1 for _ in tests_path.rglob("test_*.py"))
|
||||
|
||||
|
||||
def get_unmodelled_reason(outputs: dict[str, str]) -> str | None:
|
||||
"""Why a run cannot calibrate the estimate, or None when it matches what the estimate models."""
|
||||
if outputs.get("runner-type") != PUBLIC_AMD_RUNNERS:
|
||||
return f"it ran on {outputs.get('runner-type', 'unknown runners')}"
|
||||
if outputs.get("all-versions") != "false":
|
||||
return "it ran all Python and database versions"
|
||||
return None
|
||||
|
||||
|
||||
def build_rows(run_ids: list[int], cache_dir: Path) -> list[dict]:
|
||||
rows = []
|
||||
for run_id in run_ids:
|
||||
jobs_file = cache_dir / f"{run_id}.jobs.json"
|
||||
log_file = cache_dir / f"{run_id}.build-info.log"
|
||||
if not jobs_file.exists() or not log_file.exists():
|
||||
continue
|
||||
outputs = read_outputs(log_file)
|
||||
if "full-tests-needed" not in outputs:
|
||||
continue
|
||||
reason = get_unmodelled_reason(outputs)
|
||||
if reason is not None:
|
||||
print(f"skipping run {run_id}: {reason}")
|
||||
continue
|
||||
minutes: dict[str, float] = defaultdict(float)
|
||||
longest: dict[str, float] = defaultdict(float)
|
||||
for job in json.loads(jobs_file.read_text()):
|
||||
if job["conclusion"] == "skipped" or not job["started_at"] or not job["completed_at"]:
|
||||
continue
|
||||
duration = (
|
||||
datetime.fromisoformat(job["completed_at"]) - datetime.fromisoformat(job["started_at"])
|
||||
).total_seconds() / 60
|
||||
group = next(group for group, pattern in JOB_GROUPS if re.search(pattern, job["name"]))
|
||||
minutes[group] += duration
|
||||
longest[group] = max(longest[group], duration)
|
||||
try:
|
||||
providers = get_test_types(outputs, "individual-providers-test-types-list-as-strings-in-json")
|
||||
core_types = len(get_test_types(outputs, "core-test-types-list-as-strings-in-json"))
|
||||
except json.JSONDecodeError:
|
||||
print(f"skipping run {run_id}: its selective-check outputs could not be parsed")
|
||||
continue
|
||||
rows.append(
|
||||
{
|
||||
"outputs": outputs,
|
||||
"minutes": minutes,
|
||||
"longest": longest,
|
||||
"core_types": core_types,
|
||||
"providers": [p[len("Providers[") : -1] for p in providers if p.startswith("Providers[")],
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def print_report(rows: list[dict]) -> None:
|
||||
print(f"\nruns analysed: {len(rows)}")
|
||||
print("\njob group runs median job-minutes median longest job")
|
||||
for group, _ in JOB_GROUPS:
|
||||
present = [row for row in rows if row["minutes"].get(group)]
|
||||
if present:
|
||||
print(
|
||||
f"{group:18s}{len(present):5d} {statistics.median(r['minutes'][group] for r in present):18.1f}"
|
||||
f" {statistics.median(r['longest'][group] for r in present):18.1f}"
|
||||
)
|
||||
print("\ncore test types runs median job-minutes median longest job")
|
||||
core = [row for row in rows if row["core_types"] and row["minutes"].get("core")]
|
||||
for count in sorted({row["core_types"] for row in core}):
|
||||
selected = [row for row in core if row["core_types"] == count]
|
||||
print(
|
||||
f"{count:15d}{len(selected):7d} {statistics.median(r['minutes']['core'] for r in selected):18.1f}"
|
||||
f" {statistics.median(r['longest']['core'] for r in selected):18.1f}"
|
||||
)
|
||||
tested = [row for row in rows if row["providers"] and row["minutes"].get("providers")]
|
||||
partial = [row for row in tested if len(row["providers"]) < 50]
|
||||
full = [row for row in tested if len(row["providers"]) >= 50]
|
||||
if full:
|
||||
print(
|
||||
f"\nall providers: {len(full)} runs, median job-minutes "
|
||||
f"{statistics.median(r['minutes']['providers'] for r in full):.1f}, median longest job "
|
||||
f"{statistics.median(r['longest']['providers'] for r in full):.1f}"
|
||||
)
|
||||
test_files = [sum(count_provider_test_files(p) for p in row["providers"]) for row in partial]
|
||||
if len(set(test_files)) < 2:
|
||||
print("partial provider runs: not enough different provider test-suite sizes to fit")
|
||||
else:
|
||||
slope, intercept = statistics.linear_regression(
|
||||
test_files, [r["minutes"]["providers"] for r in partial]
|
||||
)
|
||||
longest_slope, longest_intercept = statistics.linear_regression(
|
||||
test_files, [r["longest"]["providers"] for r in partial]
|
||||
)
|
||||
print(
|
||||
f"partial provider runs: {len(partial)} runs, "
|
||||
f"{len({tuple(row['providers']) for row in partial})} distinct provider sets"
|
||||
)
|
||||
print(f" job-minutes ~= {intercept:.1f} + {slope:.3f} * provider test files")
|
||||
print(f" longest job ~= {longest_intercept:.1f} + {longest_slope:.3f} * provider test files")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument("--since", required=True, help="Earliest run creation date (YYYY-MM-DD).")
|
||||
parser.add_argument("--cache-dir", type=Path, default=Path("files/ci-minutes-cache"))
|
||||
args = parser.parse_args()
|
||||
args.cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
run_ids = list_runs(args.since)
|
||||
print(f"runs listed: {len(run_ids)}")
|
||||
with ThreadPoolExecutor(max_workers=4) as executor:
|
||||
list(executor.map(lambda run_id: fetch_run(run_id, args.cache_dir), run_ids))
|
||||
print_report(build_rows(run_ids, args.cache_dir))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||