This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 391578af620 Add a command to take a prepared provider back out of a 
release (#71836)
391578af620 is described below

commit 391578af62027fe8939ad4bd6188eabcc6707f92
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Sep 8 18:51:17 2026 +0200

    Add a command to take a prepared provider back out of a release (#71836)
    
    * Document dropping a prepared provider back to doc-only
    
    Release managers hit this when review concludes a prepared provider's 
changes
    are internal after all: the changelog entry can be corrected, but the 
version
    bump and changelog section stay behind and the provider is still built and
    uploaded. The sequence that actually removes it from the wave - and the 
marker
    file that records it - was described nowhere outside the breeze sources.
    
    The pre-merge sweep only ever looked for providers missing from a wave, so 
the
    opposite direction had nothing watching it in either the manual or the 
agentic
    flow.
    
    * Add a command to take a prepared provider back out of a release
    
    When review concludes that an already-prepared provider has no user-facing
    changes, correcting its changelog entry leaves the version bump and the
    changelog section behind, so the provider is still built and uploaded. 
Undoing
    that by hand is a restore-rerun-answer-N sequence that release managers
    repeatedly get wrong, and it is unavailable during an incremental update at 
all:
    that mode answers every question with yes, so the prompt that reclassifies a
    provider as doc-only never appears.
    
    * Say why a never-released provider cannot be dropped to doc-only
    
    Review pointed out that such a provider gets no doc-only marker. Writing one
    would not help: the marker is only read once the current version is tagged, 
so
    for a first release it is inert, and read literally it would suppress that
    release for good. What was wrong is the message, which claimed there were no
    changes when the real reason is that there is no earlier release to diff
    against.
    
    Marking the two functions that always raise as NoReturn also lets the 
compiler,
    rather than the reader, establish that the loop cannot continue past the
    doc-only branch.
    
    * Refresh the breeze command hash for prepare-provider-documentation
    
    The committed hash was computed against a stale cached breeze build, so CI's
    static checks regenerated it and failed the run.
    
    Generated-by: Claude Code (Opus 5)
    Claude-Session: https://claude.ai/code/session_01XS3bodTDYYGrPmorhtLsjP
---
 .../prepare-providers-documentation/SKILL.md       | 22 ++++++
 dev/README_RELEASE_PROVIDERS.md                    | 58 +++++++++++++++
 ...e-management_prepare-provider-documentation.svg | 78 ++++++++++++--------
 ...e-management_prepare-provider-documentation.txt |  2 +-
 .../commands/release_management_commands.py        | 23 +++++-
 .../commands/release_management_commands_config.py |  1 +
 .../prepare_providers/provider_documentation.py    | 45 +++++++++++-
 dev/breeze/tests/test_provider_documentation.py    | 83 +++++++++++++++++++++-
 8 files changed, 276 insertions(+), 36 deletions(-)

diff --git a/.agents/skills/prepare-providers-documentation/SKILL.md 
b/.agents/skills/prepare-providers-documentation/SKILL.md
index d5d5fe84998..cfcfda85817 100644
--- a/.agents/skills/prepare-providers-documentation/SKILL.md
+++ b/.agents/skills/prepare-providers-documentation/SKILL.md
@@ -901,6 +901,28 @@ git diff --name-only <base-branch>..HEAD -- 
'**/provider.yaml' \
 - **Bucket B — not in the wave.** The provider has unrecorded commits but no
   new version section, so it is a candidate to *join*. Classify it
   (Incremental Phase 3), then take it to **Incremental Phase 3.6**.
+- **Bucket C — in the wave but no longer warranting a release.** The sweep
+  above only finds commits *missing* from a wave; this bucket is the opposite
+  direction, and nothing else in the flow looks for it. A provider that review
+  has since concluded is internal-only or documentation-only still carries the
+  version bump and changelog section written by the initial run, so it would
+  still be built and uploaded to PyPI. Find these by re-reading the entries of
+  each in-wave provider's newest changelog section: if every entry is
+  `Doc-only`, or review reclassified the last remaining non-doc entry as
+  documentation, the provider should leave the wave.
+
+  Drop it back with the dedicated command rather than editing the files by
+  hand — it restores `provider.yaml` and `changelog.rst` to their released
+  state and writes the marker in one step:
+
+  ```bash
+  breeze release-management prepare-provider-documentation --mark-doc-only 
<provider-id>
+  ```
+
+  Then commit `providers/<provider-path>/docs/.latest-doc-only-change.txt`.
+  **Ask the release manager before doing it** — taking a provider out of a wave
+  is their decision, and a `Misc` entry that merely *looks* internal may still
+  be something they want released.
 
 Most Bucket B rows are ordinary noise — repo-wide tooling and test commits
 that correctly keep a provider out of the release. A Bucket B provider whose
diff --git a/dev/README_RELEASE_PROVIDERS.md b/dev/README_RELEASE_PROVIDERS.md
index 34c2132bf0f..eedaa88cbd8 100644
--- a/dev/README_RELEASE_PROVIDERS.md
+++ b/dev/README_RELEASE_PROVIDERS.md
@@ -378,6 +378,56 @@ In case you want to also release a pre-installed provider 
that is in ``not-ready
 you want to release it before you switch their state to ``ready``), pass
 ``--include-not-ready-providers``.
 
+### Dropping a prepared provider back to doc-only (no PyPI artifact)
+
+Two different outcomes are both called "doc-only", and the difference decides 
whether the provider
+gets a PyPI release at all:
+
+| | What it means | PyPI artifact |
+|---|---|---|
+| A `doc-only` entry in the changelog | The provider *is* released; one of the 
entries in the release happens to be documentation | **Yes** |
+| The `.latest-doc-only-change.txt` marker | The provider is *not* released at 
all; only its documentation is republished | **No** |
+
+The second case comes up when a provider was already prepared with, say, a 
`Misc` entry, and review
+then concludes the change is internal or documentation only, so there is 
nothing for users to install.
+Changing the changelog entry is not enough — the version bump and the 
changelog stay prepared, and the
+provider would still be built and uploaded. Drop the provider back to doc-only 
with:
+
+```shell script
+breeze release-management prepare-provider-documentation --mark-doc-only 
PROVIDER [MORE PROVIDERS]
+```
+
+This restores the provider's `provider.yaml` and `changelog.rst` to their 
released state, then writes
+`providers/PROVIDER/docs/.latest-doc-only-change.txt`. No version bump, no 
changelog section, no
+distribution. It needs an explicit list of providers — it takes them out of 
the release, so it will
+not default to every provider.
+
+Commit the marker file afterwards. It is the only artifact of the whole 
sequence, and it must be
+committed or the next release will prepare the provider again:
+
+```shell script
+git add providers/PROVIDER/docs/.latest-doc-only-change.txt
+```
+
+Doing it by hand is the same three steps: restore those two files, re-run
+`prepare-provider-documentation PROVIDER`, and answer **`N`** to
+`Does the provider: PROVIDER have any changes apart from 'doc-only'?`. Note 
that the interactive
+prompt is not reachable during `--incremental-update`, which answers every 
question with "yes" —
+that is what `--mark-doc-only` is for.
+
+The marker holds the full commit hash of the latest change that was declared 
doc-only. On the next
+release, the tooling counts commits since that hash rather than since the last 
release tag, so:
+
+* if nothing landed since the marker, the provider is skipped with
+  `The provider has doc-only changes since the last release. Skipping`;
+* if something did land, only the commits after the marker are classified, so 
the changes already
+  declared doc-only are not offered for classification a second time.
+
+> [!NOTE]
+> The same applies when using the `prepare-providers-documentation` skill — it 
classifies commits,
+> but the decision that a prepared provider should not be released at all is 
still made by the
+> release manager, and is still recorded by this marker file.
+
 ## Update versions of dependent providers to the next version
 
 Sometimes when contributors want to use next version of a dependent provider, 
instead of
@@ -458,6 +508,14 @@ following labels to the PR (if they aren't already set 
from the original PR):
 * `skip common compat check`
 * `allow provider dependency bump`
 
+The rebase before merging is also the point to check the wave in the other 
direction. The incremental
+flow looks for commits that are *missing* from the release; it does not look 
for providers that are in
+the release but should no longer be there. If review concluded that a prepared 
provider's only changes
+are internal or documentation, that provider still carries its version bump 
and changelog section, and
+it would still be built and uploaded. Drop it back with [Dropping a prepared 
provider back to
+doc-only](#dropping-a-prepared-provider-back-to-doc-only-no-pypi-artifact) 
before merging, so the
+decision made in review is actually reflected in what gets released.
+
 Once approved, merge it - be careful to do it quickly so that no new PRs are 
merged for
 providers in the meantime; if they are, you'd miss them in the changelog.
 
diff --git 
a/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.svg
 
b/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.svg
index 4a2a8e8c474..f300add9c2c 100644
--- 
a/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.svg
+++ 
b/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.svg
@@ -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 1392.0" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath 
id="breeze-release-management-prepare-provider-documentation-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="1243.3999999999999" />
+      <rect x="0" y="0" width="1463.0" height="1341.0" />
     </clipPath>
     <clipPath 
id="breeze-release-management-prepare-provider-documentation-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -195,9 +195,21 @@
 <clipPath 
id="breeze-release-management-prepare-provider-documentation-line-49">
     <rect x="0" y="1197.1" width="1464" height="24.65"/>
             </clipPath>
+<clipPath 
id="breeze-release-management-prepare-provider-documentation-line-50">
+    <rect x="0" y="1221.5" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath 
id="breeze-release-management-prepare-provider-documentation-line-51">
+    <rect x="0" y="1245.9" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath 
id="breeze-release-management-prepare-provider-documentation-line-52">
+    <rect x="0" y="1270.3" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath 
id="breeze-release-management-prepare-provider-documentation-line-53">
+    <rect x="0" y="1294.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="1292.4" rx="8"/><text 
class="breeze-release-management-prepare-provider-documentation-title" 
fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;release-management&#160;prepare-provider-documentation</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1390" rx="8"/><text 
class="breeze-release-management-prepare-provider-documentation-title" 
fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;release-management&#160;prepare-provider-documentation</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -229,35 +241,39 @@
 </text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="483.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-19)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="483.6" textLength="366" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-19)">2025-11-16&#160;or&#160;2025-11-16_01).&#160;</text><text
 class="breeze-release-management-p [...]
 </text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="508" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-20)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="508" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-20)">--incremental-update&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-management-p [...]
 </text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="532.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-21)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="532.4" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-21)">changes.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="556.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-22)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="556.8" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-22)">--only-min-version-update</text><text
 class="breeze-release-management-prepare-provider-docum [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="581.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-23)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="581.2" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-23)">documentation&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="605.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-24)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="605.6" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-24)">--reapply-templates-only&#160;</text><text
 class="breeze-release-management-prepare-provider- [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="630" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-25)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="630" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-25)">to&#160;regenerate&#160;documentation.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&
 [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="654.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-26)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="654.4" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-26)">--non-interactive&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-r [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="678.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-27)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="678.8" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-27)">releasefor&#160;providers&#160;prepared&#160;for&#160;release&#160;-&#160;useful&#160;to&
 [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="703.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-28)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="703.2" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-28)">mode&#160;in&#160;CI.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="727.6" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-29)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="727.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provid [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="752" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-30)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="752" textLength="366" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-30)">&#160;Select&#160;non-regular&#160;providers&#160;</text><text
 class="breeze-release-management- [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="776.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-31)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="776.4" textLength="353.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-31)">--include-not-ready-providers</text><text
 class="breeze-release-management-prepare-provider [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="800.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-32)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="800.8" textLength="353.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-32)">--include-removed-providers&#160;&#160;</text><text
 class="breeze-release-management-prepar [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="556.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-22)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="556.8" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-22)">--mark-doc-only&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="581.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-23)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="581.2" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-23)">the&#160;released&#160;state&#160;and&#160;record&#160;the&#160;doc-only&#160;marker&#160
 [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="605.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-24)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="605.6" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-24)">that&#160;an&#160;already-prepared&#160;provider&#160;has&#160;no&#160;user-facing&#160;c
 [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="630" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-25)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="630" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-25)">of&#160;providers.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="654.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-26)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="654.4" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-26)">--only-min-version-update</text><text
 class="breeze-release-management-prepare-provider-docum [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="678.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-27)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="678.8" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-27)">documentation&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#16
 [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="703.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-28)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="703.2" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-28)">--reapply-templates-only&#160;</text><text
 class="breeze-release-management-prepare-provider- [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="727.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-29)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="727.6" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-29)">to&#160;regenerate&#160;documentation.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1
 [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="752" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-30)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="752" textLength="305" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-30)">--non-interactive&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-relea [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="776.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-31)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="776.4" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-31)">releasefor&#160;providers&#160;prepared&#160;for&#160;release&#160;-&#160;useful&#160;to&
 [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="800.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-32)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="353.8" 
y="800.8" textLength="1085.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-32)">mode&#160;in&#160;CI.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#
 [...]
 </text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="825.2" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-33)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="825.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provid [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="849.6" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-34)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="849.6" textLength="146.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-34)">&#160;Skip&#160;steps&#160;</text><text
 class="breeze-release-management-prepare-provider- [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="874" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-35)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="874" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-35)">--skip-git-fetch</text><text
 class="breeze-release-management-prepare-provider-documentation-r1 [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="898.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-36)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="244" 
