This is an automated email from the ASF dual-hosted git repository.
ephraimanierobi pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit b9aed715fada9b41572c0741260fb0b852d8f68d
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Nov 1 19:15:42 2025 +0100
[v3-1-test] Dev: Add Task SDK support to `start-release` command (#57658)
(#57666)
* Add Task SDK support to start-release command
Enhance the breeze release-management start-release command to handle
Task SDK releases alongside Airflow releases, matching the functionality
of the start-rc-process command.
Changes:
- Add optional --task-sdk-release-candidate parameter to start-release
- Update SVN operations to handle both Airflow and Task SDK artifacts
- Support uploading both packages to PyPI separately
- Create and push tags for both Airflow and Task SDK releases
- Improve documentation with environment variables for all version
parameters
- Add concrete examples for publish-docs commands
This allows release managers to release Airflow and Task SDK together
in a single workflow or release Airflow independently when Task SDK
updates are not needed.
* Update vote email template to include Task SDK
Update the vote email template to include Task SDK release information,
based on the format used in recent releases.
Changes:
- Add TASK_SDK_VERSION_WITHOUT_RC environment variable
- Update subject line to include both Airflow and Task SDK versions
- Add separate sections for Task SDK artifacts
- Include Task SDK in PyPI installation instructions
- Add docs preview and release notes links
- Add simplified uv-based installation example
(cherry picked from commit 1c845c2838fb8db0969b62588a362778cc9a1f30)
Co-authored-by: Kaxil Naik <[email protected]>
---
dev/README_RELEASE_AIRFLOW.md | 96 +++++++------
.../output_release-management_start-release.svg | 28 ++--
.../output_release-management_start-release.txt | 2 +-
.../src/airflow_breeze/commands/release_command.py | 151 +++++++++++++++++----
.../commands/release_management_commands_config.py | 5 +-
5 files changed, 201 insertions(+), 81 deletions(-)
diff --git a/dev/README_RELEASE_AIRFLOW.md b/dev/README_RELEASE_AIRFLOW.md
index 4aed6b4daa5..f8aaa54d122 100644
--- a/dev/README_RELEASE_AIRFLOW.md
+++ b/dev/README_RELEASE_AIRFLOW.md
@@ -277,6 +277,8 @@ export VERSION_SUFFIX=rc1
export VERSION_BRANCH=2-1
export VERSION_WITHOUT_RC=${VERSION/rc?/}
export TASK_SDK_VERSION=1.0.5rc1
+export TASK_SDK_VERSION_WITHOUT_RC=${TASK_SDK_VERSION/rc?/}
+export PREVIOUS_VERSION=3.0.4
# Set AIRFLOW_REPO_ROOT to the path of your git repo
export AIRFLOW_REPO_ROOT=$(pwd)
@@ -362,7 +364,7 @@ uv tool install -e ./dev/breeze
git pull # Ensure that the script is up-to-date
breeze release-management start-rc-process \
--version ${VERSION} \
- --previous-version <PREVIOUS_VERSION> \
+ --previous-version ${PREVIOUS_VERSION} \
--task-sdk-version ${TASK_SDK_VERSION}
```
@@ -373,7 +375,7 @@ uv tool install -e ./dev/breeze
# Test with dry-run (shows what would be executed without doing it)
breeze release-management start-rc-process \
--version ${VERSION} \
- --previous-version <PREVIOUS_VERSION> \
+ --previous-version ${PREVIOUS_VERSION} \
--task-sdk-version ${TASK_SDK_VERSION} \
--remote-name upstream \
--dry-run
@@ -390,7 +392,7 @@ uv tool install -e ./dev/breeze
- Generate the body of the issue using the below command:
```shell script
- breeze release-management generate-issue-content-core --previous-release
<PREVIOUS_VERSION> --current-release ${VERSION}
+ breeze release-management generate-issue-content-core --previous-release
${PREVIOUS_VERSION} --current-release ${VERSION}
```
## Publish release candidate documentation (staging)
@@ -414,7 +416,10 @@ The command does the following:
3. Triggers S3 to GitHub Sync
```shell script
- breeze workflow-run publish-docs --ref <tag> --site-env <staging/live/auto>
apache-airflow docker-stack task-sdk
+breeze workflow-run publish-docs --ref <tag> --site-env <staging/live/auto>
apache-airflow docker-stack task-sdk
+
+# Example for RC
+breeze workflow-run publish-docs --ref ${VERSION} --site-env staging
apache-airflow docker-stack task-sdk
```
The `--ref` parameter should be the tag of the release candidate you are
publishing.
@@ -501,7 +506,7 @@ Subject:
```shell script
cat <<EOF
-[VOTE] Release Airflow ${VERSION_WITHOUT_RC} from ${VERSION}
+[VOTE] Release Airflow ${VERSION_WITHOUT_RC} from ${VERSION} & Task SDK
${TASK_SDK_VERSION_WITHOUT_RC} from ${TASK_SDK_VERSION}
EOF
```
@@ -511,24 +516,35 @@ Body:
cat <<EOF
Hey fellow Airflowers,
-I have cut Airflow ${VERSION}. This email is calling a vote on the release,
-which will last at least 72 hours, from Friday, October 8, 2021 at 4:00 pm UTC
+The release candidates for Apache Airflow ${VERSION} and Task SDK
${TASK_SDK_VERSION} are now available for testing!
+
+This email is calling for a vote on the release, which will last at least 72
hours, from Friday, October 8, 2021 at 4:00 pm UTC
until Monday, October 11, 2021 at 4:00 pm UTC, and until 3 binding +1 votes
have been received.
https://www.timeanddate.com/worldclock/fixedtime.html?msg=8&iso=20211011T1600&p1=1440
Status of testing of the release is kept in TODO:URL_OF_THE_ISSUE_HERE
-Consider this my (binding) +1.
+Consider this my +1 binding vote.
Airflow ${VERSION} is available at:
-https://dist.apache.org/repos/dist/dev/airflow/$VERSION/
+https://dist.apache.org/repos/dist/dev/airflow/${VERSION}/
+
+"apache-airflow" Meta package:
+- *apache-airflow-${VERSION_WITHOUT_RC}-source.tar.gz* is a source release
that comes with INSTALL instructions.
+- *apache-airflow-${VERSION_WITHOUT_RC}.tar.gz* is the binary Python "sdist"
release.
+- *apache_airflow-${VERSION_WITHOUT_RC}-py3-none-any.whl* is the binary Python
wheel "binary" release.
+
+"apache-airflow-core" package:
+- *apache_airflow_core-${VERSION_WITHOUT_RC}.tar.gz* is the binary Python
"sdist" release.
+- *apache_airflow_core-${VERSION_WITHOUT_RC}-py3-none-any.whl* is the binary
Python wheel "binary" release.
+
+Task SDK ${TASK_SDK_VERSION} is available at:
+https://dist.apache.org/repos/dist/dev/airflow/task-sdk/${TASK_SDK_VERSION}/
-*apache-airflow-${VERSION_WITHOUT_RC}-source.tar.gz* is a source release that
comes with INSTALL instructions.
-*apache-airflow-${VERSION_WITHOUT_RC}.tar.gz* is the binary Python "sdist"
release fore airflow meta distribution.
-*apache_airflow-${VERSION_WITHOUT_RC}-py3-none-any.whl* is the binary Python
wheel "binary" release for airflow meta distribution.
-*apache-airflow_core-${VERSION_WITHOUT_RC}.tar.gz* is the binary Python
"sdist" release for airflow core distribution.
-*apache_airflow_core-${VERSION_WITHOUT_RC}-py3-none-any.whl* is the binary
Python wheel "binary" release for airflow core distribution.
+"apache-airflow-task-sdk" package:
+- *apache_airflow_task_sdk-${TASK_SDK_VERSION_WITHOUT_RC}.tar.gz* is the
binary Python "sdist" release.
+- *apache_airflow_task_sdk-${TASK_SDK_VERSION_WITHOUT_RC}-py3-none-any.whl* is
the binary Python wheel "binary" release.
Public keys are available at:
https://dist.apache.org/repos/dist/release/airflow/KEYS
@@ -549,36 +565,26 @@ The test procedure for contributors and members of the
community who would like
https://github.com/apache/airflow/blob/main/dev/README_RELEASE_AIRFLOW.md#verify-the-release-candidate-by-contributors
Please note that the version number excludes the 'rcX' string, so it's now
-simply ${VERSION_WITHOUT_RC}. This will allow us to rename the artifact
without modifying
+simply ${VERSION_WITHOUT_RC} for Airflow package and
${TASK_SDK_VERSION_WITHOUT_RC} for Task SDK. This will allow us to rename the
artifact without modifying
the artifact checksums when we actually release.
-Release Notes:
https://github.com/apache/airflow/blob/${VERSION}/RELEASE_NOTES.rst
+Docs (for preview):
+https://airflow.staged.apache.org/docs/apache-airflow/${VERSION_WITHOUT_RC}
-For information on what goes into a release please see:
https://github.com/apache/airflow/blob/main/dev/WHAT_GOES_INTO_THE_NEXT_RELEASE.md
+Release Notes:
+- https://github.com/apache/airflow/blob/${VERSION}/RELEASE_NOTES.rst
+-
https://airflow.staged.apache.org/docs/apache-airflow/${VERSION_WITHOUT_RC}/release_notes.html
(Rendered HTML)
-Changes since PREVIOUS_VERSION_OR_RC:
-*Bugs*:
-[AIRFLOW-3732] Fix issue when trying to edit connection in RBAC UI
-[AIRFLOW-2866] Fix missing CSRF token head when using RBAC UI (#3804)
-...
+Testing Instructions using PyPI:
+You can build a virtualenv that installs this and other required packages
(e.g. task sdk), like this:
+uv venv
+uv pip install -U \\
+ apache-airflow==${VERSION} \\
+ apache-airflow-core==${VERSION} \\
+ apache-airflow-task-sdk==${TASK_SDK_VERSION}
-*Improvements*:
-[AIRFLOW-3302] Small CSS fixes (#4140)
-[Airflow-2766] Respect shared datetime across tabs
-...
-
-
-*New features*:
-[AIRFLOW-2874] Enables FAB's theme support (#3719)
-[AIRFLOW-3336] Add new TriggerRule for 0 upstream failures (#4182)
-...
-
-
-*Doc-only Change*:
-[AIRFLOW-XXX] Fix BashOperator Docstring (#4052)
-[AIRFLOW-3018] Fix Minor issues in Documentation
-...
+Constraints files are at
https://github.com/apache/airflow/tree/constraints-${VERSION}
Cheers,
<your name>
@@ -947,12 +953,19 @@ The best way of doing this is to svn cp between the two
repos (this avoids havin
```shell script
export RC=3.0.5rc5
export VERSION=${RC/rc?/}
+export TASK_SDK_RC=1.0.5rc1
+export PREVIOUS_RELEASE=3.0.4
# cd to the airflow repo directory and set the environment variable below
export AIRFLOW_REPO_ROOT=$(pwd)
# start the release process by running the below command
-breeze release-management start-release --release-candidate ${RC}
--previous-release <PREVIOUS RELEASE>
+breeze release-management start-release \
+ --release-candidate ${RC} \
+ --previous-release ${PREVIOUS_RELEASE} \
+ --task-sdk-release-candidate ${TASK_SDK_RC}
```
+Note: The `--task-sdk-release-candidate` parameter is optional. If you are
releasing Airflow without a corresponding Task SDK release, you can omit this
parameter.
+
```Dockerfile
ARG AIRFLOW_EXTRAS=".....,<provider>,...."
```
@@ -1016,10 +1029,11 @@ The command does the following:
3. Triggers S3 to GitHub Sync
```shell script
- breeze workflow-run publish-docs --ref <tag> --site-env <staging/live/auto>
+# Example for final release
+breeze workflow-run publish-docs --ref ${VERSION_WITHOUT_RC} --site-env live
apache-airflow docker-stack task-sdk
```
-The `--ref` parameter should be the tag of the final candidate you are
publishing.
+The `--ref` parameter should be the tag of the final version you are
publishing.
The `--site-env` parameter should be set to `staging` for pre-release versions
or `live` for final releases. the default option is `auto`
if the tag is rc it publishes to `staging` bucket, otherwise it publishes to
`live` bucket.
diff --git a/dev/breeze/doc/images/output_release-management_start-release.svg
b/dev/breeze/doc/images/output_release-management_start-release.svg
index 91411fe496c..41227a891b6 100644
--- a/dev/breeze/doc/images/output_release-management_start-release.svg
+++ b/dev/breeze/doc/images/output_release-management_start-release.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 416.0"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 440.4"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -45,7 +45,7 @@
<defs>
<clipPath id="breeze-release-management-start-release-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="365.0" />
+ <rect x="0" y="0" width="1463.0" height="389.4" />
</clipPath>
<clipPath id="breeze-release-management-start-release-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -89,9 +89,12 @@
<clipPath id="breeze-release-management-start-release-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-release-management-start-release-line-14">
+ <rect x="0" y="343.1" 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="414" rx="8"/><text
class="breeze-release-management-start-release-title" fill="#c5c8c6"
text-anchor="middle" x="740"
y="27">Command: release-management start-release</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="438.4" rx="8"/><text
class="breeze-release-management-start-release-title" fill="#c5c8c6"
text-anchor="middle" x="740"
y="27">Command: release-management start-release</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -107,15 +110,16 @@
</text><text class="breeze-release-management-start-release-r1" x="12.2"
y="93.2" textLength="1305.4"
clip-path="url(#breeze-release-management-start-release-line-3)">Start the process of releasing an Airflow version. This command will guide you through the release process.</text><text
class="breeze-release-management-start-release-r1" x="1464" y="93.2"
textLength="12.2" clip-path="url(#breeze-release-managem [...]
</text><text class="breeze-release-management-start-release-r1" x="1464"
y="117.6" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-4)">
</text><text class="breeze-release-management-start-release-r5" x="0" y="142"
textLength="24.4"
clip-path="url(#breeze-release-management-start-release-line-5)">╭─</text><text
class="breeze-release-management-start-release-r5" x="24.4" y="142"
textLength="256.2"
clip-path="url(#breeze-release-management-start-release-line-5)"> Start release flags </text><text
class="breeze-release-management-start-release-r5" x="280.6" y="142"
textLength="1159" clip-path="url(#breeze- [...]
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="166.4" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-6)">│</text><text
class="breeze-release-management-start-release-r6" x="24.4" y="166.4"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-6)">*</text><text
class="breeze-release-management-start-release-r4" x="61" y="166.4"
textLength="231.8"
clip-path="url(#breeze-release-management-start-release-line- [...]
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="190.8" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-7)">│</text><text
class="breeze-release-management-start-release-r6" x="24.4" y="190.8"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-7)">*</text><text
class="breeze-release-management-start-release-r4" x="61" y="190.8"
textLength="219.6"
clip-path="url(#breeze-release-management-start-release-line- [...]
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="215.2" textLength="1464"
clip-path="url(#breeze-release-management-start-release-line-8)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-start-release-r1" x="1464" y="215.2"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-8)">
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="239.6" textLength="24.4"
clip-path="url(#breeze-release-management-start-release-line-9)">╭─</text><text
class="breeze-release-management-start-release-r5" x="24.4" y="239.6"
textLength="195.2"
clip-path="url(#breeze-release-management-start-release-line-9)"> Common options </text><text
class="breeze-release-management-start-release-r5" x="219.6" y="239.6"
textLength="1220" clip-path="url(#breeze-rele [...]
-</text><text class="breeze-release-management-start-release-r5" x="0" y="264"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-10)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="264"
textLength="97.6"
clip-path="url(#breeze-release-management-start-release-line-10)">--answer</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="264"
textLength="24.4" clip-path="url(#breeze-release-management-start-release- [...]
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="288.4" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-11)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="288.4"
textLength="109.8"
clip-path="url(#breeze-release-management-start-release-line-11)">--dry-run</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="288.4"
textLength="24.4" clip-path="url(#breeze-release-management-start- [...]
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="312.8" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-12)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="312.8"
textLength="109.8"
clip-path="url(#breeze-release-management-start-release-line-12)">--verbose</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="312.8"
textLength="24.4" clip-path="url(#breeze-release-management-start- [...]
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="337.2" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-13)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="337.2"
textLength="73.2"
clip-path="url(#breeze-release-management-start-release-line-13)">--help</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="337.2"
textLength="24.4" clip-path="url(#breeze-release-management-start-rele [...]
-</text><text class="breeze-release-management-start-release-r5" x="0"
y="361.6" textLength="1464"
clip-path="url(#breeze-release-management-start-release-line-14)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-start-release-r1" x="1464" y="361.6"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-14)">
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="166.4" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-6)">│</text><text
class="breeze-release-management-start-release-r6" x="24.4" y="166.4"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-6)">*</text><text
class="breeze-release-management-start-release-r4" x="61" y="166.4"
textLength="231.8"
clip-path="url(#breeze-release-management-start-release-line- [...]
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="190.8" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-7)">│</text><text
class="breeze-release-management-start-release-r6" x="24.4" y="190.8"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-7)">*</text><text
class="breeze-release-management-start-release-r4" x="61" y="190.8"
textLength="219.6"
clip-path="url(#breeze-release-management-start-release-line- [...]
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="215.2" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-8)">│</text><text
class="breeze-release-management-start-release-r4" x="61" y="215.2"
textLength="341.6"
clip-path="url(#breeze-release-management-start-release-line-8)">--task-sdk-release-candidate</text><text
class="breeze-release-management-start-release-r1" x="451.4" y="215.2"
textLength="488" clip-path="url(#breeze-release-man [...]
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="239.6" textLength="1464"
clip-path="url(#breeze-release-management-start-release-line-9)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-start-release-r1" x="1464" y="239.6"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-9)">
+</text><text class="breeze-release-management-start-release-r5" x="0" y="264"
textLength="24.4"
clip-path="url(#breeze-release-management-start-release-line-10)">╭─</text><text
class="breeze-release-management-start-release-r5" x="24.4" y="264"
textLength="195.2"
clip-path="url(#breeze-release-management-start-release-line-10)"> Common options </text><text
class="breeze-release-management-start-release-r5" x="219.6" y="264"
textLength="1220" clip-path="url(#breeze-release- [...]
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="288.4" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-11)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="288.4"
textLength="97.6"
clip-path="url(#breeze-release-management-start-release-line-11)">--answer</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="288.4"
textLength="24.4" clip-path="url(#breeze-release-management-start-re [...]
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="312.8" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-12)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="312.8"
textLength="109.8"
clip-path="url(#breeze-release-management-start-release-line-12)">--dry-run</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="312.8"
textLength="24.4" clip-path="url(#breeze-release-management-start- [...]
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="337.2" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-13)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="337.2"
textLength="109.8"
clip-path="url(#breeze-release-management-start-release-line-13)">--verbose</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="337.2"
textLength="24.4" clip-path="url(#breeze-release-management-start- [...]
+</text><text class="breeze-release-management-start-release-r5" x="0"
y="361.6" textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-14)">│</text><text
class="breeze-release-management-start-release-r4" x="24.4" y="361.6"
textLength="73.2"
clip-path="url(#breeze-release-management-start-release-line-14)">--help</text><text
class="breeze-release-management-start-release-r9" x="158.6" y="361.6"
textLength="24.4" clip-path="url(#breeze-release-management-start-rele [...]
+</text><text class="breeze-release-management-start-release-r5" x="0" y="386"
textLength="1464"
clip-path="url(#breeze-release-management-start-release-line-15)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-release-management-start-release-r1" x="1464" y="386"
textLength="12.2"
clip-path="url(#breeze-release-management-start-release-line-15)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_release-management_start-release.txt
b/dev/breeze/doc/images/output_release-management_start-release.txt
index 98156901ab4..5920f348902 100644
--- a/dev/breeze/doc/images/output_release-management_start-release.txt
+++ b/dev/breeze/doc/images/output_release-management_start-release.txt
@@ -1 +1 @@
-d84c6e5a6fcab35c07287bc4d2d65841
+a860ddc98626bc82dc298e2bd0081f97
diff --git a/dev/breeze/src/airflow_breeze/commands/release_command.py
b/dev/breeze/src/airflow_breeze/commands/release_command.py
index 4fe371c2e7a..2ac3bd2547a 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_command.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_command.py
@@ -44,14 +44,18 @@ def clone_asf_repo(working_dir):
)
-def create_version_dir(version):
- if confirm_action(f"Create SVN version directory for {version}?"):
+def create_version_dir(version, task_sdk_version=None):
+ if confirm_action(f"Create SVN version directory for Airflow {version}?"):
run_command(["svn", "mkdir", f"{version}"], check=True)
- console_print(f"{version} directory created")
+ console_print(f"Airflow {version} directory created")
+ if task_sdk_version and confirm_action(f"Create SVN version directory for
Task SDK {task_sdk_version}?"):
+ run_command(["svn", "mkdir", f"task-sdk/{task_sdk_version}"],
check=True)
+ console_print(f"Task SDK {task_sdk_version} directory created")
-def copy_artifacts_to_svn(rc, svn_dev_repo):
- if confirm_action(f"Copy artifacts to SVN for {rc}?"):
+
+def copy_artifacts_to_svn(rc, task_sdk_rc, svn_dev_repo, svn_release_repo):
+ if confirm_action(f"Copy Airflow artifacts to SVN for {rc}?"):
bash_command = f"""
for f in {svn_dev_repo}/{rc}/*; do
svn cp "$f" "$(basename "$f")/"
@@ -66,16 +70,51 @@ def copy_artifacts_to_svn(rc, svn_dev_repo):
],
check=True,
)
- console_print("Artifacts copied to SVN:")
+ console_print("Airflow artifacts copied to SVN:")
+ run_command(["ls"])
+
+ if task_sdk_rc and confirm_action(f"Copy Task SDK artifacts to SVN for
{task_sdk_rc}?"):
+ # Save current directory
+ current_dir = os.getcwd()
+ # Change to task-sdk release directory
+ task_sdk_version = task_sdk_rc[:-3]
+ os.chdir(f"{svn_release_repo}/task-sdk/{task_sdk_version}")
+
+ bash_command = f"""
+ for f in {svn_dev_repo}/task-sdk/{task_sdk_rc}/*; do
+ svn cp "$f" "$(basename "$f")/"
+ done
+ """
+
+ run_command(
+ [
+ "bash",
+ "-c",
+ bash_command,
+ ],
+ check=True,
+ )
+ console_print("Task SDK artifacts copied to SVN:")
run_command(["ls"])
+ # Go back to previous directory
+ os.chdir(current_dir)
-def commit_release(version, rc, svn_release_version_dir):
- if confirm_action(f"Commit release {version} to SVN?"):
+
+def commit_release(version, task_sdk_version, rc, task_sdk_rc,
svn_release_repo):
+ commit_message = f"Release Airflow {version} from {rc}"
+ if task_sdk_version and task_sdk_rc:
+ commit_message += f" & Task SDK {task_sdk_version} from {task_sdk_rc}"
+
+ if confirm_action("Commit release to SVN?"):
+ # Need to commit from parent directory to include both airflow and
task-sdk if applicable
+ current_dir = os.getcwd()
+ os.chdir(svn_release_repo)
run_command(
- ["svn", "commit", "-m", f"Release Airflow {version} from {rc}"],
+ ["svn", "commit", "-m", commit_message],
check=True,
)
+ os.chdir(current_dir)
def remove_old_release(previous_release):
@@ -97,19 +136,46 @@ def verify_pypi_package(version):
run_command(["twine", "check", "*.whl", f"*{version}.tar.gz"],
check=True)
-def upload_to_pypi(version):
- if confirm_action("Upload to PyPI?"):
+def upload_to_pypi(version, task_sdk_version=None):
+ if confirm_action("Upload Airflow packages to PyPI?"):
run_command(
- ["twine", "upload", "-r", "pypi", "*.whl", f"*{version}.tar.gz"],
+ [
+ "twine",
+ "upload",
+ "-r",
+ "pypi",
+ "apache_airflow-*.whl",
+ f"apache_airflow-{version}.tar.gz",
+ f"apache_airflow_core-{version}.tar.gz",
+ "apache_airflow_core-*.whl",
+ ],
check=True,
)
- console_print("Packages pushed to production PyPI")
+ console_print("Airflow packages pushed to production PyPI")
console_print(
"Verify that the package looks good by downloading it and
installing it into a virtual "
"environment. The package download link is available at: "
"https://pypi.python.org/pypi/apache-airflow"
)
+ if task_sdk_version and confirm_action("Upload Task SDK packages to
PyPI?"):
+ run_command(
+ [
+ "twine",
+ "upload",
+ "-r",
+ "pypi",
+ "apache_airflow_task_sdk-*.whl",
+ f"apache_airflow_task_sdk-{task_sdk_version}.tar.gz",
+ ],
+ check=True,
+ )
+ console_print("Task SDK packages pushed to production PyPI")
+ console_print(
+ "Verify that the Task SDK package is available at: "
+ "https://pypi.python.org/pypi/apache-airflow-task-sdk"
+ )
+
def retag_constraints(release_candidate, version):
if confirm_action(f"Retag constraints for {release_candidate} as
{version}?"):
@@ -157,8 +223,8 @@ def tag_and_push_latest_constraint(version):
)
-def push_tag_for_final_version(version, release_candidate):
- if confirm_action(f"Push tag for final version {version}?"):
+def push_tag_for_final_version(version, release_candidate,
task_sdk_version=None, task_sdk_rc=None):
+ if confirm_action(f"Push Airflow tag for final version {version}?"):
console_print(
"""
This step should only be done now and not before, because it triggers
an automated
@@ -175,6 +241,28 @@ def push_tag_for_final_version(version, release_candidate):
)
run_command(["git", "push", "origin", "tag", f"{version}"], check=True)
+ if (
+ task_sdk_version
+ and task_sdk_rc
+ and confirm_action(f"Push Task SDK tag for final version
{task_sdk_version}?")
+ ):
+ confirm_action(
+ f"Confirm that Task SDK {task_sdk_version} is pushed to PyPI. Is
it pushed?", abort=True
+ )
+ run_command(["git", "checkout", f"task-sdk/{task_sdk_rc}"], check=True)
+ run_command(
+ [
+ "git",
+ "tag",
+ "-s",
+ f"task-sdk/{task_sdk_version}",
+ "-m",
+ f"Airflow Task SDK {task_sdk_version}",
+ ],
+ check=True,
+ )
+ run_command(["git", "push", "origin", "tag",
f"task-sdk/{task_sdk_version}"], check=True)
+
@release_management.command(
name="start-release",
@@ -182,23 +270,34 @@ def push_tag_for_final_version(version,
release_candidate):
help="Start the process of releasing an Airflow version. "
"This command will guide you through the release process. ",
)
[email protected]("--release-candidate", required=True)
[email protected]("--previous-release", required=True)
[email protected]("--release-candidate", required=True, help="Airflow release
candidate e.g. 3.0.5rc1")
[email protected]("--previous-release", required=True, help="Previous Airflow
release e.g. 3.0.4")
[email protected]("--task-sdk-release-candidate", required=False, help="Task SDK
release candidate e.g. 1.0.5rc1")
@option_answer
@option_dry_run
@option_verbose
-def airflow_release(release_candidate, previous_release):
+def airflow_release(release_candidate, previous_release,
task_sdk_release_candidate):
if "rc" not in release_candidate:
exit("Release candidate must contain 'rc'")
if "rc" in previous_release:
exit("Previous release must not contain 'rc'")
+
version = release_candidate[:-3]
+ task_sdk_version = None
+ if task_sdk_release_candidate:
+ if "rc" not in task_sdk_release_candidate:
+ exit("Task SDK release candidate must contain 'rc'")
+ task_sdk_version = task_sdk_release_candidate[:-3]
+
os.chdir(AIRFLOW_ROOT_PATH)
airflow_repo_root = os.getcwd()
console_print()
- console_print("Release candidate:", release_candidate)
- console_print("Release Version:", version)
- console_print("Previous release:", previous_release)
+ console_print("Airflow Release candidate:", release_candidate)
+ console_print("Airflow Release Version:", version)
+ console_print("Previous Airflow release:", previous_release)
+ if task_sdk_release_candidate:
+ console_print("Task SDK Release candidate:",
task_sdk_release_candidate)
+ console_print("Task SDK Release Version:", task_sdk_version)
console_print("Airflow repo root:", airflow_repo_root)
console_print()
console_print("Below are your git remotes. We will push to origin:")
@@ -224,7 +323,7 @@ def airflow_release(release_candidate, previous_release):
os.chdir(svn_release_repo)
# Create the version directory
- create_version_dir(version)
+ create_version_dir(version, task_sdk_version)
svn_release_version_dir = f"{svn_release_repo}/{version}"
console_print("SVN Release version dir:", svn_release_version_dir)
@@ -235,10 +334,10 @@ def airflow_release(release_candidate, previous_release):
confirm_action("Version directory does not exist. Do you want to
Continue?", abort=True)
# Copy artifacts to the version directory
- copy_artifacts_to_svn(release_candidate, svn_dev_repo)
+ copy_artifacts_to_svn(release_candidate, task_sdk_release_candidate,
svn_dev_repo, svn_release_repo)
# Commit the release to svn
- commit_release(version, release_candidate, svn_release_version_dir)
+ commit_release(version, task_sdk_version, release_candidate,
task_sdk_release_candidate, svn_release_repo)
confirm_action(
"Verify that the artifacts appear in
https://dist.apache.org/repos/dist/release/airflow/", abort=True
@@ -255,7 +354,7 @@ def airflow_release(release_candidate, previous_release):
verify_pypi_package(version)
# Upload to pypi
- upload_to_pypi(version)
+ upload_to_pypi(version, task_sdk_version)
# Change Directory to airflow
os.chdir(airflow_repo_root)
@@ -265,6 +364,6 @@ def airflow_release(release_candidate, previous_release):
tag_and_push_latest_constraint(version)
# Push tag for final version
- push_tag_for_final_version(version, release_candidate)
+ push_tag_for_final_version(version, release_candidate, task_sdk_version,
task_sdk_release_candidate)
console_print("Done!")
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 2e843a04af6..9c7b086c1dd 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
@@ -436,7 +436,10 @@ RELEASE_MANAGEMENT_PARAMETERS: dict[str, list[dict[str,
str | list[str]]]] = {
}
],
"breeze release-management start-release": [
- {"name": "Start release flags", "options": ["--release-candidate",
"--previous-release"]}
+ {
+ "name": "Start release flags",
+ "options": ["--release-candidate", "--previous-release",
"--task-sdk-release-candidate"],
+ }
],
"breeze release-management update-constraints": [
{