Imported from BerkeleyLibrary/mokelumne (
.agents/skills/upgrade-airflow-version/SKILL.md). Install upstream withnpx skills add BerkeleyLibrary/mokelumne --skill upgrade-airflow-version. Copyright stays with the author.
Upgrade Airflow Version
Upgrade Mokelumne to a requested Airflow release while keeping its compiled dependencies compatible with the packages preinstalled in the upstream Airflow image.
Inspect the Current State
-
Read the repository's
AGENTS.mdand follow its current dependency, testing, security, and commit instructions. -
Run
git status --short. Preserve unrelated tracked and untracked work. -
Locate the current versions and dependency inputs:
grep -nE "AIRFLOW_VERSION|apache-airflow|task-sdk|constraints" \ Dockerfile pyproject.toml constraints.txt README.md requirements.txt -
Review the most recent Airflow-upgrade commit when useful. Use it to understand repository conventions, not as a substitute for inspecting the new image.
-
Record whether the Compose stack is running so its original state can be restored after verification.
Derive Versions from the Target Image
Pull or run the requested upstream image and inspect its installed packages:
docker run --rm --entrypoint python apache/airflow:<version> -m pip freeze
Inspect the image metadata rather than assuming the task SDK has the same patch version as Airflow:
docker run --rm --entrypoint python apache/airflow:<version> -c \
"from importlib.metadata import version; \
print('apache-airflow', version('apache-airflow')); \
print('apache-airflow-core', version('apache-airflow-core')); \
print('apache-airflow-task-sdk', version('apache-airflow-task-sdk'))"
Use the image's default Python variant, which matches the Dockerfile build and
CI environment. Treat the image's pip freeze output as the authority for
compatibility constraints.
Upgrade the Berkeley Providers First
Treat compatible new releases of both mokelumne-providers-tind and
mokelumne-providers-ldc as required parts of every Airflow upgrade. Their
source lives in separate upstream repositories, not in Mokelumne.
For each provider repository:
- Update its Airflow or
apache-airflow-task-sdkdependency for the target Airflow release. - Refresh its constraints and hash-pinned requirements according to that repository's instructions.
- Run its focused and complete tests plus
pip checkagainst the target Airflow version. - Release a new provider version through its tag-triggered PyPI workflow.
Do not copy provider implementation into Mokelumne or reference an unreleased provider version. Publishing releases or modifying upstream repositories requires the user's separate authorization. If compatible releases do not already exist and that authorization is absent, report the provider release chain as a blocker before compiling Mokelumne's requirements.
Update Dependency Inputs
- Change
AIRFLOW_VERSIONinDockerfile. - Change the exact
apache-airflow-task-sdkdependency inpyproject.tomlto the version installed in the target image. - Update the minimum versions of both
mokelumne-providers-tindandmokelumne-providers-ldcinpyproject.tomlto their newly released, Airflow-compatible versions. - Update the Airflow version example in
README.mdwhen it is stale. - Update the base-image version in the
constraints.txtheader. - Refresh the selective constraints in
constraints.txtfrom the target image. Keep exact pins or narrow ranges for packages whose independent resolution can conflict with preinstalled image packages.
Keep the provider dependency update in the same Mokelumne change as the Airflow update so the generated requirements cannot retain older provider releases by accident.
Regenerate Hash-Pinned Requirements
Never hand-edit generated pins. Run the repository command:
UV_CACHE_DIR=/tmp/mokelumne-uv-cache \
uv pip compile pyproject.toml --extra test -c constraints.txt \
--generate-hashes -o requirements.txt
Confirm that requirements.txt resolves apache-airflow,
apache-airflow-core, apache-airflow-task-sdk,
mokelumne-providers-tind, and mokelumne-providers-ldc to the intended
versions. Verify that the two provider pins changed to the new releases. Update
lock data only when it is tracked or otherwise part of the repository's current
dependency workflow; uv.lock is currently ignored.
Resolve Base-Image Conflicts
Build the Compose images:
docker compose build
Keep the Dockerfile's pip check guard enabled. If it reports that generated
pins conflict with packages preinstalled in the Airflow image:
- Compare each conflict with the target image's
pip freezeoutput and installed-package requirements. - Add the widest appropriate constraint to
constraints.txt. For example, specifycryptography >= 49, < 51instead ofcryptography == 50.0.0if it is known that major versions 49 and 50 ofcryptographywork with the specified Airflow version. - Regenerate
requirements.txtwith hashes as specified above. - Rebuild until
pip checkreports no broken requirements.
Common conflict families include cryptography/pyOpenSSL,
grpcio/grpcio-status, importlib-metadata/litellm, and aligned
OpenTelemetry packages. Derive versions from the current target image; do not
reuse old version numbers blindly.
Recreate and Verify the Stack
If .env is missing, generate development secrets without displaying or
committing them:
docker compose run \
--entrypoint /opt/airflow/scripts/setup_dev.py \
--no-deps --rm airflow-init
Start or recreate the stack and wait for it to become healthy:
docker compose up --detach
docker compose ps
Verify the running container's versions and dependency consistency:
docker compose exec airflow-cli python -c \
"from importlib.metadata import version; \
print('apache-airflow', version('apache-airflow')); \
print('apache-airflow-core', version('apache-airflow-core')); \
print('apache-airflow-task-sdk', version('apache-airflow-task-sdk')); \
print('mokelumne-providers-tind', version('mokelumne-providers-tind')); \
print('mokelumne-providers-ldc', version('mokelumne-providers-ldc'))"
docker compose exec airflow-cli python -m pip check
Run the complete test suite:
docker compose exec airflow-cli python -m pytest
Run pylint, pydoclint, and mypy as directed by AGENTS.md only when
Python modules changed. Do not fix unrelated failures or warnings; report them
separately.
Review and Restore State
- Run
git diff --check. - Review
git status --short, the complete source diff, and the changed-version inventory inrequirements.txt. - Confirm that only intended dependency and documentation files changed.
Ensure
.env, credentials, test artifacts, and generated secrets are not tracked. - If the stack was stopped initially, restore that state with
docker compose down. Never add-vunless the user explicitly requests deletion of persistent volumes. - Report updated Airflow, task SDK, TIND provider, and LDC provider versions;
build and
pip checkresults; focused and full test counts; warnings; and final Compose state.
Do not commit, push, publish, or create a pull request unless the user separately requests each action.