y="898.4" textLength="1195.6" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-36)">is&#160;recreated&#160;and&#160;fetched&#160;to&#160;make&#160;sure&#160;that&#160;it&#x27;
 [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="922.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-37)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="922.8" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-37)">--skip-changelog</text><text
 class="breeze-release-management-prepare-provider-documentatio [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="947.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-38)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="947.2" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-38)">--skip-readme&#160;&#160;&#160;</text><text
 class="breeze-release-management-prepare-provid [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="971.6" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-39)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="971.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provid [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="996" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-40)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="996" textLength="219.6" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-40)">&#160;Advanced&#160;options&#160;</text><text
 class="breeze-release-management-prepare-provide [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1020.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-41)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1020.4" textLength="231.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-41)">--base-branch&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-manag [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1044.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-42)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="329.4" 
y="1044.8" textLength="97.6" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-42)">branch)&#160;</text><text
 class="breeze-release-management-prepare-provider-documentation [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1069.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-43)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1069.2" textLength="231.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-43)">--github-repository</text><text
 class="breeze-release-management-prepare-provider-documen [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1093.6" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-44)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="1093.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-prov [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1118" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-45)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="1118" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-45)">&#160;Common&#160;options&#160;</text><text
 class="breeze-release-management-prepare-provide [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1142.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-46)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1142.4" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-46)">--verbose</text><text
 class="breeze-release-management-prepare-provider-documentation-r7" [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1166.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-47)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1166.8" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-47)">--answer&#160;</text><text
 class="breeze-release-management-prepare-provider-documentatio [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1191.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-48)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1191.2" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-48)">--dry-run</text><text
 class="breeze-release-management-prepare-provider-documentation-r7" [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1215.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-49)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1215.6" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-49)">--help&#160;&#160;&#160;</text><text
 class="breeze-release-management-prepare-provider-do [...]
