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 2d9bb46cd6 Use `uv` as packaging tool used in CI builds (#37692)
2d9bb46cd6 is described below
commit 2d9bb46cd60583c56603141fe555e7e065950a6a
Author: Jarek Potiuk <[email protected]>
AuthorDate: Mon Feb 26 13:10:31 2024 +0100
Use `uv` as packaging tool used in CI builds (#37692)
The `uv` tool released in Feb 2024 by ruff creators provides a
way faster drop-in replacement to `pip` and we are using it now
in our CI, when it can bring significant speed improvements (and
soon possibly more features).
This PR replaces `pip install` and `pip uninstall` with equivalent
`uv pip install` and `uv pip uninstall` commands, controlled by
a single `AIRFLOW_USE_UV` ARG. In CI images it is set to "true" so
CI images are prepared using UV, but PROD images (which are also
used during CI tests) are built using pip. This way we can get
both - stability and compliance for user-facing `pip` installation
and speed and new features coming from `uv`.
---
.github/workflows/ci.yml | 2 +-
Dockerfile | 169 ++++++++++++++------
Dockerfile.ci | 175 +++++++++++++++------
dev/breeze/doc/ci/02_images.md | 3 +
dev/breeze/doc/images/output_ci-image_build.svg | 96 +++++------
dev/breeze/doc/images/output_ci-image_build.txt | 2 +-
dev/breeze/doc/images/output_prod-image_build.svg | 18 +--
dev/breeze/doc/images/output_prod-image_build.txt | 2 +-
.../airflow_breeze/commands/ci_image_commands.py | 11 ++
.../commands/ci_image_commands_config.py | 1 +
.../commands/production_image_commands_config.py | 4 +-
.../commands/release_management_commands.py | 2 +
.../src/airflow_breeze/params/build_ci_params.py | 2 +
.../src/airflow_breeze/params/build_prod_params.py | 2 +-
docs/docker-stack/build-arg-ref.rst | 4 +
scripts/docker/common.sh | 71 ++++++++-
scripts/docker/entrypoint_ci.sh | 32 ++--
scripts/docker/install_additional_dependencies.sh | 12 +-
scripts/docker/install_airflow.sh | 22 ++-
...install_airflow_dependencies_from_branch_tip.sh | 12 +-
.../docker/install_from_docker_context_files.sh | 23 ++-
scripts/docker/install_mssql.sh | 1 -
scripts/docker/install_pip_version.sh | 7 +-
scripts/docker/install_pipx_tools.sh | 3 +-
scripts/in_container/_in_container_utils.sh | 37 +++++
tests/cli/commands/test_webserver_command.py | 7 +-
tests/providers/weaviate/hooks/test_weaviate.py | 9 +-
.../providers/weaviate/operators/test_weaviate.py | 4 +-
28 files changed, 506 insertions(+), 227 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bc730277ce..409dfaf44d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -175,7 +175,7 @@ jobs:
# We only push CI cache as PROD cache usually does not gain as much from
fresh cache because
# it uses prepared airflow and provider packages that invalidate the cache
anyway most of the time
push-early-buildx-cache-to-github-registry:
- timeout-minutes: 50
+ timeout-minutes: 110
name: "Push Early Image Cache"
runs-on: ${{fromJSON(needs.build-info.outputs.runs-on)}}
needs:
diff --git a/Dockerfile b/Dockerfile
index 4ac935925f..f5efda7abe 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -49,6 +49,8 @@ ARG AIRFLOW_VERSION="2.8.1"
ARG PYTHON_BASE_IMAGE="python:3.8-slim-bookworm"
ARG AIRFLOW_PIP_VERSION=24.0
+ARG AIRFLOW_UV_VERSION=0.1.10
+ARG AIRFLOW_USE_UV="false"
ARG AIRFLOW_IMAGE_REPOSITORY="https://github.com/apache/airflow"
ARG
AIRFLOW_IMAGE_README_URL="https://raw.githubusercontent.com/apache/airflow/main/docs/docker-stack/README.md"
@@ -336,7 +338,6 @@ set -euo pipefail
common::get_colors
declare -a packages
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
: "${INSTALL_MSSQL_CLIENT:?Should be true or false}"
@@ -416,14 +417,13 @@ COPY <<"EOF" /install_pip_version.sh
#!/usr/bin/env bash
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
-common::install_pip_version
+common::install_packaging_tool
EOF
# The content below is automatically copied from
scripts/docker/install_airflow_dependencies_from_branch_tip.sh
@@ -436,7 +436,6 @@ COPY <<"EOF"
/install_airflow_dependencies_from_branch_tip.sh
: "${AIRFLOW_BRANCH:?Should be set}"
: "${INSTALL_MYSQL_CLIENT:?Should be true or false}"
: "${INSTALL_POSTGRES_CLIENT:?Should be true or false}"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
function install_airflow_dependencies_from_branch_tip() {
echo
@@ -452,26 +451,27 @@ function install_airflow_dependencies_from_branch_tip() {
# dependencies that we can cache and reuse when installing airflow using
constraints and latest
# pyproject.toml in the next step (when we install regular airflow).
set -x
- pip install --root-user-action ignore \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
"apache-airflow[${AIRFLOW_EXTRAS}] @
https://github.com/${AIRFLOW_REPO}/archive/${AIRFLOW_BRANCH}.tar.gz"
- common::install_pip_version
+ common::install_packaging_tool
# Uninstall airflow and providers to keep only the dependencies. In the
future when
# planned https://github.com/pypa/pip/issues/11440 is implemented in pip
we might be able to use this
# flag and skip the remove step.
- pip freeze | grep apache-airflow-providers | xargs pip uninstall --yes
2>/dev/null || true
+ ${PACKAGING_TOOL_CMD} freeze | grep apache-airflow-providers | xargs
${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} 2>/dev/null || true
set +x
echo
echo "${COLOR_BLUE}Uninstalling just airflow. Dependencies remain. Now
target airflow can be reinstalled using mostly cached
dependencies${COLOR_RESET}"
echo
- pip uninstall --yes apache-airflow || true
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} apache-airflow ||
true
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow_dependencies_from_branch_tip
EOF
@@ -481,6 +481,10 @@ COPY <<"EOF" /common.sh
#!/usr/bin/env bash
set -euo pipefail
+: "${AIRFLOW_PIP_VERSION:?Should be set}"
+: "${AIRFLOW_UV_VERSION:?Should be set}"
+: "${AIRFLOW_USE_UV:?Should be set}"
+
function common::get_colors() {
COLOR_BLUE=$'\e[34m'
COLOR_GREEN=$'\e[32m'
@@ -494,6 +498,40 @@ function common::get_colors() {
export COLOR_YELLOW
}
+function common::get_packaging_tool() {
+ ## IMPORTANT: IF YOU MODIFY THIS FUNCTION YOU SHOULD ALSO MODIFY
CORRESPONDING FUNCTION IN
+ ## `scripts/in_container/_in_container_utils.sh`
+ if [[ ${AIRFLOW_USE_UV} == "true" ]]; then
+ echo
+ echo "${COLOR_BLUE}Using 'uv' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL="uv"
+ export PACKAGING_TOOL_CMD="uv pip"
+ export EXTRA_INSTALL_FLAGS=""
+ export EXTRA_UNINSTALL_FLAGS=""
+ export RESOLUTION_HIGHEST_FLAG="--resolution highest"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--resolution lowest-direct"
+ # We need to lie about VIRTUAL_ENV to make uv works
+ # Until https://github.com/astral-sh/uv/issues/1396 is fixed
+ # In case we are running user installation, we need to set VIRTUAL_ENV
to user's home + .local
+ if [[ ${PIP_USER=} == "true" ]]; then
+ VIRTUAL_ENV="${HOME}/.local"
+ else
+ VIRTUAL_ENV=$(python -c "import sys; print(sys.prefix)")
+ fi
+ export VIRTUAL_ENV
+ else
+ echo
+ echo "${COLOR_BLUE}Using 'pip' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL="pip"
+ export PACKAGING_TOOL_CMD="pip"
+ export EXTRA_INSTALL_FLAGS="--root-user-action ignore"
+ export EXTRA_UNINSTALL_FLAGS="--yes"
+ export RESOLUTION_HIGHEST_FLAG="--upgrade-strategy eager"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--upgrade --upgrade-strategy
only-if-needed"
+ fi
+}
function common::get_airflow_version_specification() {
if [[ -z ${AIRFLOW_VERSION_SPECIFICATION=}
@@ -529,20 +567,41 @@ function common::get_constraints_location() {
fi
}
-function common::show_pip_version_and_location() {
+function common::show_packaging_tool_version_and_location() {
echo "PATH=${PATH}"
- echo "pip on path: $(which pip)"
- echo "Using pip: $(pip --version)"
+ if [[ ${PACKAGING_TOOL} == "pip" ]]; then
+ echo "${COLOR_BLUE}Using 'pip' to install Airflow${COLOR_RESET}"
+ echo "pip on path: $(which pip)"
+ echo "Using pip: $(pip --version)"
+ else
+ echo "${COLOR_BLUE}Using 'uv' to install Airflow${COLOR_RESET}"
+ echo "uv on path: $(which uv)"
+ echo "Using uv: $(uv --version)"
+ fi
}
-function common::install_pip_version() {
+function common::install_packaging_tool() {
echo
echo "${COLOR_BLUE}Installing pip version
${AIRFLOW_PIP_VERSION}${COLOR_RESET}"
echo
if [[ ${AIRFLOW_PIP_VERSION} =~ .*https.* ]]; then
- pip install --disable-pip-version-check "pip @ ${AIRFLOW_PIP_VERSION}"
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check "pip
@ ${AIRFLOW_PIP_VERSION}"
else
- pip install --disable-pip-version-check "pip==${AIRFLOW_PIP_VERSION}"
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"pip==${AIRFLOW_PIP_VERSION}"
+ fi
+ if [[ ${AIRFLOW_USE_UV} == "true" ]]; then
+ echo
+ echo "${COLOR_BLUE}Installing uv version
${AIRFLOW_UV_VERSION}${COLOR_RESET}"
+ echo
+ if [[ ${AIRFLOW_UV_VERSION} =~ .*https.* ]]; then
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"uv @ ${AIRFLOW_UV_VERSION}"
+ else
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"uv==${AIRFLOW_UV_VERSION}"
+ fi
fi
mkdir -p "${HOME}/.local/bin"
}
@@ -601,8 +660,6 @@ COPY <<"EOF" /install_from_docker_context_files.sh
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
function install_airflow_and_providers_from_docker_context_files(){
if [[ ${INSTALL_MYSQL_CLIENT} != "true" ]]; then
AIRFLOW_EXTRAS=${AIRFLOW_EXTRAS/mysql,}
@@ -619,7 +676,7 @@ function
install_airflow_and_providers_from_docker_context_files(){
fi
# shellcheck disable=SC2206
- local pip_flags=(
+ local packaging_flags=(
# Don't quote this -- if it is empty we don't want it to create an
# empty array element
--find-links="file:///docker-context-files"
@@ -669,7 +726,7 @@ function
install_airflow_and_providers_from_docker_context_files(){
echo
# force reinstall all airflow + provider packages with constraints
found in
set -x
- pip install "${pip_flags[@]}" --root-user-action ignore --upgrade \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"${packaging_flags[@]}" --upgrade \
${ADDITIONAL_PIP_INSTALL_FLAGS} --constraint
"${local_constraints_file}" \
${reinstalling_apache_airflow_package}
${reinstalling_apache_airflow_providers_packages}
set +x
@@ -678,7 +735,7 @@ function
install_airflow_and_providers_from_docker_context_files(){
echo "${COLOR_BLUE}Installing docker-context-files packages with
constraints from GitHub${COLOR_RESET}"
echo
set -x
- pip install "${pip_flags[@]}" --root-user-action ignore \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"${packaging_flags[@]}" \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
--constraint "${AIRFLOW_CONSTRAINTS_LOCATION}" \
${reinstalling_apache_airflow_package}
${reinstalling_apache_airflow_providers_packages}
@@ -689,17 +746,16 @@ function
install_airflow_and_providers_from_docker_context_files(){
echo "${COLOR_BLUE}Installing docker-context-files packages without
constraints${COLOR_RESET}"
echo
set -x
- pip install "${pip_flags[@]}" --root-user-action ignore \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"${packaging_flags[@]}" \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${reinstalling_apache_airflow_package}
${reinstalling_apache_airflow_providers_packages}
set +x
fi
- common::install_pip_version
+ common::install_packaging_tool
pip check
}
function install_all_other_packages_from_docker_context_files() {
-
echo
echo "${COLOR_BLUE}Force re-installing all other package from local files
without dependencies${COLOR_RESET}"
echo
@@ -709,22 +765,22 @@ function
install_all_other_packages_from_docker_context_files() {
grep -v apache_airflow | grep -v apache-airflow || true)
if [[ -n "${reinstalling_other_packages}" ]]; then
set -x
- pip install ${ADDITIONAL_PIP_INSTALL_FLAGS} \
- --root-user-action ignore --force-reinstall --no-deps --no-index
${reinstalling_other_packages}
- common::install_pip_version
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
${ADDITIONAL_PIP_INSTALL_FLAGS} \
+ --force-reinstall --no-deps --no-index
${reinstalling_other_packages}
+ common::install_packaging_tool
set +x
fi
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow_and_providers_from_docker_context_files
-common::show_pip_version_and_location
install_all_other_packages_from_docker_context_files
EOF
@@ -734,8 +790,6 @@ COPY <<"EOF" /install_airflow.sh
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
function install_airflow() {
# Coherence check for editable installation mode.
if [[ ${AIRFLOW_INSTALLATION_METHOD} != "." && \
@@ -760,22 +814,21 @@ function install_airflow() {
echo "${COLOR_BLUE}Remove airflow and all provider packages installed
before potentially${COLOR_RESET}"
echo
set -x
- pip freeze | grep apache-airflow | xargs pip uninstall --yes
2>/dev/null || true
+ ${PACKAGING_TOOL_CMD} freeze | grep apache-airflow | xargs
${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} 2>/dev/null || true
set +x
echo
echo "${COLOR_BLUE}Installing all packages with eager upgrade with
${AIRFLOW_INSTALL_EDITABLE_FLAG} mode${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore \
- --upgrade --upgrade-strategy eager \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_HIGHEST_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
\
${EAGER_UPGRADE_ADDITIONAL_REQUIREMENTS=}
set +x
- common::install_pip_version
+ common::install_packaging_tool
echo
- echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
+ echo "${COLOR_BLUE}Running '${PACKAGING_TOOL} check'${COLOR_RESET}"
echo
pip check
else
@@ -783,17 +836,17 @@ function install_airflow() {
echo "${COLOR_BLUE}Installing all packages with constraints and
upgrade if needed${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore ${AIRFLOW_INSTALL_EDITABLE_FLAG}
\
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
\
--constraint "${AIRFLOW_CONSTRAINTS_LOCATION}" || true
- common::install_pip_version
+ common::install_packaging_tool
# then upgrade if needed without using constraints to account for new
limits in pyproject.toml
- pip install --root-user-action ignore --upgrade --upgrade-strategy
only-if-needed \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_LOWEST_DIRECT_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -804,10 +857,11 @@ function install_airflow() {
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow
EOF
@@ -819,7 +873,6 @@ set -euo pipefail
: "${UPGRADE_TO_NEWER_DEPENDENCIES:?Should be true or false}"
: "${ADDITIONAL_PYTHON_DEPS:?Should be set}"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
@@ -829,10 +882,10 @@ function install_additional_dependencies() {
echo "${COLOR_BLUE}Installing additional dependencies while upgrading
to newer dependencies${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore --upgrade --upgrade-strategy
eager \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_HIGHEST_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${ADDITIONAL_PYTHON_DEPS} ${EAGER_UPGRADE_ADDITIONAL_REQUIREMENTS=}
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -843,10 +896,10 @@ function install_additional_dependencies() {
echo "${COLOR_BLUE}Installing additional dependencies upgrading only
if needed${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore --upgrade --upgrade-strategy
only-if-needed \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
"${RESOLUTION_LOWEST_DIRECT_FLAG}" \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${ADDITIONAL_PYTHON_DEPS}
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -856,10 +909,11 @@ function install_additional_dependencies() {
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_additional_dependencies
EOF
@@ -1246,6 +1300,8 @@ ARG INSTALL_MYSQL_CLIENT_TYPE="mariadb"
ARG INSTALL_MSSQL_CLIENT="true"
ARG INSTALL_POSTGRES_CLIENT="true"
ARG AIRFLOW_PIP_VERSION
+ARG AIRFLOW_UV_VERSION
+ARG AIRFLOW_USE_UV
ENV INSTALL_MYSQL_CLIENT=${INSTALL_MYSQL_CLIENT} \
INSTALL_MYSQL_CLIENT_TYPE=${INSTALL_MYSQL_CLIENT_TYPE} \
@@ -1327,6 +1383,8 @@ RUN if [[ -f /docker-context-files/pip.conf ]]; then \
ARG ADDITIONAL_PIP_INSTALL_FLAGS=""
ENV AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION} \
+ AIRFLOW_UV_VERSION=${AIRFLOW_UV_VERSION} \
+ AIRFLOW_USE_UV=${AIRFLOW_USE_UV} \
AIRFLOW_PRE_CACHED_PIP_PACKAGES=${AIRFLOW_PRE_CACHED_PIP_PACKAGES} \
AIRFLOW_VERSION=${AIRFLOW_VERSION} \
AIRFLOW_INSTALLATION_METHOD=${AIRFLOW_INSTALLATION_METHOD} \
@@ -1342,7 +1400,6 @@ ENV AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION} \
AIRFLOW_CONSTRAINTS_LOCATION=${AIRFLOW_CONSTRAINTS_LOCATION} \
DEFAULT_CONSTRAINTS_BRANCH=${DEFAULT_CONSTRAINTS_BRANCH} \
PATH=${PATH}:${AIRFLOW_USER_HOME_DIR}/.local/bin \
- AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION} \
PIP_PROGRESS_BAR=${PIP_PROGRESS_BAR} \
ADDITIONAL_PIP_INSTALL_FLAGS=${ADDITIONAL_PIP_INSTALL_FLAGS} \
AIRFLOW_USER_HOME_DIR=${AIRFLOW_USER_HOME_DIR} \
@@ -1458,12 +1515,16 @@ LABEL org.apache.airflow.distro="debian" \
ARG PYTHON_BASE_IMAGE
ARG AIRFLOW_PIP_VERSION
+ARG AIRFLOW_UV_VERSION
+ARG AIRFLOW_USE_UV
ENV PYTHON_BASE_IMAGE=${PYTHON_BASE_IMAGE} \
# Make sure noninteractive debian install is used and language variables
set
DEBIAN_FRONTEND=noninteractive LANGUAGE=C.UTF-8 LANG=C.UTF-8
LC_ALL=C.UTF-8 \
LC_CTYPE=C.UTF-8 LC_MESSAGES=C.UTF-8 LD_LIBRARY_PATH=/usr/local/lib \
- AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION}
+ AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION} \
+ AIRFLOW_UV_VERSION=${AIRFLOW_UV_VERSION} \
+ AIRFLOW_USE_UV=${AIRFLOW_USE_UV}
ARG RUNTIME_APT_DEPS=""
ARG ADDITIONAL_RUNTIME_APT_DEPS=""
@@ -1503,10 +1564,14 @@ ENV PATH="${AIRFLOW_USER_HOME_DIR}/.local/bin:${PATH}" \
AIRFLOW_USER_HOME_DIR=${AIRFLOW_USER_HOME_DIR} \
AIRFLOW_HOME=${AIRFLOW_HOME}
-# THE 3 LINES ARE ONLY NEEDED IN ORDER TO MAKE PYMSSQL BUILD WORK WITH LATEST
CYTHON
+# THE 7 LINES ARE ONLY NEEDED IN ORDER TO MAKE PYMSSQL BUILD WORK WITH LATEST
CYTHON
# AND SHOULD BE REMOVED WHEN WORKAROUND IN install_mssql.sh IS REMOVED
ARG AIRFLOW_PIP_VERSION=24.0
-ENV AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION}
+ARG AIRFLOW_UV_VERSION=0.1.10
+ARG AIRFLOW_USE_UV="false"
+ENV AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION} \
+ AIRFLOW_UV_VERSION=${AIRFLOW_UV_VERSION} \
+ AIRFLOW_USE_UV=${AIRFLOW_USE_UV}
COPY --from=scripts common.sh /scripts/docker/
# Only copy mysql/mssql installation scripts for now - so that changing the
other
diff --git a/Dockerfile.ci b/Dockerfile.ci
index f5044a2ef9..8e927094e8 100644
--- a/Dockerfile.ci
+++ b/Dockerfile.ci
@@ -296,7 +296,6 @@ set -euo pipefail
common::get_colors
declare -a packages
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
: "${INSTALL_MSSQL_CLIENT:?Should be true or false}"
@@ -376,14 +375,13 @@ COPY <<"EOF" /install_pip_version.sh
#!/usr/bin/env bash
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
-common::install_pip_version
+common::install_packaging_tool
EOF
# The content below is automatically copied from
scripts/docker/install_airflow_dependencies_from_branch_tip.sh
@@ -396,7 +394,6 @@ COPY <<"EOF"
/install_airflow_dependencies_from_branch_tip.sh
: "${AIRFLOW_BRANCH:?Should be set}"
: "${INSTALL_MYSQL_CLIENT:?Should be true or false}"
: "${INSTALL_POSTGRES_CLIENT:?Should be true or false}"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
function install_airflow_dependencies_from_branch_tip() {
echo
@@ -412,26 +409,27 @@ function install_airflow_dependencies_from_branch_tip() {
# dependencies that we can cache and reuse when installing airflow using
constraints and latest
# pyproject.toml in the next step (when we install regular airflow).
set -x
- pip install --root-user-action ignore \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
"apache-airflow[${AIRFLOW_EXTRAS}] @
https://github.com/${AIRFLOW_REPO}/archive/${AIRFLOW_BRANCH}.tar.gz"
- common::install_pip_version
+ common::install_packaging_tool
# Uninstall airflow and providers to keep only the dependencies. In the
future when
# planned https://github.com/pypa/pip/issues/11440 is implemented in pip
we might be able to use this
# flag and skip the remove step.
- pip freeze | grep apache-airflow-providers | xargs pip uninstall --yes
2>/dev/null || true
+ ${PACKAGING_TOOL_CMD} freeze | grep apache-airflow-providers | xargs
${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} 2>/dev/null || true
set +x
echo
echo "${COLOR_BLUE}Uninstalling just airflow. Dependencies remain. Now
target airflow can be reinstalled using mostly cached
dependencies${COLOR_RESET}"
echo
- pip uninstall --yes apache-airflow || true
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} apache-airflow ||
true
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow_dependencies_from_branch_tip
EOF
@@ -441,6 +439,10 @@ COPY <<"EOF" /common.sh
#!/usr/bin/env bash
set -euo pipefail
+: "${AIRFLOW_PIP_VERSION:?Should be set}"
+: "${AIRFLOW_UV_VERSION:?Should be set}"
+: "${AIRFLOW_USE_UV:?Should be set}"
+
function common::get_colors() {
COLOR_BLUE=$'\e[34m'
COLOR_GREEN=$'\e[32m'
@@ -454,6 +456,40 @@ function common::get_colors() {
export COLOR_YELLOW
}
+function common::get_packaging_tool() {
+ ## IMPORTANT: IF YOU MODIFY THIS FUNCTION YOU SHOULD ALSO MODIFY
CORRESPONDING FUNCTION IN
+ ## `scripts/in_container/_in_container_utils.sh`
+ if [[ ${AIRFLOW_USE_UV} == "true" ]]; then
+ echo
+ echo "${COLOR_BLUE}Using 'uv' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL="uv"
+ export PACKAGING_TOOL_CMD="uv pip"
+ export EXTRA_INSTALL_FLAGS=""
+ export EXTRA_UNINSTALL_FLAGS=""
+ export RESOLUTION_HIGHEST_FLAG="--resolution highest"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--resolution lowest-direct"
+ # We need to lie about VIRTUAL_ENV to make uv works
+ # Until https://github.com/astral-sh/uv/issues/1396 is fixed
+ # In case we are running user installation, we need to set VIRTUAL_ENV
to user's home + .local
+ if [[ ${PIP_USER=} == "true" ]]; then
+ VIRTUAL_ENV="${HOME}/.local"
+ else
+ VIRTUAL_ENV=$(python -c "import sys; print(sys.prefix)")
+ fi
+ export VIRTUAL_ENV
+ else
+ echo
+ echo "${COLOR_BLUE}Using 'pip' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL="pip"
+ export PACKAGING_TOOL_CMD="pip"
+ export EXTRA_INSTALL_FLAGS="--root-user-action ignore"
+ export EXTRA_UNINSTALL_FLAGS="--yes"
+ export RESOLUTION_HIGHEST_FLAG="--upgrade-strategy eager"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--upgrade --upgrade-strategy
only-if-needed"
+ fi
+}
function common::get_airflow_version_specification() {
if [[ -z ${AIRFLOW_VERSION_SPECIFICATION=}
@@ -489,20 +525,41 @@ function common::get_constraints_location() {
fi
}
-function common::show_pip_version_and_location() {
+function common::show_packaging_tool_version_and_location() {
echo "PATH=${PATH}"
- echo "pip on path: $(which pip)"
- echo "Using pip: $(pip --version)"
+ if [[ ${PACKAGING_TOOL} == "pip" ]]; then
+ echo "${COLOR_BLUE}Using 'pip' to install Airflow${COLOR_RESET}"
+ echo "pip on path: $(which pip)"
+ echo "Using pip: $(pip --version)"
+ else
+ echo "${COLOR_BLUE}Using 'uv' to install Airflow${COLOR_RESET}"
+ echo "uv on path: $(which uv)"
+ echo "Using uv: $(uv --version)"
+ fi
}
-function common::install_pip_version() {
+function common::install_packaging_tool() {
echo
echo "${COLOR_BLUE}Installing pip version
${AIRFLOW_PIP_VERSION}${COLOR_RESET}"
echo
if [[ ${AIRFLOW_PIP_VERSION} =~ .*https.* ]]; then
- pip install --disable-pip-version-check "pip @ ${AIRFLOW_PIP_VERSION}"
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check "pip
@ ${AIRFLOW_PIP_VERSION}"
else
- pip install --disable-pip-version-check "pip==${AIRFLOW_PIP_VERSION}"
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"pip==${AIRFLOW_PIP_VERSION}"
+ fi
+ if [[ ${AIRFLOW_USE_UV} == "true" ]]; then
+ echo
+ echo "${COLOR_BLUE}Installing uv version
${AIRFLOW_UV_VERSION}${COLOR_RESET}"
+ echo
+ if [[ ${AIRFLOW_UV_VERSION} =~ .*https.* ]]; then
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"uv @ ${AIRFLOW_UV_VERSION}"
+ else
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"uv==${AIRFLOW_UV_VERSION}"
+ fi
fi
mkdir -p "${HOME}/.local/bin"
}
@@ -548,7 +605,7 @@ function install_pipx_tools() {
echo "${COLOR_BLUE}Installing pipx tools${COLOR_RESET}"
echo
# Make sure PIPX is installed in latest version
- pip install --root-user-action ignore --upgrade "pipx>=1.2.1"
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
"pipx>=1.2.1"
if [[ $(uname -m) != "aarch64" ]]; then
# Do not install mssql-cli for ARM
# Install all the tools we need available in command line but without
impacting the current environment
@@ -562,6 +619,7 @@ function install_pipx_tools() {
}
common::get_colors
+common::get_packaging_tool
install_pipx_tools
EOF
@@ -572,8 +630,6 @@ COPY <<"EOF" /install_airflow.sh
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
function install_airflow() {
# Coherence check for editable installation mode.
if [[ ${AIRFLOW_INSTALLATION_METHOD} != "." && \
@@ -598,22 +654,21 @@ function install_airflow() {
echo "${COLOR_BLUE}Remove airflow and all provider packages installed
before potentially${COLOR_RESET}"
echo
set -x
- pip freeze | grep apache-airflow | xargs pip uninstall --yes
2>/dev/null || true
+ ${PACKAGING_TOOL_CMD} freeze | grep apache-airflow | xargs
${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} 2>/dev/null || true
set +x
echo
echo "${COLOR_BLUE}Installing all packages with eager upgrade with
${AIRFLOW_INSTALL_EDITABLE_FLAG} mode${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore \
- --upgrade --upgrade-strategy eager \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_HIGHEST_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
\
${EAGER_UPGRADE_ADDITIONAL_REQUIREMENTS=}
set +x
- common::install_pip_version
+ common::install_packaging_tool
echo
- echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
+ echo "${COLOR_BLUE}Running '${PACKAGING_TOOL} check'${COLOR_RESET}"
echo
pip check
else
@@ -621,17 +676,17 @@ function install_airflow() {
echo "${COLOR_BLUE}Installing all packages with constraints and
upgrade if needed${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore ${AIRFLOW_INSTALL_EDITABLE_FLAG}
\
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
\
--constraint "${AIRFLOW_CONSTRAINTS_LOCATION}" || true
- common::install_pip_version
+ common::install_packaging_tool
# then upgrade if needed without using constraints to account for new
limits in pyproject.toml
- pip install --root-user-action ignore --upgrade --upgrade-strategy
only-if-needed \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_LOWEST_DIRECT_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -642,10 +697,11 @@ function install_airflow() {
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow
EOF
@@ -657,7 +713,6 @@ set -euo pipefail
: "${UPGRADE_TO_NEWER_DEPENDENCIES:?Should be true or false}"
: "${ADDITIONAL_PYTHON_DEPS:?Should be set}"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
@@ -667,10 +722,10 @@ function install_additional_dependencies() {
echo "${COLOR_BLUE}Installing additional dependencies while upgrading
to newer dependencies${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore --upgrade --upgrade-strategy
eager \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_HIGHEST_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${ADDITIONAL_PYTHON_DEPS} ${EAGER_UPGRADE_ADDITIONAL_REQUIREMENTS=}
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -681,10 +736,10 @@ function install_additional_dependencies() {
echo "${COLOR_BLUE}Installing additional dependencies upgrading only
if needed${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore --upgrade --upgrade-strategy
only-if-needed \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
"${RESOLUTION_LOWEST_DIRECT_FLAG}" \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${ADDITIONAL_PYTHON_DEPS}
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -694,10 +749,11 @@ function install_additional_dependencies() {
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_additional_dependencies
EOF
@@ -893,8 +949,12 @@ function check_boto_upgrade() {
echo
echo "${COLOR_BLUE}Upgrading boto3, botocore to latest version to run
Amazon tests with them${COLOR_RESET}"
echo
- pip uninstall --root-user-action ignore aiobotocore s3fs -y || true
- pip install --root-user-action ignore --upgrade boto3 botocore
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} aiobotocore s3fs
|| true
+ # We need to include oss2 as dependency as otherwise jmespath will be
bumped and it will not pass
+ # the pip check test, Similarly gcloud-aio-auth limit is needed to be
included as it bumps cryptography
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade boto3
botocore "oss2>=2.14.0" "gcloud-aio-auth>=4.0.0,<5.0.0"
pip check
}
@@ -903,25 +963,31 @@ function check_pydantic() {
echo
echo "${COLOR_YELLOW}Reinstalling airflow from local sources to
account for pyproject.toml changes${COLOR_RESET}"
echo
- pip install --root-user-action ignore -e .
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} -e .
echo
echo "${COLOR_YELLOW}Remove pydantic and 3rd party libraries that
depend on it${COLOR_RESET}"
echo
- pip uninstall --root-user-action ignore pydantic aws-sam-translator
openai pyiceberg qdrant-client cfn-lint -y
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} pydantic
aws-sam-translator openai \
+ pyiceberg qdrant-client cfn-lint weaviate-client
pip check
elif [[ ${PYDANTIC=} == "v1" ]]; then
echo
echo "${COLOR_YELLOW}Reinstalling airflow from local sources to
account for pyproject.toml changes${COLOR_RESET}"
echo
- pip install --root-user-action ignore -e .
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} -e .
echo
- echo "${COLOR_YELLOW}Uninstalling pyicberg which is not compatible
with Pydantic 1${COLOR_RESET}"
+ echo "${COLOR_YELLOW}Uninstalling dependencies which are not
compatible with Pydantic 1${COLOR_RESET}"
echo
- pip uninstall pyiceberg -y
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} pyiceberg
waeviate-client
echo
echo "${COLOR_YELLOW}Downgrading Pydantic to < 2${COLOR_RESET}"
echo
- pip install --upgrade "pydantic<2.0.0"
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
"pydantic<2.0.0"
pip check
else
echo
@@ -939,7 +1005,8 @@ function check_download_sqlalchemy() {
echo
echo "${COLOR_BLUE}Downgrading sqlalchemy to minimum supported version:
${min_sqlalchemy_version}${COLOR_RESET}"
echo
- pip install --root-user-action ignore
"sqlalchemy==${min_sqlalchemy_version}"
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"sqlalchemy==${min_sqlalchemy_version}"
pip check
}
@@ -951,7 +1018,8 @@ function check_download_pendulum() {
echo
echo "${COLOR_BLUE}Downgrading pendulum to minimum supported version:
${min_pendulum_version}${COLOR_RESET}"
echo
- pip install --root-user-action ignore "pendulum==${min_pendulum_version}"
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"pendulum==${min_pendulum_version}"
pip check
}
@@ -1042,10 +1110,14 @@ ENV DEV_APT_COMMAND=${DEV_APT_COMMAND} \
COPY --from=scripts install_os_dependencies.sh /scripts/docker/
RUN bash /scripts/docker/install_os_dependencies.sh dev
-# THE 3 LINES ARE ONLY NEEDED IN ORDER TO MAKE PYMSSQL BUILD WORK WITH LATEST
CYTHON
+# THE 7 LINES ARE ONLY NEEDED IN ORDER TO MAKE PYMSSQL BUILD WORK WITH LATEST
CYTHON
# AND SHOULD BE REMOVED WHEN WORKAROUND IN install_mssql.sh IS REMOVED
ARG AIRFLOW_PIP_VERSION=24.0
-ENV AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION}
+ARG AIRFLOW_UV_VERSION=0.1.10
+ARG AIRFLOW_USE_UV="true"
+ENV AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION} \
+ AIRFLOW_UV_VERSION=${AIRFLOW_UV_VERSION} \
+ AIRFLOW_USE_UV=${AIRFLOW_USE_UV}
COPY --from=scripts common.sh /scripts/docker/
# Only copy mysql/mssql installation scripts for now - so that changing the
other
@@ -1108,9 +1180,13 @@ ARG DEFAULT_CONSTRAINTS_BRANCH="constraints-main"
ARG AIRFLOW_CI_BUILD_EPOCH="10"
ARG AIRFLOW_PRE_CACHED_PIP_PACKAGES="true"
ARG AIRFLOW_PIP_VERSION=24.0
+ARG AIRFLOW_UV_VERSION=0.1.10
+ARG AIRFLOW_USE_UV="true"
# Setup PIP
# By default PIP install run without cache to make image smaller
ARG PIP_NO_CACHE_DIR="true"
+# By default UV install run without cache to make image smaller
+ARG UV_NO_CACHE="true"
# By default PIP has progress bar but you can disable it.
ARG PIP_PROGRESS_BAR="on"
# Optimizing installation of Cassandra driver (in case there are no prebuilt
wheels which is the
@@ -1138,6 +1214,8 @@ ENV AIRFLOW_REPO=${AIRFLOW_REPO}\
AIRFLOW_PRE_CACHED_PIP_PACKAGES=${AIRFLOW_PRE_CACHED_PIP_PACKAGES} \
AIRFLOW_VERSION=${AIRFLOW_VERSION} \
AIRFLOW_PIP_VERSION=${AIRFLOW_PIP_VERSION} \
+ AIRFLOW_UV_VERSION=${AIRFLOW_UV_VERSION} \
+ AIRFLOW_USE_UV=${AIRFLOW_USE_UV} \
# In the CI image we always:
# * install MySQL, MsSQL
# * install airflow from current sources, not from PyPI package
@@ -1153,6 +1231,7 @@ ENV AIRFLOW_REPO=${AIRFLOW_REPO}\
AIRFLOW_VERSION_SPECIFICATION="" \
PIP_NO_CACHE_DIR=${PIP_NO_CACHE_DIR} \
PIP_PROGRESS_BAR=${PIP_PROGRESS_BAR} \
+ UV_NO_CACHE=${UV_NO_CACHE} \
ADDITIONAL_PIP_INSTALL_FLAGS=${ADDITIONAL_PIP_INSTALL_FLAGS} \
CASS_DRIVER_BUILD_CONCURRENCY=${CASS_DRIVER_BUILD_CONCURRENCY} \
CASS_DRIVER_NO_CYTHON=${CASS_DRIVER_NO_CYTHON}
diff --git a/dev/breeze/doc/ci/02_images.md b/dev/breeze/doc/ci/02_images.md
index 4c6fc2c016..7807d94b1e 100644
--- a/dev/breeze/doc/ci/02_images.md
+++ b/dev/breeze/doc/ci/02_images.md
@@ -428,6 +428,7 @@ can be used for CI images:
| `DEPENDENCIES_EPOCH_NUMBER` | `2`
| increasing this number will reinstall all apt
dependencies
|
| `ADDITIONAL_PIP_INSTALL_FLAGS` |
| additional `pip` flags passed to the
installation commands (except when reinstalling `pip` itself)
|
| `PIP_NO_CACHE_DIR` | `true`
| if true, then no pip cache will be stored
|
+| `UV_NO_CACHE` | `true`
| if true, then no uv cache will be stored
|
| `HOME` | `/root`
| Home directory of the root user (CI image has
root user as default)
|
| `AIRFLOW_HOME` | `/root/airflow`
| Airflow's HOME (that's where logs and sqlite
databases are stored)
|
| `AIRFLOW_SOURCES` | `/opt/airflow`
| Mounted sources of Airflow
|
@@ -447,6 +448,8 @@ can be used for CI images:
| `ADDITIONAL_DEV_APT_DEPS` |
| Additional apt dev dependencies installed in
the first part of the image
|
| `ADDITIONAL_DEV_APT_ENV` |
| Additional env variables defined when
installing dev deps
|
| `AIRFLOW_PIP_VERSION` | `24.0`
| PIP version used.
|
+| `AIRFLOW_UV_VERSION` | `0.1.10`
| UV version used.
|
+| `AIRFLOW_USE_UV` | `true`
| Whether to use UV for installation.
|
| `PIP_PROGRESS_BAR` | `on`
| Progress bar for PIP installation
|
Here are some examples of how CI images can built manually. CI is always
diff --git a/dev/breeze/doc/images/output_ci-image_build.svg
b/dev/breeze/doc/images/output_ci-image_build.svg
index 17ea15e9e9..f617eb05e7 100644
--- a/dev/breeze/doc/images/output_ci-image_build.svg
+++ b/dev/breeze/doc/images/output_ci-image_build.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 2343.6"
xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 2368.0"
xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@@ -43,7 +43,7 @@
<defs>
<clipPath id="breeze-ci-image-build-clip-terminal">
- <rect x="0" y="0" width="1463.0" height="2292.6" />
+ <rect x="0" y="0" width="1463.0" height="2317.0" />
</clipPath>
<clipPath id="breeze-ci-image-build-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -324,9 +324,12 @@
<clipPath id="breeze-ci-image-build-line-92">
<rect x="0" y="2246.3" width="1464" height="24.65"/>
</clipPath>
+<clipPath id="breeze-ci-image-build-line-93">
+ <rect x="0" y="2270.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="2341.6" rx="8"/><text
class="breeze-ci-image-build-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Command: ci-image build</text>
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1"
x="1" y="1" width="1480" height="2366" rx="8"/><text
class="breeze-ci-image-build-title" fill="#c5c8c6" text-anchor="middle" x="740"
y="27">Command: ci-image build</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -387,49 +390,50 @@
</text><text class="breeze-ci-image-build-r5" x="0" y="1191.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-48)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1191.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-48)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1191.2" textLength="85.4"
clip-path="url(#breeze-ci-image-build-line-48)">-python</text><text
class="breeze-ci-image-build-r4" x="122" y="1191.2" textLength="73.2" clip-pa
[...]
</text><text class="breeze-ci-image-build-r5" x="0" y="1215.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-49)">│</text><text
class="breeze-ci-image-build-r1" x="439.2" y="1215.6" textLength="1000.4"
clip-path="url(#breeze-ci-image-build-line-49)">something like: python:VERSION-slim-bookworm.                            
[...]
</text><text class="breeze-ci-image-build-r5" x="0" y="1240" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-50)">│</text><text
class="breeze-ci-image-build-r7" x="439.2" y="1240" textLength="1000.4"
clip-path="url(#breeze-ci-image-build-line-50)">(TEXT)                                     
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1264.4"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-51)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1264.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-51)">
-</text><text class="breeze-ci-image-build-r5" x="0" y="1288.8"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-52)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1288.8" textLength="597.8"
clip-path="url(#breeze-ci-image-build-line-52)"> Selecting constraint location (for power users) </text><text
class="breeze-ci-image-build-r5" x="622.2" y="1288.8" textLength="817.4"
clip-path="url(#breeze-ci-image-build-line-52)">────────── [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1313.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-53)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1313.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-53)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1313.2" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-53)">-airflow</text><text
class="breeze-ci-image-build-r4" x="134.2" y="1313.2" textLength="256.2" cli
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1337.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-54)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1337.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-54)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1337.6" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-54)">-airflow</text><text
class="breeze-ci-image-build-r4" x="134.2" y="1337.6" textLength="207.4" cli
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1362" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-55)">│</text><text
class="breeze-ci-image-build-r7" x="451.4" y="1362" textLength="866.2"
clip-path="url(#breeze-ci-image-build-line-55)">(constraints-source-providers | constraints | constraints-no-providers)</text><text
class="breeze-ci-image-build-r5" x="1451.8" y="1362" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-55)">│</text>< [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1386.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-56)">│</text><text
class="breeze-ci-image-build-r5" x="451.4" y="1386.4" textLength="866.2"
clip-path="url(#breeze-ci-image-build-line-56)">[default: constraints-source-providers]                              
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1410.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-57)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1410.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-57)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1410.8" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-57)">-airflow</text><text
class="breeze-ci-image-build-r4" x="134.2" y="1410.8" textLength="268.4" cli
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1435.2"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-58)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1435.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-58)">
-</text><text class="breeze-ci-image-build-r5" x="0" y="1459.6"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-59)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1459.6" textLength="634.4"
clip-path="url(#breeze-ci-image-build-line-59)"> Choosing dependencies and extras (for power users) </text><text
class="breeze-ci-image-build-r5" x="658.8" y="1459.6" textLength="780.8"
clip-path="url(#breeze-ci-image-build-line-59)">── [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1484" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-60)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1484" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-60)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1484" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-60)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1484" textLength="183" clip-path
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1508.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-61)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1508.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-61)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1508.4" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-61)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1508.4" textLength="146.4" [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1532.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-62)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1532.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-62)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1532.8" textLength="48.8"
clip-path="url(#breeze-ci-image-build-line-62)">-dev</text><text
class="breeze-ci-image-build-r4" x="85.4" y="1532.8" textLength="109.8"
clip-pat [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1557.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-63)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1557.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-63)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1557.2" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-63)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1557.2" textLength="158.6" [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1581.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-64)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1581.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-64)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1581.6" textLength="48.8"
clip-path="url(#breeze-ci-image-build-line-64)">-dev</text><text
class="breeze-ci-image-build-r4" x="85.4" y="1581.6" textLength="146.4"
clip-pat [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1606" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-65)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1606" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-65)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1606" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-65)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1606" textLength="195.2" clip-pa
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1630.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-66)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1630.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-66)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1630.4" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-66)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1630.4" textLength="146.4" [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1654.8"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-67)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1654.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-67)">
-</text><text class="breeze-ci-image-build-r5" x="0" y="1679.2"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-68)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1679.2" textLength="268.4"
clip-path="url(#breeze-ci-image-build-line-68)"> Backtracking options </text><text
class="breeze-ci-image-build-r5" x="292.8" y="1679.2" textLength="1146.8"
clip-path="url(#breeze-ci-image-build-line-68)">────────────────────────────────────────────────────────
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1703.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-69)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1703.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-69)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1703.6" textLength="73.2"
clip-path="url(#breeze-ci-image-build-line-69)">-build</text><text
class="breeze-ci-image-build-r4" x="109.8" y="1703.6" textLength="195.2" clip-
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1728" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-70)">│</text><text
class="breeze-ci-image-build-r1" x="549" y="1728" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-70)">backtracking problems.                                  
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1752.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-71)">│</text><text
class="breeze-ci-image-build-r7" x="549" y="1752.4" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-71)">(INTEGER)                                     
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1776.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-72)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1776.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-72)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1776.8" textLength="73.2"
clip-path="url(#breeze-ci-image-build-line-72)">-eager</text><text
class="breeze-ci-image-build-r4" x="109.8" y="1776.8" textLength="390.4" clip-
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1801.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-73)">│</text><text
class="breeze-ci-image-build-r1" x="549" y="1801.2" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-73)">(see `breeze ci find-backtracking-candidates`).                          </text><text
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1825.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-74)">│</text><text
class="breeze-ci-image-build-r7" x="549" y="1825.6" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-74)">(TEXT)                                     &#
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1850" textLength="1464"
clip-path="url(#breeze-ci-image-build-line-75)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1850" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-75)">
-</text><text class="breeze-ci-image-build-r5" x="0" y="1874.4"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-76)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1874.4" textLength="622.2"
clip-path="url(#breeze-ci-image-build-line-76)"> Preparing cache and push (for maintainers and CI) </text><text
class="breeze-ci-image-build-r5" x="646.6" y="1874.4" textLength="793"
clip-path="url(#breeze-ci-image-build-line-76)"> [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1898.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-77)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1898.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-77)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1898.8" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-77)">-builder</text><text
class="breeze-ci-image-build-r1" x="341.6" y="1898.8" textLength="756.4" cli
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1923.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-78)">│</text><text
class="breeze-ci-image-build-r5" x="341.6" y="1923.2" textLength="756.4"
clip-path="url(#breeze-ci-image-build-line-78)">[default: autodetect]                                 
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1947.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-79)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1947.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-79)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1947.6" textLength="109.8"
clip-path="url(#breeze-ci-image-build-line-79)">-platform</text><text
class="breeze-ci-image-build-r1" x="341.6" y="1947.6" textLength="329.4" c [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1972" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-80)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1972" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-80)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1972" textLength="61"
clip-path="url(#breeze-ci-image-build-line-80)">-push</text><text
class="breeze-ci-image-build-r1" x="341.6" y="1972" textLength="353.8"
clip-path="url(# [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="1996.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-81)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1996.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-81)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1996.4" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-81)">-prepare</text><text
class="breeze-ci-image-build-r4" x="134.2" y="1996.4" textLength="158.6" cli
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2020.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-82)">│</text><text
class="breeze-ci-image-build-r1" x="341.6" y="2020.8" textLength="1098"
clip-path="url(#breeze-ci-image-build-line-82)">image).                                     
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2045.2"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-83)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="2045.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-83)">
-</text><text class="breeze-ci-image-build-r5" x="0" y="2069.6"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-84)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="2069.6" textLength="280.6"
clip-path="url(#breeze-ci-image-build-line-84)"> Github authentication </text><text
class="breeze-ci-image-build-r5" x="305" y="2069.6" textLength="1134.6"
clip-path="url(#breeze-ci-image-build-line-84)">─────────────────────────────────────────────────────────
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2094" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-85)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2094" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-85)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2094" textLength="85.4"
clip-path="url(#breeze-ci-image-build-line-85)">-github</text><text
class="breeze-ci-image-build-r4" x="122" y="2094" textLength="134.2"
clip-path="url [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2118.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-86)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2118.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-86)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2118.4" textLength="85.4"
clip-path="url(#breeze-ci-image-build-line-86)">-github</text><text
class="breeze-ci-image-build-r4" x="122" y="2118.4" textLength="73.2" clip-pa
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2142.8"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-87)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="2142.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-87)">
-</text><text class="breeze-ci-image-build-r5" x="0" y="2167.2"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-88)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="2167.2" textLength="195.2"
clip-path="url(#breeze-ci-image-build-line-88)"> Common options </text><text
class="breeze-ci-image-build-r5" x="219.6" y="2167.2" textLength="1220"
clip-path="url(#breeze-ci-image-build-line-88)">────────────────────────────────────────────────────────────────
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2191.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-89)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2191.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-89)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2191.6" textLength="85.4"
clip-path="url(#breeze-ci-image-build-line-89)">-answer</text><text
class="breeze-ci-image-build-r6" x="158.6" y="2191.6" textLength="24.4" clip-
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2216" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-90)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2216" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-90)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2216" textLength="48.8"
clip-path="url(#breeze-ci-image-build-line-90)">-dry</text><text
class="breeze-ci-image-build-r4" x="85.4" y="2216" textLength="48.8"
clip-path="url(#b [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2240.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-91)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2240.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-91)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2240.4" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-91)">-verbose</text><text
class="breeze-ci-image-build-r6" x="158.6" y="2240.4" textLength="24.4" clip
[...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2264.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-92)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2264.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-92)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2264.8" textLength="61"
clip-path="url(#breeze-ci-image-build-line-92)">-help</text><text
class="breeze-ci-image-build-r6" x="158.6" y="2264.8" textLength="24.4"
clip-path [...]
-</text><text class="breeze-ci-image-build-r5" x="0" y="2289.2"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-93)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="2289.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-93)">
+</text><text class="breeze-ci-image-build-r5" x="0" y="1264.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-51)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1264.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-51)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1264.4" textLength="48.8"
clip-path="url(#breeze-ci-image-build-line-51)">-use</text><text
class="breeze-ci-image-build-r4" x="85.4" y="1264.4" textLength="36.6"
clip-path [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1288.8"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-52)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1288.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-52)">
+</text><text class="breeze-ci-image-build-r5" x="0" y="1313.2"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-53)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1313.2" textLength="597.8"
clip-path="url(#breeze-ci-image-build-line-53)"> Selecting constraint location (for power users) </text><text
class="breeze-ci-image-build-r5" x="622.2" y="1313.2" textLength="817.4"
clip-path="url(#breeze-ci-image-build-line-53)">────────── [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1337.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-54)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1337.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-54)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1337.6" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-54)">-airflow</text><text
class="breeze-ci-image-build-r4" x="134.2" y="1337.6" textLength="256.2" cli
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1362" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-55)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1362" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-55)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1362" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-55)">-airflow</text><text
class="breeze-ci-image-build-r4" x="134.2" y="1362" textLength="207.4"
clip-path=" [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1386.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-56)">│</text><text
class="breeze-ci-image-build-r7" x="451.4" y="1386.4" textLength="866.2"
clip-path="url(#breeze-ci-image-build-line-56)">(constraints-source-providers | constraints | constraints-no-providers)</text><text
class="breeze-ci-image-build-r5" x="1451.8" y="1386.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-56)">│</ [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1410.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-57)">│</text><text
class="breeze-ci-image-build-r5" x="451.4" y="1410.8" textLength="866.2"
clip-path="url(#breeze-ci-image-build-line-57)">[default: constraints-source-providers]                              
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1435.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-58)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1435.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-58)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1435.2" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-58)">-airflow</text><text
class="breeze-ci-image-build-r4" x="134.2" y="1435.2" textLength="268.4" cli
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1459.6"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-59)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1459.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-59)">
+</text><text class="breeze-ci-image-build-r5" x="0" y="1484" textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-60)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1484" textLength="634.4"
clip-path="url(#breeze-ci-image-build-line-60)"> Choosing dependencies and extras (for power users) </text><text
class="breeze-ci-image-build-r5" x="658.8" y="1484" textLength="780.8"
clip-path="url(#breeze-ci-image-build-line-60)">──────── [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1508.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-61)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1508.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-61)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1508.4" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-61)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1508.4" textLength="183" c [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1532.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-62)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1532.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-62)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1532.8" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-62)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1532.8" textLength="146.4" [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1557.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-63)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1557.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-63)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1557.2" textLength="48.8"
clip-path="url(#breeze-ci-image-build-line-63)">-dev</text><text
class="breeze-ci-image-build-r4" x="85.4" y="1557.2" textLength="109.8"
clip-pat [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1581.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-64)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1581.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-64)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1581.6" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-64)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1581.6" textLength="158.6" [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1606" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-65)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1606" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-65)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1606" textLength="48.8"
clip-path="url(#breeze-ci-image-build-line-65)">-dev</text><text
class="breeze-ci-image-build-r4" x="85.4" y="1606" textLength="146.4"
clip-path="url(# [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1630.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-66)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1630.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-66)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1630.4" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-66)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1630.4" textLength="195.2" [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1654.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-67)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1654.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-67)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1654.8" textLength="134.2"
clip-path="url(#breeze-ci-image-build-line-67)">-additional</text><text
class="breeze-ci-image-build-r4" x="170.8" y="1654.8" textLength="146.4" [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1679.2"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-68)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1679.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-68)">
+</text><text class="breeze-ci-image-build-r5" x="0" y="1703.6"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-69)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1703.6" textLength="268.4"
clip-path="url(#breeze-ci-image-build-line-69)"> Backtracking options </text><text
class="breeze-ci-image-build-r5" x="292.8" y="1703.6" textLength="1146.8"
clip-path="url(#breeze-ci-image-build-line-69)">────────────────────────────────────────────────────────
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1728" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-70)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1728" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-70)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1728" textLength="73.2"
clip-path="url(#breeze-ci-image-build-line-70)">-build</text><text
class="breeze-ci-image-build-r4" x="109.8" y="1728" textLength="195.2"
clip-path="ur [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1752.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-71)">│</text><text
class="breeze-ci-image-build-r1" x="549" y="1752.4" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-71)">backtracking problems.                                  
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1776.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-72)">│</text><text
class="breeze-ci-image-build-r7" x="549" y="1776.8" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-72)">(INTEGER)                                     
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1801.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-73)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1801.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-73)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1801.2" textLength="73.2"
clip-path="url(#breeze-ci-image-build-line-73)">-eager</text><text
class="breeze-ci-image-build-r4" x="109.8" y="1801.2" textLength="390.4" clip-
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1825.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-74)">│</text><text
class="breeze-ci-image-build-r1" x="549" y="1825.6" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-74)">(see `breeze ci find-backtracking-candidates`).                          </text><text
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1850" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-75)">│</text><text
class="breeze-ci-image-build-r7" x="549" y="1850" textLength="890.6"
clip-path="url(#breeze-ci-image-build-line-75)">(TEXT)                                      
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1874.4"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-76)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="1874.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-76)">
+</text><text class="breeze-ci-image-build-r5" x="0" y="1898.8"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-77)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="1898.8" textLength="622.2"
clip-path="url(#breeze-ci-image-build-line-77)"> Preparing cache and push (for maintainers and CI) </text><text
class="breeze-ci-image-build-r5" x="646.6" y="1898.8" textLength="793"
clip-path="url(#breeze-ci-image-build-line-77)"> [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1923.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-78)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1923.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-78)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1923.2" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-78)">-builder</text><text
class="breeze-ci-image-build-r1" x="341.6" y="1923.2" textLength="756.4" cli
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1947.6"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-79)">│</text><text
class="breeze-ci-image-build-r5" x="341.6" y="1947.6" textLength="756.4"
clip-path="url(#breeze-ci-image-build-line-79)">[default: autodetect]                                 
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1972" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-80)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1972" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-80)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1972" textLength="109.8"
clip-path="url(#breeze-ci-image-build-line-80)">-platform</text><text
class="breeze-ci-image-build-r1" x="341.6" y="1972" textLength="329.4"
clip-path [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="1996.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-81)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="1996.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-81)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="1996.4" textLength="61"
clip-path="url(#breeze-ci-image-build-line-81)">-push</text><text
class="breeze-ci-image-build-r1" x="341.6" y="1996.4" textLength="353.8"
clip-pat [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2020.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-82)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2020.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-82)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2020.8" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-82)">-prepare</text><text
class="breeze-ci-image-build-r4" x="134.2" y="2020.8" textLength="158.6" cli
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2045.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-83)">│</text><text
class="breeze-ci-image-build-r1" x="341.6" y="2045.2" textLength="1098"
clip-path="url(#breeze-ci-image-build-line-83)">image).                                     
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2069.6"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-84)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="2069.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-84)">
+</text><text class="breeze-ci-image-build-r5" x="0" y="2094" textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-85)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="2094" textLength="280.6"
clip-path="url(#breeze-ci-image-build-line-85)"> Github authentication </text><text
class="breeze-ci-image-build-r5" x="305" y="2094" textLength="1134.6"
clip-path="url(#breeze-ci-image-build-line-85)">───────────────────────────────────────────────────────────────
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2118.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-86)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2118.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-86)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2118.4" textLength="85.4"
clip-path="url(#breeze-ci-image-build-line-86)">-github</text><text
class="breeze-ci-image-build-r4" x="122" y="2118.4" textLength="134.2" clip-p
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2142.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-87)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2142.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-87)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2142.8" textLength="85.4"
clip-path="url(#breeze-ci-image-build-line-87)">-github</text><text
class="breeze-ci-image-build-r4" x="122" y="2142.8" textLength="73.2" clip-pa
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2167.2"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-88)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="2167.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-88)">
+</text><text class="breeze-ci-image-build-r5" x="0" y="2191.6"
textLength="24.4"
clip-path="url(#breeze-ci-image-build-line-89)">╭─</text><text
class="breeze-ci-image-build-r5" x="24.4" y="2191.6" textLength="195.2"
clip-path="url(#breeze-ci-image-build-line-89)"> Common options </text><text
class="breeze-ci-image-build-r5" x="219.6" y="2191.6" textLength="1220"
clip-path="url(#breeze-ci-image-build-line-89)">────────────────────────────────────────────────────────────────
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2216" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-90)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2216" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-90)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2216" textLength="85.4"
clip-path="url(#breeze-ci-image-build-line-90)">-answer</text><text
class="breeze-ci-image-build-r6" x="158.6" y="2216" textLength="24.4"
clip-path="ur [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2240.4"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-91)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2240.4" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-91)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2240.4" textLength="48.8"
clip-path="url(#breeze-ci-image-build-line-91)">-dry</text><text
class="breeze-ci-image-build-r4" x="85.4" y="2240.4" textLength="48.8"
clip-path [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2264.8"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-92)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2264.8" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-92)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2264.8" textLength="97.6"
clip-path="url(#breeze-ci-image-build-line-92)">-verbose</text><text
class="breeze-ci-image-build-r6" x="158.6" y="2264.8" textLength="24.4" clip
[...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2289.2"
textLength="12.2" clip-path="url(#breeze-ci-image-build-line-93)">│</text><text
class="breeze-ci-image-build-r4" x="24.4" y="2289.2" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-93)">-</text><text
class="breeze-ci-image-build-r4" x="36.6" y="2289.2" textLength="61"
clip-path="url(#breeze-ci-image-build-line-93)">-help</text><text
class="breeze-ci-image-build-r6" x="158.6" y="2289.2" textLength="24.4"
clip-path [...]
+</text><text class="breeze-ci-image-build-r5" x="0" y="2313.6"
textLength="1464"
clip-path="url(#breeze-ci-image-build-line-94)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-ci-image-build-r1" x="1464" y="2313.6" textLength="12.2"
clip-path="url(#breeze-ci-image-build-line-94)">
</text>
</g>
</g>
diff --git a/dev/breeze/doc/images/output_ci-image_build.txt
b/dev/breeze/doc/images/output_ci-image_build.txt
index b4ab5dac08..b59fb9fc0b 100644
--- a/dev/breeze/doc/images/output_ci-image_build.txt
+++ b/dev/breeze/doc/images/output_ci-image_build.txt
@@ -1 +1 @@
-d2ef2733519d945c8cfd4fed63a43f24
+f535999147ac00393852eb3b28d7125b
diff --git a/dev/breeze/doc/images/output_prod-image_build.svg
b/dev/breeze/doc/images/output_prod-image_build.svg
index 2e6599bb57..be7de879be 100644
--- a/dev/breeze/doc/images/output_prod-image_build.svg
+++ b/dev/breeze/doc/images/output_prod-image_build.svg
@@ -393,15 +393,15 @@
</text><text class="breeze-prod-image-build-r5" x="0" y="752"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-30)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="752" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-30)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="752" textLength="97.6"
clip-path="url(#breeze-prod-image-build-line-30)">-include</text><text
class="breeze-prod-image-build-r4" x="134.2" y="752" textLength="195.2" c [...]
</text><text class="breeze-prod-image-build-r5" x="0" y="776.4"
textLength="1464"
clip-path="url(#breeze-prod-image-build-line-31)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-prod-image-build-r1" x="1464" y="776.4" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-31)">
</text><text class="breeze-prod-image-build-r5" x="0" y="800.8"
textLength="24.4"
clip-path="url(#breeze-prod-image-build-line-32)">╭─</text><text
class="breeze-prod-image-build-r5" x="24.4" y="800.8" textLength="512.4"
clip-path="url(#breeze-prod-image-build-line-32)"> Advanced build options (for power users) </text><text
class="breeze-prod-image-build-r5" x="536.8" y="800.8" textLength="902.8"
clip-path="url(#breeze-prod-image-build-line-32)">──────── [...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="825.2"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-33)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="825.2" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-33)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="825.2" textLength="85.4"
clip-path="url(#breeze-prod-image-build-line-33)">-debian</text><text
class="breeze-prod-image-build-r4" x="122" y="825.2" textLength="97. [...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="849.6"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-34)">│</text><text
class="breeze-prod-image-build-r7" x="439.2" y="849.6" textLength="793"
clip-path="url(#breeze-prod-image-build-line-34)">(bookworm | bullseye)                                &
[...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="874"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-35)">│</text><text
class="breeze-prod-image-build-r5" x="439.2" y="874" textLength="793"
clip-path="url(#breeze-prod-image-build-line-35)">[default: bookworm]                                  
[...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="898.4"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-36)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="898.4" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-36)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="898.4" textLength="85.4"
clip-path="url(#breeze-prod-image-build-line-36)">-python</text><text
class="breeze-prod-image-build-r4" x="122" y="898.4" textLength="73. [...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="922.8"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-37)">│</text><text
class="breeze-prod-image-build-r1" x="439.2" y="922.8" textLength="1000.4"
clip-path="url(#breeze-prod-image-build-line-37)">something like: python:VERSION-slim-bookworm.                           
[...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="947.2"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-38)">│</text><text
class="breeze-prod-image-build-r7" x="439.2" y="947.2" textLength="1000.4"
clip-path="url(#breeze-prod-image-build-line-38)">(TEXT)                                    
[...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="971.6"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-39)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="971.6" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-39)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="971.6" textLength="85.4"
clip-path="url(#breeze-prod-image-build-line-39)">-commit</text><text
class="breeze-prod-image-build-r4" x="122" y="971.6" textLength="48. [...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="996"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-40)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="996" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-40)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="996" textLength="134.2"
clip-path="url(#breeze-prod-image-build-line-40)">-additional</text><text
class="breeze-prod-image-build-r4" x="170.8" y="996" textLength="219. [...]
-</text><text class="breeze-prod-image-build-r5" x="0" y="1020.4"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-41)">│</text><text
class="breeze-prod-image-build-r1" x="439.2" y="1020.4" textLength="1000.4"
clip-path="url(#breeze-prod-image-build-line-41)">itself).                                   &
[...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="825.2"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-33)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="825.2" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-33)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="825.2" textLength="134.2"
clip-path="url(#breeze-prod-image-build-line-33)">-additional</text><text
class="breeze-prod-image-build-r4" x="170.8" y="825.2" textLeng [...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="849.6"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-34)">│</text><text
class="breeze-prod-image-build-r1" x="439.2" y="849.6" textLength="1000.4"
clip-path="url(#breeze-prod-image-build-line-34)">itself).                                   
[...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="874"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-35)">│</text><text
class="breeze-prod-image-build-r7" x="439.2" y="874" textLength="1000.4"
clip-path="url(#breeze-prod-image-build-line-35)">(TEXT)                                    
[...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="898.4"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-36)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="898.4" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-36)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="898.4" textLength="85.4"
clip-path="url(#breeze-prod-image-build-line-36)">-commit</text><text
class="breeze-prod-image-build-r4" x="122" y="898.4" textLength="48. [...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="922.8"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-37)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="922.8" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-37)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="922.8" textLength="85.4"
clip-path="url(#breeze-prod-image-build-line-37)">-debian</text><text
class="breeze-prod-image-build-r4" x="122" y="922.8" textLength="97. [...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="947.2"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-38)">│</text><text
class="breeze-prod-image-build-r7" x="439.2" y="947.2" textLength="793"
clip-path="url(#breeze-prod-image-build-line-38)">(bookworm | bullseye)                                &
[...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="971.6"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-39)">│</text><text
class="breeze-prod-image-build-r5" x="439.2" y="971.6" textLength="793"
clip-path="url(#breeze-prod-image-build-line-39)">[default: bookworm]                                 &#
[...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="996"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-40)">│</text><text
class="breeze-prod-image-build-r4" x="24.4" y="996" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-40)">-</text><text
class="breeze-prod-image-build-r4" x="36.6" y="996" textLength="85.4"
clip-path="url(#breeze-prod-image-build-line-40)">-python</text><text
class="breeze-prod-image-build-r4" x="122" y="996" textLength="73.2" clip- [...]
+</text><text class="breeze-prod-image-build-r5" x="0" y="1020.4"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-41)">│</text><text
class="breeze-prod-image-build-r1" x="439.2" y="1020.4" textLength="1000.4"
clip-path="url(#breeze-prod-image-build-line-41)">something like: python:VERSION-slim-bookworm.                           &#
[...]
</text><text class="breeze-prod-image-build-r5" x="0" y="1044.8"
textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-42)">│</text><text
class="breeze-prod-image-build-r7" x="439.2" y="1044.8" textLength="1000.4"
clip-path="url(#breeze-prod-image-build-line-42)">(TEXT)                                   
[...]
</text><text class="breeze-prod-image-build-r5" x="0" y="1069.2"
textLength="1464"
clip-path="url(#breeze-prod-image-build-line-43)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
class="breeze-prod-image-build-r1" x="1464" y="1069.2" textLength="12.2"
clip-path="url(#breeze-prod-image-build-line-43)">
</text><text class="breeze-prod-image-build-r5" x="0" y="1093.6"
textLength="24.4"
clip-path="url(#breeze-prod-image-build-line-44)">╭─</text><text
class="breeze-prod-image-build-r5" x="24.4" y="1093.6" textLength="597.8"
clip-path="url(#breeze-prod-image-build-line-44)"> Selecting constraint location (for power users) </text><text
class="breeze-prod-image-build-r5" x="622.2" y="1093.6" textLength="817.4"
clip-path="url(#breeze-prod-image-build-line-44) [...]
diff --git a/dev/breeze/doc/images/output_prod-image_build.txt
b/dev/breeze/doc/images/output_prod-image_build.txt
index dbfb23f9c0..86876deb7f 100644
--- a/dev/breeze/doc/images/output_prod-image_build.txt
+++ b/dev/breeze/doc/images/output_prod-image_build.txt
@@ -1 +1 @@
-e3ed45363576b9bb3eb1cf5e3a2c08df
+07693b2597b00fdb156949c753dae783
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 103d4dafd5..8213555c0a 100644
--- a/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
@@ -252,6 +252,14 @@ option_eager_upgrade_additional_requirements =
click.option(
"(see `breeze ci find-backtracking-candidates`).",
)
+option_use_uv_ci = click.option(
+ "--use-uv/--no-use-uv",
+ is_flag=True,
+ default=True,
+ help="Use uv instead of pip as packaging tool.",
+ envvar="USE_UV",
+)
+
option_upgrade_to_newer_dependencies = click.option(
"-u",
"--upgrade-to-newer-dependencies",
@@ -319,6 +327,7 @@ option_version_suffix_for_pypi_ci = click.option(
@option_tag_as_latest
@option_upgrade_on_failure
@option_upgrade_to_newer_dependencies
+@option_use_uv_ci
@option_verbose
@option_version_suffix_for_pypi_ci
def build(
@@ -359,6 +368,7 @@ def build(
tag_as_latest: bool,
upgrade_on_failure: bool,
upgrade_to_newer_dependencies: bool,
+ use_uv: bool,
version_suffix_for_pypi: str,
):
"""Build CI image. Include building multiple images for all python
versions."""
@@ -425,6 +435,7 @@ def build(
tag_as_latest=tag_as_latest,
upgrade_on_failure=upgrade_on_failure,
upgrade_to_newer_dependencies=upgrade_to_newer_dependencies,
+ use_uv=use_uv,
version_suffix_for_pypi=version_suffix_for_pypi,
)
if platform:
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 97f5f23538..46d0a93a64 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
@@ -59,6 +59,7 @@ CI_IMAGE_TOOLS_PARAMETERS: dict[str, list[dict[str, str |
list[str]]]] = {
"--debian-version",
"--install-mysql-client-type",
"--python-image",
+ "--use-uv",
],
},
{
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 78b4b9e00d..df780dbbd8 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
@@ -53,10 +53,10 @@ PRODUCTION_IMAGE_TOOLS_PARAMETERS: dict[str, list[dict[str,
str | list[str]]]] =
{
"name": "Advanced build options (for power users)",
"options": [
+ "--additional-pip-install-flags",
+ "--commit-sha",
"--debian-version",
"--python-image",
- "--commit-sha",
- "--additional-pip-install-flags",
],
},
{
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 68a21549f9..b1d53d7065 100644
--- a/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/release_management_commands.py
@@ -214,6 +214,8 @@ class VersionedFile(NamedTuple):
AIRFLOW_PIP_VERSION = "24.0"
+AIRFLOW_UV_VERSION = "0.1.10"
+AIRFLOW_USE_UV = False
WHEEL_VERSION = "0.36.2"
GITPYTHON_VERSION = "3.1.40"
RICH_VERSION = "13.7.0"
diff --git a/dev/breeze/src/airflow_breeze/params/build_ci_params.py
b/dev/breeze/src/airflow_breeze/params/build_ci_params.py
index 2883eded8c..be412e3c14 100644
--- a/dev/breeze/src/airflow_breeze/params/build_ci_params.py
+++ b/dev/breeze/src/airflow_breeze/params/build_ci_params.py
@@ -41,6 +41,7 @@ class BuildCiParams(CommonBuildParams):
eager_upgrade_additional_requirements: str | None = None
skip_provider_dependencies_check: bool = False
skip_image_upgrade_check: bool = False
+ use_uv: bool = True
warn_image_upgrade_needed: bool = False
@property
@@ -65,6 +66,7 @@ class BuildCiParams(CommonBuildParams):
self._req_arg("AIRFLOW_IMAGE_DATE_CREATED",
self.airflow_image_date_created)
self._req_arg("AIRFLOW_IMAGE_REPOSITORY",
self.airflow_image_repository)
self._req_arg("AIRFLOW_PRE_CACHED_PIP_PACKAGES",
self.airflow_pre_cached_pip_packages)
+ self._req_arg("AIRFLOW_USE_UV", self.use_uv)
self._req_arg("AIRFLOW_VERSION", self.airflow_version)
self._req_arg("BUILD_ID", self.build_id)
self._req_arg("CONSTRAINTS_GITHUB_REPOSITORY",
self.constraints_github_repository)
diff --git a/dev/breeze/src/airflow_breeze/params/build_prod_params.py
b/dev/breeze/src/airflow_breeze/params/build_prod_params.py
index 334edaab48..342ac0c143 100644
--- a/dev/breeze/src/airflow_breeze/params/build_prod_params.py
+++ b/dev/breeze/src/airflow_breeze/params/build_prod_params.py
@@ -51,10 +51,10 @@ class BuildProdParams(CommonBuildParams):
install_airflow_reference: str | None = None
install_airflow_version: str | None = None
install_packages_from_context: bool = False
- use_constraints_for_context_packages: bool = False
installation_method: str = "."
runtime_apt_command: str | None = None
runtime_apt_deps: str | None = None
+ use_constraints_for_context_packages: bool = False
@property
def airflow_version(self) -> str:
diff --git a/docs/docker-stack/build-arg-ref.rst
b/docs/docker-stack/build-arg-ref.rst
index a3dbf447ad..805dc1dfe6 100644
--- a/docs/docker-stack/build-arg-ref.rst
+++ b/docs/docker-stack/build-arg-ref.rst
@@ -47,6 +47,10 @@ Those are the most common arguments that you use when you
want to build a custom
+------------------------------------------+------------------------------------------+---------------------------------------------+
| ``AIRFLOW_PIP_VERSION`` | ``24.0``
| PIP version used. |
+------------------------------------------+------------------------------------------+---------------------------------------------+
+| ``AIRFLOW_UV_VERSION`` | ``0.1.10``
| UV version used. |
++------------------------------------------+------------------------------------------+---------------------------------------------+
+| ``AIRFLOW_USE_UV`` | ``false``
| Whether to use UV. |
++------------------------------------------+------------------------------------------+---------------------------------------------+
| ``ADDITIONAL_PIP_INSTALL_FLAGS`` |
| additional ``pip`` flags passed to the |
| |
| installation commands (except when |
| |
| reinstalling ``pip`` itself) |
diff --git a/scripts/docker/common.sh b/scripts/docker/common.sh
index 0e04f2f4bd..3aca611440 100644
--- a/scripts/docker/common.sh
+++ b/scripts/docker/common.sh
@@ -18,6 +18,10 @@
# shellcheck shell=bash
set -euo pipefail
+: "${AIRFLOW_PIP_VERSION:?Should be set}"
+: "${AIRFLOW_UV_VERSION:?Should be set}"
+: "${AIRFLOW_USE_UV:?Should be set}"
+
function common::get_colors() {
COLOR_BLUE=$'\e[34m'
COLOR_GREEN=$'\e[32m'
@@ -31,6 +35,40 @@ function common::get_colors() {
export COLOR_YELLOW
}
+function common::get_packaging_tool() {
+ ## IMPORTANT: IF YOU MODIFY THIS FUNCTION YOU SHOULD ALSO MODIFY
CORRESPONDING FUNCTION IN
+ ## `scripts/in_container/_in_container_utils.sh`
+ if [[ ${AIRFLOW_USE_UV} == "true" ]]; then
+ echo
+ echo "${COLOR_BLUE}Using 'uv' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL="uv"
+ export PACKAGING_TOOL_CMD="uv pip"
+ export EXTRA_INSTALL_FLAGS=""
+ export EXTRA_UNINSTALL_FLAGS=""
+ export RESOLUTION_HIGHEST_FLAG="--resolution highest"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--resolution lowest-direct"
+ # We need to lie about VIRTUAL_ENV to make uv works
+ # Until https://github.com/astral-sh/uv/issues/1396 is fixed
+ # In case we are running user installation, we need to set VIRTUAL_ENV
to user's home + .local
+ if [[ ${PIP_USER=} == "true" ]]; then
+ VIRTUAL_ENV="${HOME}/.local"
+ else
+ VIRTUAL_ENV=$(python -c "import sys; print(sys.prefix)")
+ fi
+ export VIRTUAL_ENV
+ else
+ echo
+ echo "${COLOR_BLUE}Using 'pip' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL="pip"
+ export PACKAGING_TOOL_CMD="pip"
+ export EXTRA_INSTALL_FLAGS="--root-user-action ignore"
+ export EXTRA_UNINSTALL_FLAGS="--yes"
+ export RESOLUTION_HIGHEST_FLAG="--upgrade-strategy eager"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--upgrade --upgrade-strategy
only-if-needed"
+ fi
+}
function common::get_airflow_version_specification() {
if [[ -z ${AIRFLOW_VERSION_SPECIFICATION=}
@@ -66,20 +104,41 @@ function common::get_constraints_location() {
fi
}
-function common::show_pip_version_and_location() {
+function common::show_packaging_tool_version_and_location() {
echo "PATH=${PATH}"
- echo "pip on path: $(which pip)"
- echo "Using pip: $(pip --version)"
+ if [[ ${PACKAGING_TOOL} == "pip" ]]; then
+ echo "${COLOR_BLUE}Using 'pip' to install Airflow${COLOR_RESET}"
+ echo "pip on path: $(which pip)"
+ echo "Using pip: $(pip --version)"
+ else
+ echo "${COLOR_BLUE}Using 'uv' to install Airflow${COLOR_RESET}"
+ echo "uv on path: $(which uv)"
+ echo "Using uv: $(uv --version)"
+ fi
}
-function common::install_pip_version() {
+function common::install_packaging_tool() {
echo
echo "${COLOR_BLUE}Installing pip version
${AIRFLOW_PIP_VERSION}${COLOR_RESET}"
echo
if [[ ${AIRFLOW_PIP_VERSION} =~ .*https.* ]]; then
- pip install --disable-pip-version-check "pip @ ${AIRFLOW_PIP_VERSION}"
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check "pip
@ ${AIRFLOW_PIP_VERSION}"
else
- pip install --disable-pip-version-check "pip==${AIRFLOW_PIP_VERSION}"
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"pip==${AIRFLOW_PIP_VERSION}"
+ fi
+ if [[ ${AIRFLOW_USE_UV} == "true" ]]; then
+ echo
+ echo "${COLOR_BLUE}Installing uv version
${AIRFLOW_UV_VERSION}${COLOR_RESET}"
+ echo
+ if [[ ${AIRFLOW_UV_VERSION} =~ .*https.* ]]; then
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"uv @ ${AIRFLOW_UV_VERSION}"
+ else
+ # shellcheck disable=SC2086
+ pip install --root-user-action ignore --disable-pip-version-check
"uv==${AIRFLOW_UV_VERSION}"
+ fi
fi
mkdir -p "${HOME}/.local/bin"
}
diff --git a/scripts/docker/entrypoint_ci.sh b/scripts/docker/entrypoint_ci.sh
index 875d0b2291..4e770992bc 100755
--- a/scripts/docker/entrypoint_ci.sh
+++ b/scripts/docker/entrypoint_ci.sh
@@ -221,8 +221,12 @@ function check_boto_upgrade() {
echo
echo "${COLOR_BLUE}Upgrading boto3, botocore to latest version to run
Amazon tests with them${COLOR_RESET}"
echo
- pip uninstall --root-user-action ignore aiobotocore s3fs -y || true
- pip install --root-user-action ignore --upgrade boto3 botocore
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} aiobotocore s3fs
|| true
+ # We need to include oss2 as dependency as otherwise jmespath will be
bumped and it will not pass
+ # the pip check test, Similarly gcloud-aio-auth limit is needed to be
included as it bumps cryptography
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade boto3
botocore "oss2>=2.14.0" "gcloud-aio-auth>=4.0.0,<5.0.0"
pip check
}
@@ -232,25 +236,31 @@ function check_pydantic() {
echo
echo "${COLOR_YELLOW}Reinstalling airflow from local sources to
account for pyproject.toml changes${COLOR_RESET}"
echo
- pip install --root-user-action ignore -e .
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} -e .
echo
echo "${COLOR_YELLOW}Remove pydantic and 3rd party libraries that
depend on it${COLOR_RESET}"
echo
- pip uninstall --root-user-action ignore pydantic aws-sam-translator
openai pyiceberg qdrant-client cfn-lint -y
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} pydantic
aws-sam-translator openai \
+ pyiceberg qdrant-client cfn-lint weaviate-client
pip check
elif [[ ${PYDANTIC=} == "v1" ]]; then
echo
echo "${COLOR_YELLOW}Reinstalling airflow from local sources to
account for pyproject.toml changes${COLOR_RESET}"
echo
- pip install --root-user-action ignore -e .
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} -e .
echo
- echo "${COLOR_YELLOW}Uninstalling pyicberg which is not compatible
with Pydantic 1${COLOR_RESET}"
+ echo "${COLOR_YELLOW}Uninstalling dependencies which are not
compatible with Pydantic 1${COLOR_RESET}"
echo
- pip uninstall pyiceberg -y
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} pyiceberg
waeviate-client
echo
echo "${COLOR_YELLOW}Downgrading Pydantic to < 2${COLOR_RESET}"
echo
- pip install --upgrade "pydantic<2.0.0"
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
"pydantic<2.0.0"
pip check
else
echo
@@ -269,7 +279,8 @@ function check_download_sqlalchemy() {
echo
echo "${COLOR_BLUE}Downgrading sqlalchemy to minimum supported version:
${min_sqlalchemy_version}${COLOR_RESET}"
echo
- pip install --root-user-action ignore
"sqlalchemy==${min_sqlalchemy_version}"
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"sqlalchemy==${min_sqlalchemy_version}"
pip check
}
@@ -282,7 +293,8 @@ function check_download_pendulum() {
echo
echo "${COLOR_BLUE}Downgrading pendulum to minimum supported version:
${min_pendulum_version}${COLOR_RESET}"
echo
- pip install --root-user-action ignore "pendulum==${min_pendulum_version}"
+ # shellcheck disable=SC2086
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"pendulum==${min_pendulum_version}"
pip check
}
diff --git a/scripts/docker/install_additional_dependencies.sh
b/scripts/docker/install_additional_dependencies.sh
index 742e701f60..79e83eeb9e 100644
--- a/scripts/docker/install_additional_dependencies.sh
+++ b/scripts/docker/install_additional_dependencies.sh
@@ -20,7 +20,6 @@ set -euo pipefail
: "${UPGRADE_TO_NEWER_DEPENDENCIES:?Should be true or false}"
: "${ADDITIONAL_PYTHON_DEPS:?Should be set}"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
# shellcheck source=scripts/docker/common.sh
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
@@ -32,10 +31,10 @@ function install_additional_dependencies() {
echo "${COLOR_BLUE}Installing additional dependencies while upgrading
to newer dependencies${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore --upgrade --upgrade-strategy
eager \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_HIGHEST_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${ADDITIONAL_PYTHON_DEPS} ${EAGER_UPGRADE_ADDITIONAL_REQUIREMENTS=}
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -46,10 +45,10 @@ function install_additional_dependencies() {
echo "${COLOR_BLUE}Installing additional dependencies upgrading only
if needed${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore --upgrade --upgrade-strategy
only-if-needed \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
"${RESOLUTION_LOWEST_DIRECT_FLAG}" \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${ADDITIONAL_PYTHON_DEPS}
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -59,9 +58,10 @@ function install_additional_dependencies() {
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_additional_dependencies
diff --git a/scripts/docker/install_airflow.sh
b/scripts/docker/install_airflow.sh
index dd70188239..e8fb806ac6 100644
--- a/scripts/docker/install_airflow.sh
+++ b/scripts/docker/install_airflow.sh
@@ -29,8 +29,6 @@
# shellcheck source=scripts/docker/common.sh
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
function install_airflow() {
# Coherence check for editable installation mode.
if [[ ${AIRFLOW_INSTALLATION_METHOD} != "." && \
@@ -55,22 +53,21 @@ function install_airflow() {
echo "${COLOR_BLUE}Remove airflow and all provider packages installed
before potentially${COLOR_RESET}"
echo
set -x
- pip freeze | grep apache-airflow | xargs pip uninstall --yes
2>/dev/null || true
+ ${PACKAGING_TOOL_CMD} freeze | grep apache-airflow | xargs
${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} 2>/dev/null || true
set +x
echo
echo "${COLOR_BLUE}Installing all packages with eager upgrade with
${AIRFLOW_INSTALL_EDITABLE_FLAG} mode${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore \
- --upgrade --upgrade-strategy eager \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_HIGHEST_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
\
${EAGER_UPGRADE_ADDITIONAL_REQUIREMENTS=}
set +x
- common::install_pip_version
+ common::install_packaging_tool
echo
- echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
+ echo "${COLOR_BLUE}Running '${PACKAGING_TOOL} check'${COLOR_RESET}"
echo
pip check
else
@@ -78,17 +75,17 @@ function install_airflow() {
echo "${COLOR_BLUE}Installing all packages with constraints and
upgrade if needed${COLOR_RESET}"
echo
set -x
- pip install --root-user-action ignore ${AIRFLOW_INSTALL_EDITABLE_FLAG}
\
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
\
--constraint "${AIRFLOW_CONSTRAINTS_LOCATION}" || true
- common::install_pip_version
+ common::install_packaging_tool
# then upgrade if needed without using constraints to account for new
limits in pyproject.toml
- pip install --root-user-action ignore --upgrade --upgrade-strategy
only-if-needed \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
${RESOLUTION_LOWEST_DIRECT_FLAG} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${AIRFLOW_INSTALL_EDITABLE_FLAG} \
"${AIRFLOW_INSTALLATION_METHOD}[${AIRFLOW_EXTRAS}]${AIRFLOW_VERSION_SPECIFICATION}"
- common::install_pip_version
+ common::install_packaging_tool
set +x
echo
echo "${COLOR_BLUE}Running 'pip check'${COLOR_RESET}"
@@ -99,9 +96,10 @@ function install_airflow() {
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow
diff --git a/scripts/docker/install_airflow_dependencies_from_branch_tip.sh
b/scripts/docker/install_airflow_dependencies_from_branch_tip.sh
index f8bfabd1e2..202a40c41e 100644
--- a/scripts/docker/install_airflow_dependencies_from_branch_tip.sh
+++ b/scripts/docker/install_airflow_dependencies_from_branch_tip.sh
@@ -34,7 +34,6 @@
: "${AIRFLOW_BRANCH:?Should be set}"
: "${INSTALL_MYSQL_CLIENT:?Should be true or false}"
: "${INSTALL_POSTGRES_CLIENT:?Should be true or false}"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
function install_airflow_dependencies_from_branch_tip() {
echo
@@ -50,25 +49,26 @@ function install_airflow_dependencies_from_branch_tip() {
# dependencies that we can cache and reuse when installing airflow using
constraints and latest
# pyproject.toml in the next step (when we install regular airflow).
set -x
- pip install --root-user-action ignore \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
"apache-airflow[${AIRFLOW_EXTRAS}] @
https://github.com/${AIRFLOW_REPO}/archive/${AIRFLOW_BRANCH}.tar.gz"
- common::install_pip_version
+ common::install_packaging_tool
# Uninstall airflow and providers to keep only the dependencies. In the
future when
# planned https://github.com/pypa/pip/issues/11440 is implemented in pip
we might be able to use this
# flag and skip the remove step.
- pip freeze | grep apache-airflow-providers | xargs pip uninstall --yes
2>/dev/null || true
+ ${PACKAGING_TOOL_CMD} freeze | grep apache-airflow-providers | xargs
${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} 2>/dev/null || true
set +x
echo
echo "${COLOR_BLUE}Uninstalling just airflow. Dependencies remain. Now
target airflow can be reinstalled using mostly cached
dependencies${COLOR_RESET}"
echo
- pip uninstall --yes apache-airflow || true
+ ${PACKAGING_TOOL_CMD} uninstall ${EXTRA_UNINSTALL_FLAGS} apache-airflow ||
true
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow_dependencies_from_branch_tip
diff --git a/scripts/docker/install_from_docker_context_files.sh
b/scripts/docker/install_from_docker_context_files.sh
index 8d9c6cdd85..6e286b9d9c 100644
--- a/scripts/docker/install_from_docker_context_files.sh
+++ b/scripts/docker/install_from_docker_context_files.sh
@@ -24,8 +24,6 @@
# shellcheck source=scripts/docker/common.sh
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
function install_airflow_and_providers_from_docker_context_files(){
if [[ ${INSTALL_MYSQL_CLIENT} != "true" ]]; then
AIRFLOW_EXTRAS=${AIRFLOW_EXTRAS/mysql,}
@@ -42,7 +40,7 @@ function
install_airflow_and_providers_from_docker_context_files(){
fi
# shellcheck disable=SC2206
- local pip_flags=(
+ local packaging_flags=(
# Don't quote this -- if it is empty we don't want it to create an
# empty array element
--find-links="file:///docker-context-files"
@@ -92,7 +90,7 @@ function
install_airflow_and_providers_from_docker_context_files(){
echo
# force reinstall all airflow + provider packages with constraints
found in
set -x
- pip install "${pip_flags[@]}" --root-user-action ignore --upgrade \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"${packaging_flags[@]}" --upgrade \
${ADDITIONAL_PIP_INSTALL_FLAGS} --constraint
"${local_constraints_file}" \
${reinstalling_apache_airflow_package}
${reinstalling_apache_airflow_providers_packages}
set +x
@@ -101,7 +99,7 @@ function
install_airflow_and_providers_from_docker_context_files(){
echo "${COLOR_BLUE}Installing docker-context-files packages with
constraints from GitHub${COLOR_RESET}"
echo
set -x
- pip install "${pip_flags[@]}" --root-user-action ignore \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"${packaging_flags[@]}" \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
--constraint "${AIRFLOW_CONSTRAINTS_LOCATION}" \
${reinstalling_apache_airflow_package}
${reinstalling_apache_airflow_providers_packages}
@@ -112,12 +110,12 @@ function
install_airflow_and_providers_from_docker_context_files(){
echo "${COLOR_BLUE}Installing docker-context-files packages without
constraints${COLOR_RESET}"
echo
set -x
- pip install "${pip_flags[@]}" --root-user-action ignore \
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
"${packaging_flags[@]}" \
${ADDITIONAL_PIP_INSTALL_FLAGS} \
${reinstalling_apache_airflow_package}
${reinstalling_apache_airflow_providers_packages}
set +x
fi
- common::install_pip_version
+ common::install_packaging_tool
pip check
}
@@ -126,7 +124,6 @@ function
install_airflow_and_providers_from_docker_context_files(){
# method on air-gaped system where you do not want to download any
dependencies from remote hosts
# which is a requirement for serious installations
function install_all_other_packages_from_docker_context_files() {
-
echo
echo "${COLOR_BLUE}Force re-installing all other package from local files
without dependencies${COLOR_RESET}"
echo
@@ -136,20 +133,20 @@ function
install_all_other_packages_from_docker_context_files() {
grep -v apache_airflow | grep -v apache-airflow || true)
if [[ -n "${reinstalling_other_packages}" ]]; then
set -x
- pip install ${ADDITIONAL_PIP_INSTALL_FLAGS} \
- --root-user-action ignore --force-reinstall --no-deps --no-index
${reinstalling_other_packages}
- common::install_pip_version
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS}
${ADDITIONAL_PIP_INSTALL_FLAGS} \
+ --force-reinstall --no-deps --no-index
${reinstalling_other_packages}
+ common::install_packaging_tool
set +x
fi
}
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
common::get_constraints_location
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
install_airflow_and_providers_from_docker_context_files
-common::show_pip_version_and_location
install_all_other_packages_from_docker_context_files
diff --git a/scripts/docker/install_mssql.sh b/scripts/docker/install_mssql.sh
index 9f33e56e8a..a174a1039b 100644
--- a/scripts/docker/install_mssql.sh
+++ b/scripts/docker/install_mssql.sh
@@ -24,7 +24,6 @@ set -euo pipefail
common::get_colors
declare -a packages
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
: "${INSTALL_MSSQL_CLIENT:?Should be true or false}"
diff --git a/scripts/docker/install_pip_version.sh
b/scripts/docker/install_pip_version.sh
index afe46c7c1f..af8d25e06e 100644
--- a/scripts/docker/install_pip_version.sh
+++ b/scripts/docker/install_pip_version.sh
@@ -19,11 +19,10 @@
# shellcheck source=scripts/docker/common.sh
. "$( dirname "${BASH_SOURCE[0]}" )/common.sh"
-: "${AIRFLOW_PIP_VERSION:?Should be set}"
-
common::get_colors
+common::get_packaging_tool
common::get_airflow_version_specification
common::override_pip_version_if_needed
-common::show_pip_version_and_location
+common::show_packaging_tool_version_and_location
-common::install_pip_version
+common::install_packaging_tool
diff --git a/scripts/docker/install_pipx_tools.sh
b/scripts/docker/install_pipx_tools.sh
index 2207db994d..534dce8a93 100644
--- a/scripts/docker/install_pipx_tools.sh
+++ b/scripts/docker/install_pipx_tools.sh
@@ -24,7 +24,7 @@ function install_pipx_tools() {
echo "${COLOR_BLUE}Installing pipx tools${COLOR_RESET}"
echo
# Make sure PIPX is installed in latest version
- pip install --root-user-action ignore --upgrade "pipx>=1.2.1"
+ ${PACKAGING_TOOL_CMD} install ${EXTRA_INSTALL_FLAGS} --upgrade
"pipx>=1.2.1"
if [[ $(uname -m) != "aarch64" ]]; then
# Do not install mssql-cli for ARM
# Install all the tools we need available in command line but without
impacting the current environment
@@ -38,5 +38,6 @@ function install_pipx_tools() {
}
common::get_colors
+common::get_packaging_tool
install_pipx_tools
diff --git a/scripts/in_container/_in_container_utils.sh
b/scripts/in_container/_in_container_utils.sh
index b8d11c61e2..e991b1b413 100644
--- a/scripts/in_container/_in_container_utils.sh
+++ b/scripts/in_container/_in_container_utils.sh
@@ -60,8 +60,44 @@ function in_container_go_to_airflow_sources() {
pushd "${AIRFLOW_SOURCES}" >/dev/null 2>&1 || exit 1
}
+function in_container_get_packaging_tool() {
+ ## IMPORTANT: IF YOU MODIFY THIS FUNCTION YOU SHOULD ALSO MODIFY
CORRESPONDING FUNCTION IN
+ ## `scripts/docker/common.sh`
+ if [[ ${AIRFLOW_USE_UV} == "true" ]]; then
+ echo
+ echo "${COLOR_BLUE}Using 'uv' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL=""
+ export PACKAGING_TOOL_CMD="uv pip"
+ export EXTRA_INSTALL_FLAGS=""
+ export EXTRA_UNINSTALL_FLAGS=""
+ export RESOLUTION_HIGHEST_FLAG="--resolution highest"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--resolution lowest-direct"
+ # We need to lie about VIRTUAL_ENV to make uv works
+ # Until https://github.com/astral-sh/uv/issues/1396 is fixed
+ # In case we are running user installation, we need to set VIRTUAL_ENV
to user's home + .local
+ if [[ ${PIP_USER=} == "true" ]]; then
+ VIRTUAL_ENV="${HOME}/.local"
+ else
+ VIRTUAL_ENV=$(python -c "import sys; print(sys.prefix)")
+ fi
+ export VIRTUAL_ENV
+ else
+ echo
+ echo "${COLOR_BLUE}Using 'pip' to install Airflow${COLOR_RESET}"
+ echo
+ export PACKAGING_TOOL="pip"
+ export PACKAGING_TOOL_CMD="pip"
+ export EXTRA_INSTALL_FLAGS="--root-user-action ignore"
+ export EXTRA_UNINSTALL_FLAGS="--yes"
+ export RESOLUTION_HIGHEST_FLAG="--upgrade-strategy eager"
+ export RESOLUTION_LOWEST_DIRECT_FLAG="--upgrade --upgrade-strategy
only-if-needed"
+ fi
+}
+
function in_container_basic_check() {
assert_in_container
+ in_container_get_packaging_tool
in_container_go_to_airflow_sources
}
@@ -93,3 +129,4 @@ function in_container_set_colors() {
export CI=${CI:="false"}
export GITHUB_ACTIONS=${GITHUB_ACTIONS:="false"}
+export AIRFLOW_USE_UV=${AIRFLOW_USE_UV:="false"}
diff --git a/tests/cli/commands/test_webserver_command.py
b/tests/cli/commands/test_webserver_command.py
index 2122c508f0..376e9e0097 100644
--- a/tests/cli/commands/test_webserver_command.py
+++ b/tests/cli/commands/test_webserver_command.py
@@ -230,7 +230,7 @@ class TestCLIGetNumReadyWorkersRunning:
class TestCliWebServer(_ComonCLIGunicornTestClass):
main_process_regexp = r"airflow webserver"
- @pytest.mark.execution_timeout(210)
+ @pytest.mark.execution_timeout(400)
def test_cli_webserver_background(self, tmp_path):
with mock.patch.dict(
"os.environ",
@@ -272,11 +272,14 @@ class TestCliWebServer(_ComonCLIGunicornTestClass):
assert self._find_process(r"airflow webserver",
print_found_process=True)
console.print("[blue]Waiting for gunicorn processes:")
# wait for gunicorn to start
- for i in range(30):
+ for i in range(120):
if self._find_process(r"^gunicorn"):
break
console.print("[blue]Waiting for gunicorn to start ...")
time.sleep(1)
+ else:
+ console.print("[red]Gunicorn processes not found after 120
seconds")
+ assert False
console.print("[blue]Running gunicorn processes:")
assert self._find_all_processes("^gunicorn",
print_found_process=True)
console.print("[magenta]Webserver process started
successfully.")
diff --git a/tests/providers/weaviate/hooks/test_weaviate.py
b/tests/providers/weaviate/hooks/test_weaviate.py
index 075b3816fa..650f938dba 100644
--- a/tests/providers/weaviate/hooks/test_weaviate.py
+++ b/tests/providers/weaviate/hooks/test_weaviate.py
@@ -23,11 +23,12 @@ from unittest.mock import MagicMock, Mock
import pandas as pd
import pytest
import requests
-import weaviate
-from weaviate import ObjectAlreadyExistsException
-from airflow.models import Connection
-from airflow.providers.weaviate.hooks.weaviate import WeaviateHook
+weaviate = pytest.importorskip("weaviate")
+from weaviate import ObjectAlreadyExistsException # noqa: E402
+
+from airflow.models import Connection # noqa: E402
+from airflow.providers.weaviate.hooks.weaviate import WeaviateHook # noqa:
E402
TEST_CONN_ID = "test_weaviate_conn"
diff --git a/tests/providers/weaviate/operators/test_weaviate.py
b/tests/providers/weaviate/operators/test_weaviate.py
index b675cf5e64..597062a308 100644
--- a/tests/providers/weaviate/operators/test_weaviate.py
+++ b/tests/providers/weaviate/operators/test_weaviate.py
@@ -20,7 +20,9 @@ from unittest.mock import MagicMock, patch
import pytest
-from airflow.providers.weaviate.operators.weaviate import (
+pytest.importorskip("weaviate")
+
+from airflow.providers.weaviate.operators.weaviate import ( # noqa: E402
WeaviateDocumentIngestOperator,
WeaviateIngestOperator,
)