astronomer/Otto Airflow Upgrade
Scheduled, Otto-driven Airflow upgrades: detect the current Runtime + providers, bump to a safe target, have Otto migrate the DAG code for breaking changes, verify, and open a PR.
View on GitHubTrust Signals
- Scorecard Score
- not yet scored
- Maintenance Recency
- Activelast commit Jun 23, 2026
- License
- Apache 2.0
Pinned Snippet
uses: astronomer/otto-upgrade-action@51d37cb222c9d6e1432fc082537d271dbf4e3b49 # v0.1.0tags can be moved; commit SHAs can't. why a SHA?
Inputs
| name | description | required | default |
|---|---|---|---|
| astro-api-token | Astronomer API token for the Otto code-migration step. If empty, falls back to the ASTRO_API_TOKEN env var. When no token is available the action still opens the version-bump PR, but skips the Otto migration and flags breaking changes for manual review. | no | "" |
| astro-domain | Astronomer domain. Override for non-prod (e.g. 'astronomer-dev.io'). | no | astronomer.io |
| astro-organization | Astronomer organization ID for gateway routing. Falls back to the ASTRO_ORGANIZATION env var. | no | "" |
| github-token | Token used to push the branch and open/update the PR. Needs contents:write and pull-requests:write. To have the upgrade PR itself trigger your other CI workflows, supply a PAT or GitHub App token instead of the default GITHUB_TOKEN. | no | ${{ github.token }} |
| project-path | Path to the Astro project root (the directory containing the Dockerfile and requirements.txt). | no | . |
| target | How far to bump the Runtime: 'patch' (newest build on the current Airflow minor), 'latest-minor' (newest Runtime within the current Airflow major), or 'latest' (newest stable Runtime). Always clamped by max-upgrade-scope. | no | latest-minor |
| max-upgrade-scope | Safety clamp on how big a jump may be auto-authored: 'patch', 'minor', or 'major'. Majors are advisory-only regardless of this value — a scheduled bot never auto-authors an Airflow major migration; it surfaces it for the guided upgrade instead. | no | minor |
| include-providers | Also bump pinned 'apache-airflow-providers-*' entries in requirements.txt. Unpinned providers are reported but never changed. | no | true |
| verify-level | Post-upgrade verification: 'parse' (default — build the project's Docker image at the target Runtime and run Astro's DAG integrity tests inside it; catches image-build failures and verifies DAGs in the production-faithful environment; needs Docker, falls back to 'import' without it), 'import' (import the discovered DAG + plugin files in a PyPI-built env), 'syntax' (byte-compile only), or 'none'. Verification fails only on a NEW failure the upgrade introduces — failures that already occur at your current versions are reported but don't fail the run; env/setup problems report 'skipped'. | no | parse |
| bump-blocking-pins | When a provider bump conflicts with one of YOUR pins, raise your pin to the newest version uv can co-resolve instead of holding the provider back. Off by default — it edits user-owned dependencies. Every raise is listed in the PR's version table and gated by verification like any other change; if uv can't resolve a raise, the provider is held as usual. | no | false |
| deprecation-cleanup | Deprecated-Airflow-usage sweep (ruff AIR3 rules, dags/+plugins/+include/ only) beyond the hop's own migrations: 'fix' (default — mechanically rewrite what ruff can, e.g. operators moved to providers; remaining debt is listed in the PR), 'advisory' (only list the debt, change nothing), or 'off'. 'fix' auto-demotes to advisory when the target Airflow is not 3.x (the rewrites produce Airflow 3 forms) or when verify-level is below 'import' (nothing would gate the rewrites). Your own ruff excludes, per-file-ignores, and noqa comments are honored. | no | fix |
| base-branch | PR base branch. Empty uses the currently checked-out branch. | no | "" |
| branch | Head branch for the rolling upgrade PR. Re-runs force-push to it and update the same PR in place rather than opening a new one each run. | no | otto/airflow-upgrade |
| labels | Comma-separated labels applied to the PR (best-effort; missing labels are skipped with a warning). | no | airflow-upgrade,dependencies |
| model | Model identifier passed to Otto via --model. Empty uses Otto's default. | no | "" |
| astro-cli-version | Astro CLI version to install for the Otto step. Empty installs the latest published version (recommended). Only consulted when the Otto migration step runs. | no | "" |
| dry-run | Compute the plan, apply the bumps locally, and write the would-be PR body to the job summary — but do not push or open a PR. Use this to preview what the action would do. | no | false |
Outputs
| name | description |
|---|---|
| current-runtime | Detected current Runtime tag. |
| target-runtime | Resolved target Runtime tag. |
| overall-scope | Largest tier across the resolved plan (after pin reconciliation): patch, minor, major, or none. |
| no-update | 'true' when nothing is behind and the action no-ops. |
| verify-status | Verification result: passed, failed, or skipped (skipped when verification didn't run). |
| security-fixes | Count of security fixes listed in the Runtime release notes for the target's release line — a lower bound for cross-line upgrades. 'unknown' when it couldn't be determined, empty when the runtime didn't change. |
| pr-number | Number of the opened/updated PR (empty in dry-run or no-op). |
| pr-url | URL of the opened/updated PR (empty in dry-run or no-op). |
| branch | Head branch the upgrade was committed to. |