-</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1240" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-50)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="1240" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="849.6" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-34)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="849.6" textLength="366" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-34)">&#160;Select&#160;non-regular&#160;providers&#160;</text><text
 class="breeze-release-managem [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="874" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-35)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="874" textLength="353.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-35)">--include-not-ready-providers</text><text
 class="breeze-release-management-prepare-provider-doc [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="898.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-36)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="898.4" textLength="353.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-36)">--include-removed-providers&#160;&#160;</text><text
 class="breeze-release-management-prepar [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="922.8" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-37)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="922.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provid [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="947.2" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-38)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="947.2" textLength="146.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-38)">&#160;Skip&#160;steps&#160;</text><text
 class="breeze-release-management-prepare-provider- [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="971.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-39)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="971.6" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-39)">--skip-git-fetch</text><text
 class="breeze-release-management-prepare-provider-documentatio [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="996" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-40)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="244" 
y="996" textLength="1195.6" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-40)">is&#160;recreated&#160;and&#160;fetched&#160;to&#160;make&#160;sure&#160;that&#160;it&#x27;s&#1
 [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1020.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-41)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1020.4" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-41)">--skip-changelog</text><text
 class="breeze-release-management-prepare-provider-documentat [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1044.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-42)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1044.8" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-42)">--skip-readme&#160;&#160;&#160;</text><text
 class="breeze-release-management-prepare-prov [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1069.2" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-43)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="1069.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-prov [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1093.6" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-44)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="1093.6" textLength="219.6" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-44)">&#160;Advanced&#160;options&#160;</text><text
 class="breeze-release-management-prepare-p [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1118" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-45)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1118" textLength="231.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-45)">--base-branch&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-release-managemen [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1142.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-46)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="329.4" 
