@@ -37,13 +37,13 @@ uv run pytest --disable-warnings
3737uv build
3838EOF
3939
40- FROM local-image/vector AS airflow-build-image
40+ FROM local-image/stackable-devel AS airflow-build-image
4141
4242ARG PRODUCT_VERSION
43- ARG SHARED_STATSD_EXPORTER_VERSION
4443ARG PYTHON_VERSION
4544ARG TARGETARCH
4645ARG STACKABLE_USER_UID
46+ ARG NODEJS_VERSION
4747ARG S3FS_VERSION
4848ARG CYCLONEDX_BOM_VERSION
4949ARG UV_VERSION
@@ -54,7 +54,8 @@ ARG UV_VERSION
5454# Requires implementation of https://github.com/apache/airflow/blob/2.2.5/scripts/docker/install_mysql.sh
5555ARG AIRFLOW_EXTRAS
5656
57- RUN microdnf update && \
57+ RUN microdnf module enable -y nodejs:${NODEJS_VERSION} && \
58+ microdnf update && \
5859 microdnf install \
5960 cyrus-sasl-devel \
6061 # Needed by ./configure to build gevent, see snippet [1] at the end of file
@@ -72,6 +73,9 @@ RUN microdnf update && \
7273 python${PYTHON_VERSION}-wheel \
7374 # The airflow odbc provider can compile without the development files (headers and libraries) (see https://github.com/stackabletech/docker-images/pull/683)
7475 unixODBC \
76+ # Needed for Airflow UI assets
77+ npm \
78+ nodejs \
7579 # Needed to modify the SBOM
7680 jq && \
7781 microdnf clean all && \
@@ -81,6 +85,11 @@ COPY airflow/stackable/constraints/${PRODUCT_VERSION}/constraints-python${PYTHON
8185COPY airflow/stackable/constraints/${PRODUCT_VERSION}/build-constraints-python${PYTHON_VERSION}.txt /tmp/build-constraints.txt
8286COPY --from=opa-auth-manager-builder /tmp/opa-auth-manager/dist/opa_auth_manager-0.1.0-py3-none-any.whl /tmp/
8387
88+ COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/patches/patchable.toml /stackable/src/airflow/stackable/patches/patchable.toml
89+ COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/patches/${PRODUCT_VERSION} /stackable/src/airflow/stackable/patches/${PRODUCT_VERSION}
90+
91+ WORKDIR /stackable
92+
8493RUN <<EOF
8594python${PYTHON_VERSION} -m venv --system-site-packages /stackable/app
8695
@@ -90,8 +99,44 @@ source /stackable/app/bin/activate
9099# Also install uv to get support for build constraints
91100pip install --no-cache-dir --upgrade pip
92101pip install --no-cache-dir uv==${UV_VERSION}
102+ uv tool install hatch
103+
104+ cd "$(/stackable/patchable --images-repo-root=src checkout airflow ${PRODUCT_VERSION})"
105+
106+ if [ -d "./airflow-core" ]; then
107+ # Airflow 3.x
108+ cd airflow-core/src/airflow/ui
109+
110+ # build front-end assets
111+ 112+ pnpm install --frozen-lockfile
113+ pnpm run build
114+
115+ # build airflow wheel from airflow root folder
116+ # this picks up the UI assets from the pnpm build, and the dependencies from the root folder
117+ cd ../../..
118+ /root/.local/bin/hatch build -t wheel
119+ # First install the full apache-airflow package to get all dependencies including database drivers
120+ uv pip install --no-cache-dir apache-airflow[${AIRFLOW_EXTRAS}]==${PRODUCT_VERSION} --constraint /tmp/constraints.txt --build-constraints /tmp/build-constraints.txt
121+ # Then install the locally built core wheel to override the core package
122+ uv pip install --no-cache-dir dist/apache_airflow_core-${PRODUCT_VERSION}-py3-none-any.whl[${AIRFLOW_EXTRAS}] --constraint /tmp/constraints.txt --build-constraints /tmp/build-constraints.txt
123+ else
124+ # Airflow 2.x
125+ # build front-end assets
126+ cd airflow/www
127+ 128+ yarn install --frozen-lockfile
129+ yarn run build
130+
131+ # build airflow wheel from airflow root folder
132+ cd ../..
133+ /root/.local/bin/hatch build -t wheel
134+ # First install the full apache-airflow package to get all dependencies including database drivers
135+ uv pip install --no-cache-dir apache-airflow[${AIRFLOW_EXTRAS}]==${PRODUCT_VERSION} --constraint /tmp/constraints.txt --build-constraints /tmp/build-constraints.txt
136+ # Then install the locally built wheel to override with patched version
137+ uv pip install --no-cache-dir dist/apache_airflow-${PRODUCT_VERSION}-py3-none-any.whl[${AIRFLOW_EXTRAS}] --constraint /tmp/constraints.txt --build-constraints /tmp/build-constraints.txt
138+ fi
93139
94- uv pip install --no-cache-dir apache-airflow[${AIRFLOW_EXTRAS}]==${PRODUCT_VERSION} --constraint /tmp/constraints.txt --build-constraints /tmp/build-constraints.txt
95140# Needed for pandas S3 integration to e.g. write and read csv and parquet files to/from S3
96141uv pip install --no-cache-dir s3fs==${S3FS_VERSION} cyclonedx-bom==${CYCLONEDX_BOM_VERSION}
97142# Needed for OIDC
@@ -102,6 +147,7 @@ uv pip install --no-cache-dir /tmp/opa_auth_manager-0.1.0-py3-none-any.whl
102147# Create the SBOM for Airflow
103148# Important: All `pip install` commands must be above this line, otherwise the SBOM will be incomplete
104149cyclonedx-py environment --schema-version 1.5 --outfile /tmp/sbom.json
150+ uv pip uninstall cyclonedx-bom
105151
106152# Break circular dependencies by removing the apache-airflow dependency from the providers
107153jq '.dependencies |= map(if .ref | test("^apache-airflow-providers-") then
@@ -111,10 +157,6 @@ else
111157end)' /tmp/sbom.json > /stackable/app/airflow-${PRODUCT_VERSION}.cdx.json
112158EOF
113159
114- COPY --from=statsd_exporter-builder /statsd_exporter/statsd_exporter /stackable/statsd_exporter
115- COPY --from=statsd_exporter-builder /statsd_exporter/statsd_exporter-${SHARED_STATSD_EXPORTER_VERSION}.cdx.json /stackable/statsd_exporter-${SHARED_STATSD_EXPORTER_VERSION}.cdx.json
116- COPY --from=gitsync-image --chown=${STACKABLE_USER_UID}:0 /git-sync /stackable/git-sync
117-
118160RUN <<EOF
119161mkdir -pv /stackable/airflow
120162mkdir -pv /stackable/airflow/dags
@@ -130,6 +172,7 @@ ARG PYTHON_VERSION
130172ARG RELEASE_VERSION
131173ARG TINI_VERSION
132174ARG TARGETARCH
175+ ARG SHARED_STATSD_EXPORTER_VERSION
133176ARG STACKABLE_USER_UID
134177
135178LABEL name="Apache Airflow" \
@@ -146,11 +189,14 @@ ENV PATH=$PATH:/bin:$HOME/app/bin
146189ENV AIRFLOW_HOME=$HOME/airflow
147190
148191COPY --from=airflow-build-image --chown=${STACKABLE_USER_UID}:0 /stackable/ ${HOME}/
149- COPY --from=airflow-build-image --chown=${STACKABLE_USER_UID}:0 /stackable/git-sync ${HOME}/git-sync
150192
151193COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/utils/entrypoint.sh /entrypoint.sh
152194COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/utils/run-airflow.sh /run-airflow.sh
153195
196+ COPY --from=statsd_exporter-builder --chown=${STACKABLE_USER_UID}:0 /statsd_exporter/statsd_exporter ${HOME}/statsd_exporter
197+ COPY --from=statsd_exporter-builder --chown=${STACKABLE_USER_UID}:0 /statsd_exporter/statsd_exporter-${SHARED_STATSD_EXPORTER_VERSION}.cdx.json ${HOME}/statsd_exporter-${SHARED_STATSD_EXPORTER_VERSION}.cdx.json
198+ COPY --from=gitsync-image --chown=${STACKABLE_USER_UID}:0 /git-sync ${HOME}/git-sync
199+
154200COPY airflow/licenses /licenses
155201
156202# Update image and install needed packages
@@ -185,6 +231,7 @@ curl -o /usr/bin/tini "https://repo.stackable.tech/repository/packages/tini/tini
185231chmod a+x /entrypoint.sh
186232chmod a+x /run-airflow.sh
187233chmod +x /usr/bin/tini
234+ chmod g=u /stackable/statsd_exporter ${HOME}/statsd_exporter-${SHARED_STATSD_EXPORTER_VERSION}.cdx.json ${HOME}/git-sync
188235EOF
189236
190237# ----------------------------------------
0 commit comments