shahar1 opened a new issue, #70587:
URL: https://github.com/apache/airflow/issues/70587
## Human Summary
Since the providers registry build was introduced into the docs release
process, the release
process for the providers' docs became longer by about 20-45 minutes (median
~23).
The big issue is that this process is composed of sequential runs of
different GitHub Actions
workflows in different repositories (airflow, airflow-site, and
airflow-site-archive), and this
process shouldn't be interrupted. More run time means:
1. More time spent on watching the entire process.
2. More chance that things will go wrong in the critical path, and we might
need to do things all
over again.
In my opinion, the provider registry is not as critical a component as the
docs - which means that
it would be better separated into another workflow that will be initiated
separately.
related: #50648, #45641, #44373, #32491, #50570, #66436
<details>
<summary>Detailed investigation - measurements, code references and two open
questions (AI-generated)</summary>
During a provider release wave the release manager runs `breeze workflow-run
publish-docs` and has
to keep the terminal open and the machine awake until it returns — the whole
chain is driven from
the release manager's laptop, hence the warning at
[`dev/README_RELEASE_PROVIDERS.md:1769-1772`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/dev/README_RELEASE_PROVIDERS.md#L1769-L1772):
> Make sure to NOT close the terminal while the command is running and to
keep your computer from
> sleep. This command will run several (3!) workflows from your terminal and
this is important to
> keep it running until completion.
On the 2026-07-22 wave the `publish-docs-to-s3.yml` run alone took 90
minutes, and the docs had
been live on S3 since minute 47. The rest was the provider registry build,
which the release
manager gains nothing by waiting for. Two questions below about getting it
off that path.
#### Measured
Per-job timings, three recent wave runs:
| Job |
[30335779728](https://github.com/apache/airflow/actions/runs/30335779728) |
[30042123097](https://github.com/apache/airflow/actions/runs/30042123097) |
[29107680148](https://github.com/apache/airflow/actions/runs/29107680148) |
|---|---|---|---|
| Build Info | 0.7m | 0.7m | 0.7m |
| Build documentation | 41.0m | 34.2m | 41.8m |
| Publish documentation to S3 | 4.3m | 4.7m | 4.5m |
| — *docs are live from here* — | | | |
| Registry: Build CI image | **32.5m** | **13.3m** | **31.8m** |
| Registry: Build & Publish | 10.5m | 9.3m | 9.7m |
| **Total (wall clock)** | **90.2m** | **62.4m** | **88.9m** |
| *of which after docs were live* | *43.4m (48%)* | *22.7m (36%)* | *41.6m
(47%)* |
*(Total is run `createdAt`→`updatedAt`, so it exceeds the sum of the jobs by
the queue gaps.
`Build Java SDK Javadoc` — 0.2m, parallel with `Build documentation` — is
omitted.)*
Over the last 20 runs of the workflow, excluding one failed and one
cancelled run, split on whether
the `Update Provider Registry` job ran or was skipped:
| Cohort | n | Median total | Range |
|---|---|---|---|
| Registry ran | 11 | **59.9m** | 34.7–90.2m |
| Registry skipped | 7 | **21.2m** | 14.4–22.1m |
Not a clean A/B — the skipped runs are core version publishes plus one
dev-branch run, whose
`Build documentation` median is 16.1m against 32.6m for the registry-ran
cohort. Of the 38.7m
difference, roughly 23m is the registry and roughly 16m the larger docs
build.
The registry sub-workflow on its own: median **23.0m**, range 17.3–43.0m
(n=11) — ~38% of the
median run, and 100% additive because it is strictly serial after the S3
publish. Over half of it
(median 13.4m, range 8.0–33.1m) is spent building a CI image before `breeze
registry extract-data`
runs.
#### Question 1: why does the registry job build its own CI image?
[`registry-build.yml:59-94`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/registry-build.yml#L59-L94)
calls `ci-image-build.yml` with `branch: "main"` and `push-image: "false"`.
`branch` only sets
`DEFAULT_BRANCH` — the image name and therefore the buildx cache source
([`ci-image-build.yml:115`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/ci-image-build.yml#L115)).
No `checkout-ref` is passed, so
[`:125-129`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/ci-image-build.yml#L125-L129)
checks out the workflow ref, i.e. the release tag. The job therefore builds
**the release tag's
sources under main's image name, against main's registry cache**. The hit
rate is unstable as a
result: the same tag rebuilt on 2026-07-23 and 2026-07-28 took 13.3m and
32.5m, the slow run
re-running `install_os_dependencies.sh` for 19.6m after #70285 landed on
main.
Meanwhile
[`publish-docs-to-s3.yml:301-318`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/publish-docs-to-s3.yml#L301-L318)
builds a CI image from the *same ref, in the same run*, and never stashes
it. So every wave pays
for two full CI image builds from the same sources — the docs job's
`python3.10`
([`:101`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/publish-docs-to-s3.yml#L101))
and the registry's `python3.12`
([`registry-build.yml:88`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/registry-build.yml#L88)).
Could the registry job consume the docs job's image instead of rebuilding —
accepting that this
would move registry extraction to 3.10 — or, if main-tip dependencies are
acceptable, pull
`ghcr.io/apache/airflow/main/ci/python3.12`, which canary already pushes via
`finalize-tests.yml` → `push-image-cache.yml`? (For the pull variant note
that
`build-and-publish-registry` sets its own
[`permissions: contents:
read`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/registry-build.yml#L112-L113),
which replaces the workflow-level default, so it would need `packages: read`
adding — though the
images are public.)
To be clear about what cannot be dropped: two of the three extractors need
the image.
`breeze registry extract-data` runs `extract_metadata.py`,
`extract_parameters.py` and
`extract_connections.py`
([`registry_commands.py:112-117`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/dev/breeze/src/airflow_breeze/commands/registry_commands.py#L112-L117)),
and module discovery uses runtime inspection inside Breeze where all
providers are installed —
`registry_commands.py:103-105` even `pip install`s suspended providers
first. The question is
build-vs-reuse, not image-vs-no-image. It is worth answering regardless of
question 2 — though
note the two interact: reusing the docs job's image assumes the current
serialisation, so if
question 2 goes the parallel way, only the ghcr-pull variant survives.
#### Question 2: does `update-registry` need `needs: [publish-docs-to-s3]`?
[`publish-docs-to-s3.yml:609`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/publish-docs-to-s3.yml#L609)
is `needs: [publish-docs-to-s3, build-info]`. Dropping the first element —
keeping
`needs: [build-info]` — would run the registry *in parallel* with the docs
build. It stays a
`workflow_call`, so nothing changes about permissions, and `build-info`'s
`destination` /
`registry-providers` / `registry-full-build` outputs are still available —
`update-registry`
consumes nothing from the `publish-docs-to-s3` job. Recomputing the same 11
runs from their
per-job timings, the median run drops from 59.9m to ~39m and no run gets
longer, though on 5 of
the 11 the registry is the longer branch and becomes the critical path
itself. That is arithmetic
on historical timestamps, not an executed run — in particular it assumes the
two CI-image builds
can run concurrently without contending for runners, which the timestamps
cannot tell us.
The registry reads nothing the docs publish produces — its Sphinx
`objects.inv` fetch goes to
`apache-airflow-docs` (eu-central-1), the main-branch canary bucket written
by
[`ci-image-checks.yml:465`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/ci-image-checks.yml#L465),
not the `live-docs-airflow-apache-org` bucket the publish job writes. The
two also write disjoint
prefixes (`…/docs/` vs `…/registry/`), so there is no clobbering.
What it *emits* is the real question. The docs URLs the wave build generates
are all `/stable/`:
```python
# dev/registry/extract_metadata.py:63
AIRFLOW_PROVIDER_DOCS_URL =
"https://airflow.apache.org/docs/{package_name}/stable/"
# dev/registry/extract_parameters.py:451
base_docs_url =
f"https://airflow.apache.org/docs/apache-airflow-providers-{provider_id}/stable"
```
and they are used for deep links, not just landing pages — per-class API
anchors
(`extract_parameters.py:463-468`) and per-connection pages
(`extract_metadata.py:317-326`). Since
the inventory comes from the canary bucket, it already knows about modules
newer than the release.
So publishing the registry before the docs gives a window in which
`/stable/` links point at the
previous version, and anything **new in this release** — new provider, new
module, new connection
page — 404s until the docs land.
Recomputing that window over the same 11 runs (registry starting after
`build-info` instead of
after the publish): in **5 of 11 the window is negative** — the registry
would still have landed
after the docs, so no exposure at all. On the other 6 it runs up to ~21
minutes, median ~3 minutes
across all 11. Note the shape: the largest windows (17–21m) are the waves
where the registry's
CI-image build hit cache and took 8–13m, while the two 90-minute waves —
where that build took
~32m — come out under 5 minutes. Fixing question 1 would make this window
*wider*, not narrower.
There is a second consequence that is not just ordering: `needs:
[publish-docs-to-s3]` currently
*gates* the registry, so a failed docs build or publish skips it. Remove the
edge and the registry
publishes to live regardless, and the window stops being bounded — the
registry would sit there
pointing at `/stable/` pages that never landed. If we do this, the gate
probably has to be
reinstated somewhere, e.g. on the S3 sync step rather than on the whole job.
Note that the GitHub source URLs *are* version-pinned
(`extract_metadata.py:64-66`,
`extract_parameters.py:450-452`) and gated on the `providers-<id>/<ver>` tag
existing
([`find_latest_released_version`,
`extract_metadata.py:507-521`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/dev/registry/extract_metadata.py#L507-L521)),
so the tag is a hard input — but the tag is pushed one step *before* docs
publishing
([`README_RELEASE_PROVIDERS.md:1706`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/dev/README_RELEASE_PROVIDERS.md#L1706)),
so it is already satisfied by the time the workflow starts.
So: is a stale window of that size on new modules acceptable in exchange for
taking the registry
off the critical path, and where should the failed-publish gate live? If the
window is not
acceptable, is there a cheaper ordering than "wait for the whole publish
job"?
Worth recording why the *fully* decoupled variant is harder, in case someone
proposes it: a
`gh workflow run` issued from inside Actions arrives as `workflow_dispatch`
with
`github.event.sender.login == github-actions[bot]`, which fails the
committer allowlist at
[`registry-build.yml:65-81`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/.github/workflows/registry-build.yml#L65-L81);
`build-and-publish-registry` needs that job, so the run would go green
having done nothing — the
same silent-skip class as #65188. That would need a bot entry in the
allowlist, which is what
#69460 proposes to delete. Neither of the questions above requires going
there.
#### Separately
The release manager's wait is also longer than the workflow for an unrelated
reason:
[`monitor_workflow_run`](https://github.com/apache/airflow/blob/379d4ac118071af99e62278fcaf0b1ba5b4f2c45/dev/breeze/src/airflow_breeze/utils/gh_workflow_utils.py#L150-L193)
polls **run**-level status, so the `apache/airflow-site` refresh does not
start until the whole run
finishes, registry included. Returning once `Publish documentation to S3`
succeeds would unblock the
terminal at ~47m instead of ~90m. The trade-off is failure visibility: today
a failed run exits
non-zero in the release manager's terminal, and #65188 is a case of a
registry problem going
unnoticed for weeks, so an early return needs a real signal rather than a
printed URL. Fixing
question 2 removes most of the need for this.
#### Why now, given #50648
[#50648](https://github.com/apache/airflow/issues/50648) asked for faster
docs publishing and was
closed on 2025-06-09 with:
> Yeah. I think release date is more important than speed of publishing.
Especially that it is not
> **that** slow and with the "publish-docs" breeze command it's fine to just
submit it in terminal
> and let it run until it gets completed..
>
> Closing
I am not reopening the artifact-reuse idea declined there — the release-date
argument against it
still holds. But that assessment predates the registry, merged in
[#62261](https://github.com/apache/airflow/pull/62261) on 2026-03-07.
#50648's body cites "12-15
minutes"; runs where the registry job fires now median 59.9m. "Submit it in
terminal and let it
run" is a different proposition at 90 minutes than at 15.
#### Related
- #62261 added the registry and the `needs:` chaining.
- #66436 (release-breaking), #65506 (surfaced a red check on every
airflow-ctl / task-sdk docs
publish) and #65188 (the registry job silently never ran) are three bugs
in the registry-input
derivation inside this workflow's `build-info` job. Neither question above
addresses that class.
- #69460 — replace the per-workflow committer allowlists with a protected
`release` environment.
It does not enumerate `registry-build.yml`, but the intent covers it.
</details>
### Committer
- [x] I acknowledge that I am a maintainer/committer of the Apache Airflow
project.
---
Drafted-by: Claude Code (Opus 5); reviewed by @shahar1 before posting
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]