diff --git a/.dockerignore b/.dockerignore
index bf1cd0f3b5fb4..4e20efd84ac09 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -57,8 +57,8 @@
# This folder is for you if you want to add any packages to the docker context when you build your own
# docker image. most of other files and any new folder you add will be excluded by default
-# if you need other types of files - please add the extensions here.
!docker-context-files
+!constraints
# Avoid triggering context change on README change (new companies using Airflow)
# So please do not uncomment this line ;)
diff --git a/Dockerfile.ci b/Dockerfile.ci
index c65d45e249c78..22a5e95faa957 100644
--- a/Dockerfile.ci
+++ b/Dockerfile.ci
@@ -1268,6 +1268,7 @@ COPY setup.py ${AIRFLOW_SOURCES}/setup.py
COPY setup.cfg ${AIRFLOW_SOURCES}/setup.cfg
COPY airflow/__init__.py ${AIRFLOW_SOURCES}/airflow/
COPY generated/provider_dependencies.json ${AIRFLOW_SOURCES}/generated/
+COPY constraints/* ${AIRFLOW_SOURCES}/constraints/
COPY --from=scripts install_airflow.sh /scripts/docker/
diff --git a/constraints/README.md b/constraints/README.md
new file mode 100644
index 0000000000000..1ddfc1a3dfafc
--- /dev/null
+++ b/constraints/README.md
@@ -0,0 +1,55 @@
+
+
+Sometimes you might want to update dependencies of airflow in bulk, when working on related set of
+packages/dependencies. This might lead to excessive time needed to rebuild the image with new versions
+of dependencies (due to `pip` backtracking) and necessity to rebuild the image multiple times
+and solving conflicting dependencies.
+
+For development use only, you can store your own version of constraint files used during CI image build
+here and refer to them during building of the image using `--airflow-constraints-location constraints/constraints.txt`
+This allows you to iterate on dependencies without having to run `--upgrade-to-newer-dependencies` flag continuously.
+
+Typical workflow in this case is:
+
+* download and copy the constraint file to the folder (for example via
+[The GitHub Raw Link](https://raw.githubusercontent.com/apache/airflow/constraints-main/constraints-3.7.txt)
+* modify the constraint file in "constraints" folder
+* build the image using this command
+
+```bash
+breeze ci-image build --python 3.7 --airflow-constraints-location constraints/constraints-3.7txt
+```
+
+You can continue iterating and updating the constraint file (and rebuilding the image)
+while iterating, you can also manually add/update the dependencies and after you are done,
+you can regenerate the set of constraints based on your currently installed packages, using this command:
+
+```bash
+pip freeze | sort | \
+ grep -v "apache_airflow" | \
+ grep -v "apache-airflow==" | \
+ grep -v "@" | \
+ grep -v "/opt/airflow" > /opt/airflow/constraints/constraints-3.7.txt
+```
+
+If you are working with others on updating the dependencies, you can also commit the constraint
+file to the repository and then anyone else working on the same branch/fork, can use it for local
+image building (but the file should be removed before the branch you are working on is merged to
+the main branch).
diff --git a/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py b/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
index d37c3e313b1fd..78c8d7d850573 100644
--- a/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
@@ -35,6 +35,7 @@
option_additional_extras,
option_additional_pip_install_flags,
option_additional_python_deps,
+ option_airflow_constraints_location,
option_airflow_constraints_mode_ci,
option_airflow_constraints_reference_build,
option_answer,
@@ -188,6 +189,7 @@ def start_building(params: BuildCiParams):
@option_dev_apt_deps
@option_force_build
@option_python_image
+@option_airflow_constraints_location
@option_airflow_constraints_mode_ci
@option_airflow_constraints_reference_build
@option_tag_as_latest
diff --git a/dev/breeze/src/airflow_breeze/commands/ci_image_commands_config.py b/dev/breeze/src/airflow_breeze/commands/ci_image_commands_config.py
index 1ae0b85e9f798..5f1f9b01468eb 100644
--- a/dev/breeze/src/airflow_breeze/commands/ci_image_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/ci_image_commands_config.py
@@ -55,6 +55,7 @@
"options": [
"--builder",
"--install-providers-from-sources",
+ "--airflow-constraints-location",
"--airflow-constraints-mode",
"--airflow-constraints-reference",
"--python-image",
diff --git a/dev/breeze/src/airflow_breeze/commands/production_image_commands.py b/dev/breeze/src/airflow_breeze/commands/production_image_commands.py
index 66256b7e9e30c..ba644702c0e98 100644
--- a/dev/breeze/src/airflow_breeze/commands/production_image_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/production_image_commands.py
@@ -37,6 +37,7 @@
option_additional_runtime_apt_command,
option_additional_runtime_apt_deps,
option_additional_runtime_apt_env,
+ option_airflow_constraints_location,
option_airflow_constraints_mode_prod,
option_airflow_constraints_reference_build,
option_builder,
@@ -168,6 +169,7 @@ def prod_image():
@option_prepare_buildx_cache
@option_push
@option_empty_image
+@option_airflow_constraints_location
@option_airflow_constraints_mode_prod
@click.option(
"--installation-method",
diff --git a/dev/breeze/src/airflow_breeze/commands/production_image_commands_config.py b/dev/breeze/src/airflow_breeze/commands/production_image_commands_config.py
index 496166218323d..27b71426592b3 100644
--- a/dev/breeze/src/airflow_breeze/commands/production_image_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/production_image_commands_config.py
@@ -56,6 +56,7 @@
"--builder",
"--install-providers-from-sources",
"--airflow-extras",
+ "--airflow-constraints-location",
"--airflow-constraints-mode",
"--airflow-constraints-reference",
"--python-image",
diff --git a/dev/breeze/src/airflow_breeze/utils/common_options.py b/dev/breeze/src/airflow_breeze/utils/common_options.py
index 1d6459b7349e4..ee517fd163c0a 100644
--- a/dev/breeze/src/airflow_breeze/utils/common_options.py
+++ b/dev/breeze/src/airflow_breeze/utils/common_options.py
@@ -474,6 +474,14 @@ def _set_default_from_parent(ctx: click.core.Context, option: click.core.Option,
default=DEFAULT_AIRFLOW_CONSTRAINTS_BRANCH,
envvar="AIRFLOW_CONSTRAINTS_REFERENCE",
)
+option_airflow_constraints_location = click.option(
+ "--airflow-constraints-location",
+ type=str,
+ default="",
+ help="If specified, it is used instead of calculating reference to the constraint file. "
+ "It could be full remote URL to the location file, or local file placed in `docker-context-files` "
+ "(in this case it has to start with /opt/airflow/docker-context-files).",
+)
option_airflow_constraints_reference_build = click.option(
"--airflow-constraints-reference",
default=DEFAULT_AIRFLOW_CONSTRAINTS_BRANCH,
diff --git a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
index a08fdea87eae9..88d5912ea58db 100644
--- a/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
+++ b/dev/breeze/src/airflow_breeze/utils/docker_command_utils.py
@@ -86,6 +86,7 @@
("NOTICE", "/opt/airflow/NOTICE"),
("RELEASE_NOTES.rst", "/opt/airflow/RELEASE_NOTES.rst"),
("airflow", "/opt/airflow/airflow"),
+ ("constraints", "/opt/airflow/constraints"),
("provider_packages", "/opt/airflow/provider_packages"),
("dags", "/opt/airflow/dags"),
("dev", "/opt/airflow/dev"),
diff --git a/docker-context-files/.README.md b/docker-context-files/.README.md
index 2cafbb6dabc71..6623408d79986 100644
--- a/docker-context-files/.README.md
+++ b/docker-context-files/.README.md
@@ -21,12 +21,12 @@ This folder is part of the Docker context.
Most of other folders in Airflow are not part of the context in order to make the context smaller.
-The Production [Dockerfile](../Dockerfile) and the CI one [Dockerfile.ci](../Dockerfile.ci) copies
-the [docker-context-files](.) folder to the image context - in case of production image it copies it to
-the build segment, co content of the folder is available in the `/docker-context-file` folder inside
-the build image. You can store constraint files and wheel
+The Production [Dockerfile](../Dockerfile) image copies the [docker-context-files](.) folder to the
+image context forthe build segment, so content of the folder is available in the `/docker-context-files`
+folder inside the build image. You can store constraint files and wheel
packages there that you want to install as PYPI packages and refer to those packages using
-`--constraint-location` flag for constraints or by using `--install-packages-from-context` flag.
+`--airflow-constraints-location /docker-context-files/constraints.txt` flag for
+constraints or by using `--install-packages-from-context` flag.
By default, the content of this folder is .gitignored so that any binaries and files you put here are only
used for local builds and not committed to the repository.
diff --git a/images/breeze/output-commands-hash.txt b/images/breeze/output-commands-hash.txt
index 01ee85ccebb01..b56c3f38668a5 100644
--- a/images/breeze/output-commands-hash.txt
+++ b/images/breeze/output-commands-hash.txt
@@ -10,10 +10,10 @@ ci:get-workflow-info:01ee34c33ad62fa5dc33e0ac8773223f
ci:resource-check:1d4fe47dff9fc64ac1648ec4beb2d85c
ci:selective-check:3a085894f24cb909812fbc8253a21e13
ci:9884bf4cef3e70270068de89b9d5df2f
-ci-image:build:f8d0fafe7246ca7ac412df8c520908a3
+ci-image:build:3ffe4dd24ae7090415543e27d8504955
ci-image:pull:c16c6e57c748bfe9b365b4ffafb18472
ci-image:verify:aee88f55e8837028d19316356e29b009
-ci-image:0c727b84a764e09c54e461b30ad0410b
+ci-image:d53ee5067c46a6d8f3b21d0098c56ca2
cleanup:231de69d5f47ba29c883164e4575e310
compile-www-assets:c8a8c4f002f7246d0541897fc7c70313
exec:42bbd3c1659128b0341ae118c3482da2
@@ -31,10 +31,10 @@ k8s:status:2b8aa0b9597a1790c184c7b776ebd9c3
k8s:tests:dc44e907de908d1c4f11cf5d99915da1
k8s:upload-k8s-image:b012457bb6a98524859ecaf5746b4439
k8s:a04e7db8fb49c16a0633ac32f14463ec
-prod-image:build:b2c87adc30320ea70d1b32faf1500959
+prod-image:build:5d0fcf0f0b1f4a8d13378253214162d6
prod-image:pull:e3c89dd908fc44adf6e159c2950ebdd0
prod-image:verify:31bc5efada1d70a0a31990025db1a093
-prod-image:eb1ef0cf6e139d01ceb26f09ca3deaaa
+prod-image:2ac8e1e6b4afb259f00390ad0e90a06f
release-management:create-minor-branch:6a01066dce15e09fb269a8385626657c
release-management:generate-constraints:ae30d6ad49a1b2c15b61cb29080fd957
release-management:generate-issue-content-providers:f3c00ba74e3afc054fe29b65156740ac
diff --git a/images/breeze/output-commands.svg b/images/breeze/output-commands.svg
index 790b9fe55da49..784715a8cce83 100644
--- a/images/breeze/output-commands.svg
+++ b/images/breeze/output-commands.svg
@@ -35,8 +35,8 @@
.breeze-help-r1 { fill: #c5c8c6;font-weight: bold }
.breeze-help-r2 { fill: #c5c8c6 }
.breeze-help-r3 { fill: #d0b344;font-weight: bold }
-.breeze-help-r4 { fill: #68a0b3;font-weight: bold }
-.breeze-help-r5 { fill: #868887 }
+.breeze-help-r4 { fill: #868887 }
+.breeze-help-r5 { fill: #68a0b3;font-weight: bold }
.breeze-help-r6 { fill: #98a84b;font-weight: bold }
.breeze-help-r7 { fill: #8d7b39 }
@@ -190,50 +190,50 @@
-Usage: breeze [OPTIONS] COMMAND [ARGS]...
+Usage: breeze [OPTIONS] COMMAND [ARGS]...
-╭─ Basic flags ────────────────────────────────────────────────────────────────────────────────────────────────────────╮
-│--python-pPython major/minor version used in Airflow image for images.(>3.7< | 3.8 | 3.9 | 3.10)│
-│[default: 3.7] │
-│--backend-bDatabase backend to use.(>sqlite< | mysql | postgres | mssql)[default: sqlite]│
-│--postgres-version-PVersion of Postgres used.(>11< | 12 | 13 | 14 | 15)[default: 11]│
-│--mysql-version-MVersion of MySQL used.(>5.7< | 8)[default: 5.7]│
-│--mssql-version-SVersion of MsSQL used.(>2017-latest< | 2019-latest)[default: 2017-latest]│
-│--integrationIntegration(s) to enable when running (can be more than one). │
-│(all | all-testable | cassandra | celery | kerberos | mongo | otel | pinot | statsd | │
-│statsd | trino) │
-│--forward-credentials-fForward local credentials to container when running.│
-│--db-reset-dReset DB when entering the container.│
-│--max-timeMaximum time that the command should take - if it takes longer, the command will fail.│
-│(INTEGER RANGE) │
-│--github-repository-gGitHub repository used to pull, push run images.(TEXT)[default: apache/airflow]│
-╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
-╭─ Common options ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
-│--verbose-vPrint verbose information about performed steps.│
-│--dry-run-DIf dry-run is set, commands are only printed, not executed.│
-│--answer-aForce answer to questions.(y | n | q | yes | no | quit)│
-│--help-hShow this message and exit.│
-╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
-╭─ Basic developer commands ───────────────────────────────────────────────────────────────────────────────────────────╮
-│start-airflow Enter breeze environment and starts all Airflow components in the tmux session. Compile assets │
-│if contents of www directory changed. │
-│static-checks Run static checks. │
-│build-docs Build documentation in the container. │
-│stop Stop running breeze environment. │
-│shell Enter breeze environment. this is the default command use when no other is selected. │
-│exec Joins the interactive shell of running airflow container. │
-│compile-www-assetsCompiles www assets. │
-│cleanup Cleans the cache of parameters, docker cache and optionally built CI/PROD images. │
-╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
-╭─ Advanced command groups ────────────────────────────────────────────────────────────────────────────────────────────╮
-│testing Tools that developers can use to run tests │
-│ci-image Tools that developers can use to manually manage CI images │
-│k8s Tools that developers use to run Kubernetes tests │
-│prod-image Tools that developers can use to manually manage PROD images │
-│setup Tools that developers can use to configure Breeze │
-│release-management Tools that release managers can use to prepare and manage Airflow releases │
-│ci Tools that CI workflows use to cleanup/manage CI environment │
-╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Basic flags ────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│--python-pPython major/minor version used in Airflow image for images.(>3.7< | 3.8 | 3.9 | 3.10)│
+│[default: 3.7] │
+│--backend-bDatabase backend to use.(>sqlite< | mysql | postgres | mssql)[default: sqlite]│
+│--postgres-version-PVersion of Postgres used.(>11< | 12 | 13 | 14 | 15)[default: 11]│
+│--mysql-version-MVersion of MySQL used.(>5.7< | 8)[default: 5.7]│
+│--mssql-version-SVersion of MsSQL used.(>2017-latest< | 2019-latest)[default: 2017-latest]│
+│--integrationIntegration(s) to enable when running (can be more than one). │
+│(all | all-testable | cassandra | celery | kerberos | mongo | otel | pinot | statsd | │
+│statsd | trino) │
+│--forward-credentials-fForward local credentials to container when running.│
+│--db-reset-dReset DB when entering the container.│
+│--max-timeMaximum time that the command should take - if it takes longer, the command will fail.│
+│(INTEGER RANGE) │
+│--github-repository-gGitHub repository used to pull, push run images.(TEXT)[default: apache/airflow]│
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Common options ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│--verbose-vPrint verbose information about performed steps.│
+│--dry-run-DIf dry-run is set, commands are only printed, not executed.│
+│--answer-aForce answer to questions.(y | n | q | yes | no | quit)│
+│--help-hShow this message and exit.│
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Basic developer commands ───────────────────────────────────────────────────────────────────────────────────────────╮
+│start-airflow Enter breeze environment and starts all Airflow components in the tmux session. Compile assets │
+│if contents of www directory changed. │
+│static-checks Run static checks. │
+│build-docs Build documentation in the container. │
+│stop Stop running breeze environment. │
+│shell Enter breeze environment. this is the default command use when no other is selected. │
+│exec Joins the interactive shell of running airflow container. │
+│compile-www-assetsCompiles www assets. │
+│cleanup Cleans the cache of parameters, docker cache and optionally built CI/PROD images. │
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Advanced command groups ────────────────────────────────────────────────────────────────────────────────────────────╮
+│testing Tools that developers can use to run tests │
+│ci-image Tools that developers can use to manually manage CI images │
+│k8s Tools that developers use to run Kubernetes tests │
+│prod-image Tools that developers can use to manually manage PROD images │
+│setup Tools that developers can use to configure Breeze │
+│release-management Tools that release managers can use to prepare and manage Airflow releases │
+│ci Tools that CI workflows use to cleanup/manage CI environment │
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
diff --git a/images/breeze/output_ci-image.svg b/images/breeze/output_ci-image.svg
index bf1df9347a162..3025e6e470c36 100644
--- a/images/breeze/output_ci-image.svg
+++ b/images/breeze/output_ci-image.svg
@@ -35,8 +35,8 @@
.breeze-ci-image-r1 { fill: #c5c8c6;font-weight: bold }
.breeze-ci-image-r2 { fill: #c5c8c6 }
.breeze-ci-image-r3 { fill: #d0b344;font-weight: bold }
-.breeze-ci-image-r4 { fill: #68a0b3;font-weight: bold }
-.breeze-ci-image-r5 { fill: #868887 }
+.breeze-ci-image-r4 { fill: #868887 }
+.breeze-ci-image-r5 { fill: #68a0b3;font-weight: bold }
.breeze-ci-image-r6 { fill: #98a84b;font-weight: bold }
@@ -93,18 +93,18 @@
-Usage: breeze ci-image [OPTIONS] COMMAND [ARGS]...
+Usage: breeze ci-image [OPTIONS] COMMAND [ARGS]...
-Tools that developers can use to manually manage CI images
+Tools that developers can use to manually manage CI images
-╭─ Common options ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
-│--help-hShow this message and exit.│
-╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
-╭─ CI Image tools ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
-│build Build CI image. Include building multiple images for all python versions. │
-│pull Pull and optionally verify CI images - possibly in parallel for all Python versions. │
-│verify Verify CI image. │
-╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ Common options ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│--help-hShow this message and exit.│
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+╭─ CI Image tools ─────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│build Build CI image. Include building multiple images for all python versions. │
+│pull Pull and optionally verify CI images - possibly in parallel for all Python versions. │
+│verify Verify CI image. │
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
diff --git a/images/breeze/output_ci-image_build.svg b/images/breeze/output_ci-image_build.svg
index 944a6af1da53e..fb6299cb70534 100644
--- a/images/breeze/output_ci-image_build.svg
+++ b/images/breeze/output_ci-image_build.svg
@@ -1,4 +1,4 @@
-