y="1142.4" textLength="97.6" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-46)">branch)&#160;</text><text
 class="breeze-release-management-prepare-provider-documentation [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1166.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-47)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1166.8" textLength="231.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-47)">--github-repository</text><text
 class="breeze-release-management-prepare-provider-documen [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1191.2" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-48)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="1191.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-prov [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1215.6" textLength="24.4" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-49)">╭─</text><text
 class="breeze-release-management-prepare-provider-documentation-r5" x="24.4" 
y="1215.6" textLength="195.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-49)">&#160;Common&#160;options&#160;</text><text
 class="breeze-release-management-prepare-pro [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1240" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-50)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1240" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-50)">--verbose</text><text
 class="breeze-release-management-prepare-provider-documentation-r7" x=" [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1264.4" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-51)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1264.4" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-51)">--answer&#160;</text><text
 class="breeze-release-management-prepare-provider-documentatio [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1288.8" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-52)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1288.8" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-52)">--dry-run</text><text
 class="breeze-release-management-prepare-provider-documentation-r7" [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1313.2" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-53)">│</text><text
 class="breeze-release-management-prepare-provider-documentation-r4" x="24.4" 
y="1313.2" textLength="109.8" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-53)">--help&#160;&#160;&#160;</text><text
 class="breeze-release-management-prepare-provider-do [...]
+</text><text 
class="breeze-release-management-prepare-provider-documentation-r5" x="0" 
y="1337.6" textLength="1464" 
clip-path="url(#breeze-release-management-prepare-provider-documentation-line-54)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-release-management-prepare-provider-documentation-r1" x="1464" 
y="1337.6" textLength="12.2" 
clip-path="url(#breeze-release-management-prepare-prov [...]
 </text>
     </g>
     </g>
diff --git 
a/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt
 
b/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt
index e7ca97a104b..8b5412434a2 100644
--- 
a/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt
+++ 
b/dev/breeze/doc/images/output_release-management_prepare-provider-documentation.txt
@@ -1 +1 @@
-a94ab59178e740921f451bdc68bfb445
+2abadb69d28b092ff196d4c4830046fe
diff --git 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
index f0eb946b1c5..c876d17d654 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -981,6 +981,13 @@ def classify_provider_changes(
     is_flag=True,
     help="Runs incremental update only after rebase of earlier branch to check 
if there are no changes.",
 )
[email protected](
+    "--mark-doc-only",
+    is_flag=True,
+    help="Take the named providers back out of the release: restore their 
version and changelog to the "
+    "released state and record the doc-only marker to commit. Use when review 
concludes that an "
+    "already-prepared provider has no user-facing changes. Requires an 
explicit list of providers.",
+)
 @click.option(
     "--skip-readme",
     is_flag=True,
@@ -1011,6 +1018,7 @@ def prepare_provider_documentation(
     skip_changelog: bool,
     skip_readme: bool,
     incremental_update: bool,
+    mark_doc_only: bool,
     release_date: str | None,
 ):
     from airflow_breeze.prepare_providers.provider_documentation import (
@@ -1019,6 +1027,7 @@ def prepare_provider_documentation(
         PrepareReleaseDocsNoChangesException,
         PrepareReleaseDocsUserQuitException,
         PrepareReleaseDocsUserSkippedException,
+        drop_provider_to_doc_only,
         update_changelog,
         update_index_rst,
         update_min_airflow_version_and_build_files,
@@ -1029,10 +1038,19 @@ def prepare_provider_documentation(
         console_print("[error]Release date is required unless 
--only-min-version-update is used![/]")
         sys.exit(1)
 
+    if mark_doc_only and not provider_distributions:
+        console_print(
+            "[error]--mark-doc-only takes the named providers out of the 
release, so it needs an "
+            "explicit list of providers rather than defaulting to all of 
them![/]"
+        )
+        sys.exit(1)
+
     perform_environment_checks()
     fix_ownership_using_docker()
     cleanup_python_generated_files()
-    if incremental_update:
+    # Forcing "yes" keeps the incremental pass from re-asking about every 
provider, which also puts
+    # the reclassify-to-doc-only prompt out of reach - --mark-doc-only is how 
that decision is applied.
+    if incremental_update and not mark_doc_only:
         set_forced_answer("yes")
     if not provider_distributions:
         provider_distributions = get_available_distributions(
@@ -1052,6 +1070,9 @@ def prepare_provider_documentation(
     for provider_id in provider_distributions:
         try:
             provider_metadata = basic_provider_checks(provider_id)
+            if mark_doc_only:
+                with ci_group(f"Marking '{provider_id}' as doc-only"):
+                    drop_provider_to_doc_only(provider_id, 
base_branch=base_branch)
             if os.environ.get("GITHUB_ACTIONS", "false") != "true":
                 if not only_min_version_update:
                     console_print("-" * get_console().width)
diff --git 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
index fdca9db46e6..4c6175d5949 100644
--- 
a/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
+++ 
b/dev/breeze/src/airflow_breeze/commands/release_management_commands_config.py
@@ -293,6 +293,7 @@ RELEASE_MANAGEMENT_PARAMETERS: dict[str, list[dict[str, str 
| list[str]]]] = {
             "options": [
                 "--release-date",
                 "--incremental-update",
+                "--mark-doc-only",
                 "--only-min-version-update",
                 "--reapply-templates-only",
                 "--non-interactive",
diff --git 
a/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py 
b/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py
index 4fcd4dd34c9..6de99e295e0 100644
--- a/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py
+++ b/dev/breeze/src/airflow_breeze/prepare_providers/provider_documentation.py
@@ -30,7 +30,7 @@ from enum import Enum
 from pathlib import Path
 from shutil import copyfile
 from time import time
-from typing import Any, NamedTuple
+from typing import Any, NamedTuple, NoReturn
 
 from packaging.version import Version, parse
 from rich.syntax import Syntax
@@ -588,7 +588,7 @@ def _ask_the_user_for_the_type_of_changes(non_interactive: 
bool) -> TypeOfChange
 
 def _mark_latest_changes_as_documentation_only(
     provider_id: str, list_of_list_of_latest_changes: list[list[Change]]
-):
+) -> NoReturn:
     latest_change = list_of_list_of_latest_changes[0][0]
     provider_details = get_provider_details(provider_id=provider_id)
     console_print(
@@ -601,6 +601,47 @@ def _mark_latest_changes_as_documentation_only(
     raise PrepareReleaseDocsChangesOnlyException()
 
 
+def drop_provider_to_doc_only(provider_id: str, base_branch: str) -> NoReturn:
+    """Take a provider that is already prepared for release back out of the 
wave.
+
+    Review can conclude that a prepared provider's changes are internal after 
all. Correcting the
+    changelog entry is not enough: the version bump and the changelog section 
are already written,
+    so the provider would still be built and uploaded. Restoring both files to 
their released state
+    and recording the doc-only marker is what actually removes it from the 
release.
+    """
+    provider_details = get_provider_details(provider_id=provider_id)
+    provider_yaml_path = get_provider_yaml(provider_id)
+    changelog_path = provider_details.root_provider_path / "docs" / 
"changelog.rst"
+    restore_paths = [str(path) for path in (provider_yaml_path, 
changelog_path) if path.exists()]
+    console_print(f"[info]Restoring {provider_id} to its released state before 
marking it doc-only.[/]")
+    run_command(
+        ["git", "checkout", f"{HTTPS_REMOTE}/{base_branch}", "--", 
*restore_paths],
+        cwd=AIRFLOW_ROOT_PATH,
+        check=True,
+    )
+    clear_cache_for_provider_metadata(provider_yaml_path=provider_yaml_path)
+    marked_for_release, list_of_list_of_changes, _ = 
_get_all_changes_for_package(
+        provider_id=provider_id,
+        base_branch=base_branch,
+        reapply_templates_only=False,
+        only_min_version_update=False,
+    )
+    if not list_of_list_of_changes or not list_of_list_of_changes[0]:
+        if marked_for_release:
+            # Restored to the released state and still up for release with no 
earlier version to diff
+            # against: the provider has never been released. The marker means 
"everything after this
+            # commit is documentation" and is only read once the current 
version is tagged, so writing
+            # one here would be inert - and taken literally, would suppress 
the first release for good.
+            console_print(
+                f"[warning]{provider_id} has never been released, so there is 
no release to take it "
+                f"out of. Its prepared files were restored - drop it from the 
wave instead.[/]"
+            )
+        else:
+            console_print(f"[warning]No changes found for {provider_id} - 
nothing to mark as doc-only.[/]")
+        raise PrepareReleaseDocsNoChangesException()
+    _mark_latest_changes_as_documentation_only(provider_id, 
list_of_list_of_changes)
+
+
 VERSION_MAJOR_INDEX = 0
 VERSION_MINOR_INDEX = 1
 VERSION_PATCHLEVEL_INDEX = 2
diff --git a/dev/breeze/tests/test_provider_documentation.py 
b/dev/breeze/tests/test_provider_documentation.py
index 9deb9b225cb..25d7b493291 100644
--- a/dev/breeze/tests/test_provider_documentation.py
+++ b/dev/breeze/tests/test_provider_documentation.py
@@ -30,6 +30,7 @@ from airflow_breeze.prepare_providers.provider_documentation 
import (
     VERSION_PATCHLEVEL_INDEX,
     Change,
     PrepareReleaseDocsChangesOnlyException,
+    PrepareReleaseDocsNoChangesException,
     TypeOfChange,
     _convert_git_changes_to_table,
     _find_insertion_index_for_version,
@@ -38,12 +39,13 @@ from 
airflow_breeze.prepare_providers.provider_documentation import (
     _get_git_log_command,
     classification_result,
     classify_change_deterministically,
+    drop_provider_to_doc_only,
     get_most_impactful_change,
     get_version_tag,
     update_release_notes,
 )
 from airflow_breeze.utils.confirm import Answer
-from airflow_breeze.utils.packages import ProviderPackageDetails
+from airflow_breeze.utils.packages import HTTPS_REMOTE, ProviderPackageDetails
 
 PROVIDER_DOCUMENTATION = 
"airflow_breeze.prepare_providers.provider_documentation"
 
@@ -601,3 +603,82 @@ def 
test_doc_only_marker_written_when_classification_overrides_user_answer(
         )
 
     assert marker_file.read_text().strip() == change.full_hash
+
+
+def _make_doc_only_change(full_hash: str = "a" * 40) -> Change:
+    return Change(
+        full_hash=full_hash,
+        short_hash=full_hash[:7],
+        date="2026-06-08",
+        version="1.0.0",
+        message="Fix a typo",
+        message_without_backticks="Fix a typo",
+        pr="123",
+    )
+
+
[email protected]("airflow_breeze.prepare_providers.provider_documentation.run_command")
[email protected]("airflow_breeze.prepare_providers.provider_documentation._get_all_changes_for_package")
[email protected]("airflow_breeze.prepare_providers.provider_documentation.clear_cache_for_provider_metadata")
[email protected]("airflow_breeze.prepare_providers.provider_documentation.get_provider_yaml")
[email protected]("airflow_breeze.prepare_providers.provider_documentation.get_provider_details")
+def 
test_drop_provider_to_doc_only_restores_the_release_state_and_records_the_marker(
+    mock_details, mock_yaml, mock_clear_cache, mock_changes, mock_run, tmp_path
+):
+    """Correcting the changelog is not enough - the prepared bump would still 
be released."""
+    docs = tmp_path / "docs"
+    docs.mkdir()
+    changelog = docs / "changelog.rst"
+    changelog.write_text("changelog")
+    provider_yaml = tmp_path / "provider.yaml"
+    provider_yaml.write_text("versions: [1.0.0]")
+    mock_details.return_value = mock.MagicMock(root_provider_path=tmp_path)
+    mock_yaml.return_value = provider_yaml
+    mock_changes.return_value = (True, [[_make_doc_only_change()]], "table")
+
+    with pytest.raises(PrepareReleaseDocsChangesOnlyException):
+        drop_provider_to_doc_only("amazon", base_branch="main")
+
+    restored = mock_run.call_args.args[0]
+    assert restored[:4] == ["git", "checkout", f"{HTTPS_REMOTE}/main", "--"]
+    assert str(provider_yaml) in restored
+    assert str(changelog) in restored
+    assert (docs / ".latest-doc-only-change.txt").read_text() == "a" * 40 + 
"\n"
+
+
[email protected](
+    ("marked_for_release", "expected_reason"),
+    [
+        pytest.param(True, "has never been released", id="never-released"),
+        pytest.param(False, "No changes found", 
id="nothing-since-last-release"),
+    ],
+)
[email protected]("airflow_breeze.prepare_providers.provider_documentation.run_command")
[email protected]("airflow_breeze.prepare_providers.provider_documentation._get_all_changes_for_package")
[email protected]("airflow_breeze.prepare_providers.provider_documentation.clear_cache_for_provider_metadata")
[email protected]("airflow_breeze.prepare_providers.provider_documentation.get_provider_yaml")
[email protected]("airflow_breeze.prepare_providers.provider_documentation.get_provider_details")
+def 
test_drop_provider_to_doc_only_writes_no_marker_when_there_is_nothing_to_mark(
+    mock_details,
+    mock_yaml,
+    mock_clear_cache,
+    mock_changes,
+    mock_run,
+    tmp_path,
+    capsys,
+    marked_for_release,
+    expected_reason,
+):
+    """An empty marker would silence the provider's next release entirely, and 
a provider without a
+    release has nothing for the marker to point at."""
+    docs = tmp_path / "docs"
+    docs.mkdir()
+    mock_details.return_value = mock.MagicMock(root_provider_path=tmp_path)
+    mock_yaml.return_value = tmp_path / "provider.yaml"
+    mock_changes.return_value = (marked_for_release, [], "")
+
+    with pytest.raises(PrepareReleaseDocsNoChangesException):
+        drop_provider_to_doc_only("amazon", base_branch="main")
+
+    assert not (docs / ".latest-doc-only-change.txt").exists()
+    assert expected_reason in capsys.readouterr().out

Reply via email to