Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
5622301
Revert "Make Java SDK context signal-aware (#74690)" (#75421) (#75462)
jason810496 Oct 23, 2026
de6d319
[v3-4-test] Bump sphinx-airflow-theme to 0.3.15 for a more readable d…
github-actions[bot] Oct 23, 2026
9d0f566
[v3-4-test] Go SDK: fail a task whose return-value XCom push fails (#…
github-actions[bot] Oct 23, 2026
7ec2757
Revert "[v3-4-test] Enforce execution_timeout for tasks run by a lang…
jason810496 Oct 23, 2026
bdf2384
[v3-4-test] Show Dag version diff occurrence count on the path (#7543…
github-actions[bot] Oct 23, 2026
c2563f0
[v3-4-test] Fix docs pages listing their sections as separate pages i…
github-actions[bot] Oct 23, 2026
dc00fa6
[v3-4-test] Add consolidated Language SDK compatibility matrix (#7175…
github-actions[bot] Oct 23, 2026
e242620
[v3-4-test] Remove the gap above docs pages left from the old site ba…
github-actions[bot] Oct 23, 2026
d4706f1
[v3-4-test] Bump sphinx-airflow-theme to 0.3.16 to align the docs' On…
github-actions[bot] Oct 23, 2026
81cc1ca
[v3-4-test] Add missing zh-TW translations for Dag version path toolt…
github-actions[bot] Oct 23, 2026
9e16507
[v3-4-test] Keep the token cookie set by a route in JWTRefreshMiddlew…
github-actions[bot] Oct 23, 2026
57e21d2
[v3-4-test] Limit the CLI reference's page contents to top-level comm…
github-actions[bot] Oct 23, 2026
e5ba7be
[v3-4-test] Link task instances of task loops to their own page (#754…
github-actions[bot] Oct 23, 2026
248e6f9
[v3-4-test] Fix deferral paths in task lifecycle diagram (#75428) (#7…
github-actions[bot] Oct 23, 2026
4e25f4a
Bump swagger-ui-dist from 5.33.3 to 5.34.0 in /registry in the regist…
dependabot[bot] Oct 23, 2026
de96939
Bump @tanstack/react-query (#75508)
dependabot[bot] Oct 23, 2026
4ac335d
Bump the ts-sdk-package-updates group across 1 directory with 3 updat…
jason810496 Oct 24, 2026
9a2c293
Bump eslint in /ts-sdk in the ts-sdk-package-updates group (#75285) (…
jason810496 Oct 24, 2026
47c17f5
[v3-4-test] fix stat timing (#72553) (#75459)
github-actions[bot] Oct 24, 2026
b06c51b
[v3-4-test] Redact secrets written through RedactedIO.writelines() (#…
github-actions[bot] Oct 24, 2026
063bdb9
[v3-4-test] Guard register_at_fork in shared stats for Windows compat…
github-actions[bot] Oct 24, 2026
0027394
[v3-4-test] Clarify backfill reprocessing options (#72590) (#75465)
github-actions[bot] Oct 24, 2026
ff84def
[v3-4-test] Enable auto-merge, gated on a dedicated CI passed check (…
github-actions[bot] Oct 24, 2026
88b0674
[v3-4-test] Allow building docs with a local sphinx_airflow_theme che…
github-actions[bot] Oct 24, 2026
80e64ec
[v3-4-test] Allow jason810496 to publish docs to S3 (#75548) (#75549)
github-actions[bot] Oct 24, 2026
6c46571
[v3-4-test] Run the Kerberos renewer without metadata database checks…
github-actions[bot] Oct 24, 2026
3cf210d
[v3-4-test] Make Dags sidebar button a link and move Dag Runs and Tas…
github-actions[bot] Oct 24, 2026
79a3a56
[v3-4-test] Show the filtered task count in the Dag Tasks tab heading…
github-actions[bot] Oct 24, 2026
1541e66
[v3-4-test] Keep .airflowignore rules when the Dags folder symlink is…
github-actions[bot] Oct 24, 2026
32da579
[v3-4-test] Remove info tooltip from Dag version comparison (#75526) …
github-actions[bot] Oct 24, 2026
79e1aea
[v3-4-test] Reject non-positive max_active_runs when creating a backf…
github-actions[bot] Oct 24, 2026
f14de21
[v3-4-test] Show states of task groups as stacked cards in Grid view …
github-actions[bot] Oct 24, 2026
2e056cc
[v3-4-test] Fix breeze ci_group crash when the title is skipped in Gi…
github-actions[bot] Oct 24, 2026
2104e11
[v3-4-test] Go SDK: stop log attributes from displacing standard log …
github-actions[bot] Oct 24, 2026
0500ec8
[v3-4-test] Keep Breeze unit tests independent of the CI repository (…
github-actions[bot] Oct 25, 2026
864f107
[v3-4-test] Commit pre-release constraints onto the shared constraint…
github-actions[bot] Oct 25, 2026
9375102
[v3-4-test] UI: Fix visual and console-error bugs in Dag list and det…
github-actions[bot] Oct 25, 2026
b1d111e
[v3-4-test] Fix Go SDK install command breaking the first bundle buil…
github-actions[bot] Oct 25, 2026
5fbbb90
[v3-4-test] Cover YAML-generated TypeScript Dags in the ts_sdk e2e te…
github-actions[bot] Oct 25, 2026
214bee4
[v3-4-test] Fix "Dynamic require" error for CommonJS packages in airf…
github-actions[bot] Oct 25, 2026
f5b20a9
[v3-4-test] Stop the cdxgen server containers when SBOM generation en…
github-actions[bot] Oct 25, 2026
eff1d81
[v3-4-test] Backport today's CI changes (#75589, #74566, #74889, #756…
potiuk Oct 25, 2026
8eb4cee
[v3-4-test] Bring CI tooling level with main (#73785, #73998, #73823,…
potiuk Oct 25, 2026
d093967
[v3-4-test] Run only the component's tests on chart and airflow-ctl r…
github-actions[bot] Oct 25, 2026
82849bc
[v3-4-test] Run the component branch selection tests against main on …
github-actions[bot] Oct 26, 2026
19447fa
[v3-4-test] Add missing German Dag trigger translations (#75519) (#75…
github-actions[bot] Oct 26, 2026
caa31e8
[v3-4-test] Decide min_one_success trigger rules per index in mapped …
github-actions[bot] Oct 26, 2026
17fc103
[v3-4-test] Fix scheduler crash when retrying a task that timed out o…
github-actions[bot] Oct 26, 2026
d486547
[v3-4-test] TS SDK: Reject a blank queue in Dag and task specs (#7557…
github-actions[bot] Oct 26, 2026
2ec306e
[v3-4-test] Fetch provider release tags from apache/airflow in fork C…
github-actions[bot] Oct 26, 2026
1d4207f
[v3-4-test] Complete German UI translations (#75301) (#75567)
github-actions[bot] Oct 26, 2026
8e189c0
[v3-4-test] Add asset ID filtering to database cleanup (#74498) (#75581)
github-actions[bot] Oct 26, 2026
54610d8
[v3-4-test] Use EXISTS instead of a fan-out join in asset orphanage (…
github-actions[bot] Oct 26, 2026
7d329d9
[v3-4-test] Build no images on the airflow-ctl release branches (#756…
github-actions[bot] Oct 26, 2026
5cc50c5
[v3-4-test] Clear retry policy state when a TI is cleared (#73889) (#…
github-actions[bot] Oct 26, 2026
5436b0b
[v3-4-test] Run the database test jobs on RunsOn with docker in RAM (…
github-actions[bot] Oct 26, 2026
1873b86
[v3-4-test] Fix serialization of datetimes with a fixed UTC offset (#…
github-actions[bot] Oct 26, 2026
fe283b9
[v3-4-test] Reset Dag autoregistration state when a Python Dag file f…
github-actions[bot] Oct 26, 2026
22538bf
[v3-4-test] Return 5xx on database deadlock when updating task state …
github-actions[bot] Oct 26, 2026
62e3b1a
[v3-4-test] Stop a commented executable_resumable from marking a modu…
github-actions[bot] Oct 26, 2026
c477e4e
[v3-4-test] Update zh-TW plural form guidance for translators (#75669…
github-actions[bot] Oct 26, 2026
b902cb5
[v3-4-test] Normalize zh-TW plural forms and wording (#75504) (#75664)
github-actions[bot] Oct 26, 2026
1a578ef
[v3-4-test] Backport fork CI auto-approval (#75616, #75619, #75455, #…
potiuk Oct 26, 2026
89c6426
[v3-4-test] Keep the spot interruption notice green on transient GitH…
github-actions[bot] Oct 26, 2026
ee37502
[v3-4-test] Cancel the runs of merged pull requests when they merge (…
github-actions[bot] Oct 26, 2026
03bc831
[v3-4-test] Add emailer utilities to the SMTP provider (#74623) (#75704)
github-actions[bot] Oct 27, 2026
b85a3e6
Refuse Human-in-the-loop responses once the task stopped waiting (#75…
Lee-W Oct 27, 2026
ea6499b
[v3-4-test] Retry GitHub server errors in the fork CI monitor (#75692…
github-actions[bot] Oct 27, 2026
9a5d125
[v3-4-test] Restart crashed Breeze components under mprocs (#75585) (…
github-actions[bot] Oct 27, 2026
3920978
[v3-4-test] Deprecate airflow.utils.email in favor of the SMTP provid…
github-actions[bot] Oct 27, 2026
0ff47dc
[v3-4-test] Allow FastAPI 0.137+ by requiring cadwyn 8.1 (#75689) (#7…
vatsrahul1001 Oct 27, 2026
639d37d
[v3-4-test] Let listeners see the end date of a skipped task instance…
github-actions[bot] Oct 27, 2026
e2edfff
[v3-4-test] Run a language SDK runtime in its own process group (#757…
jason810496 Oct 27, 2026
256c891
[v3-4-test] Make the Kubernetes, E2E and Helm release jobs pass on fo…
github-actions[bot] Oct 27, 2026
1409c90
[v3-4-test] Keep cancelled CI runs from showing a failed CI passed ch…
shahar1 Oct 27, 2026
87577b6
[v3-4-test] Add dag_id and task_id tags to resumable_job metrics (#75…
github-actions[bot] Oct 27, 2026
3ebfc09
[v3-4-test] Upgrade important CI environment (#75719)
github-actions[bot] Oct 27, 2026
6027302
[v3-4-test] Add metrics for task and asset state store access (#75729…
github-actions[bot] Oct 27, 2026
ea342be
[v3-4-test] Wait for a maintainer when a fork PR changes any CI-defin…
github-actions[bot] Oct 27, 2026
9f5e63d
[v3-4-test] Report language SDK runtime launch failures in the task l…
github-actions[bot] Oct 27, 2026
e25535e
[v3-4-test] Fix Go SDK build on 32-bit targets (#75551) (#75742)
jason810496 Oct 27, 2026
78eae1f
[v3-4-test] Guard scheduler against Dag deserialization failures (#75…
vatsrahul1001 Oct 27, 2026
80bb11f
[v3-4-test] Update uv.lock for the SMTP provider 3.2.0 version (#75757)
shahar1 Oct 27, 2026
d563b90
[v3-4-test] Hide empty log groups in the task log view (#75686) (#75801)
github-actions[bot] Oct 27, 2026
65515bd
[v3-4-test] UI: Fix slow pending Dag run checks on large databases (#…
github-actions[bot] Oct 27, 2026
9764cdb
[v3-4-test] UI: Fix labels that render as raw translation keys (#7532…
github-actions[bot] Oct 27, 2026
3928f61
[v3-4-test] UI: Don't fire keyboard shortcuts while typing in a Monac…
github-actions[bot] Oct 27, 2026
ee42ee6
[v3-4-test] Fix UI crash by validating unresolvable Windows PT timezo…
github-actions[bot] Oct 27, 2026
669f3b4
[v3-4-test] Run automatic backport PRs on RunsOn runners (#75749) (#7…
github-actions[bot] Oct 27, 2026
5b34acf
[v3-4-test] Sync recent CI changes from main (#75824)
potiuk Oct 27, 2026
e55e92a
[v3-4-test] UI: Scope partitioned Dag run asset list to readable asse…
github-actions[bot] Oct 27, 2026
e64db03
[v3-4-test] Hide the scheduled run icon in the grid legend (#75775) (…
github-actions[bot] Oct 27, 2026
905a819
[v3-4-test] UI: Warn when the logical date is outside the Dag's dates…
github-actions[bot] Oct 27, 2026
fd417e2
[v3-4-test] Raise the stale bot operation budget so it reaches older …
github-actions[bot] Oct 28, 2026
7aa4106
[v3-4-test] Load the serialized Dag in ti_run only for stub tasks (#7…
jason810496 Oct 28, 2026
1ec0021
[v3-4-test] Isolate otel config-priority test from ambient OTEL env v…
github-actions[bot] Oct 28, 2026
2731400
[v3-4-test] Widen the Spot pool for RunsOn runners: more families, ca…
github-actions[bot] Oct 28, 2026
e723e68
[v3-4-test] Run the flynt prek hook in parallel batches (#75274) (#75…
github-actions[bot] Oct 28, 2026
3821b65
[v3-4-test] Stop running OpenLineage e2e compat tests when full tests…
github-actions[bot] Oct 28, 2026
27e709d
[v3-4-test] Show why external contributors' workflow runs wait for ap…
github-actions[bot] Oct 28, 2026
6f88b45
[v3-4-test] Skip spotless and the Java SDK Dag schema sync on unrelat…
github-actions[bot] Oct 28, 2026
cccca45
[v3-4-test] Avoid loading timetables for dags in Execution API endpoi…
github-actions[bot] Oct 28, 2026
4786e74
Add release notes for 3.4.0rc1
vatsrahul1001 Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
33 changes: 31 additions & 2 deletions .agents/skills/airflow-translations/locales/zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ Prioritize terms commonly used in the Taiwan tech ecosystem.

## Plural Forms

Traditional Chinese **does not** distinguish between singular and plural forms.
Use the **same translation** for both `_one` and `_other` suffixes:
Traditional Chinese **does not** distinguish between singular and plural forms,
so both suffixes use the same noun. i18next currently never selects `_one`
for `zh-TW` (the locale has a single plural category, `other`), but the key
must still exist for translation completeness.

Some keys are plain nouns rather than counts — use the same translation for
both suffixes:

**English source:**

Expand All @@ -46,6 +51,30 @@ Use the **same translation** for both `_one` and `_other` suffixes:
"dagRun_other": "Dag 執行"
```

When the English `_one` does carry a count, write it as a literal `1` instead
of interpolating `{{count, number}}`; keep the placeholder in `_other`:

**English source:**

```json
"taskCount_one": "{{count, number}} Task",
"taskCount_other": "{{count, number}} Tasks"
```

**Correct** — literal `1` in `_one`:

```json
"taskCount_one": "1 個任務",
"taskCount_other": "{{count, number}} 個任務"
```

**Incorrect** — interpolating a count that can only be 1:

```json
"taskCount_one": "{{count, number}} 個任務",
"taskCount_other": "{{count, number}} 個任務"
```

## Spacing Rules

Insert a **half-width space** between Chinese characters and adjacent
Expand Down
64 changes: 62 additions & 2 deletions .asf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ github:
rebase: false

pull_requests:
# allow auto-merge
allow_auto_merge: false
# Auto-merge waits for the required "CI passed" check enforced by the "Require CI on main" and
# "Require CI on release branches" rulesets. Without a required check it would merge as soon as
# the PR is approved, before CI finishes. The setting is repository-wide, so every branch that
# PRs target needs one of those rulesets.
allow_auto_merge: true
# enable updating head branches of pull requests
allow_update_branch: true
# auto-delete head branches after being merged
Expand Down Expand Up @@ -104,7 +107,64 @@ github:
required_conversation_resolution: true
required_signatures: false

# The two CI rulesets use the raw Rulesets API payload, because the convenience syntax can only name
# teams as bypass actors and GitHub refuses secret teams such as `airflow-committers`. Instead the
# Write repository role (actor_id 4) bypasses them: on this repository only committers hold it,
# granted by ASF Infra from the `airflow` LDAP group, so it needs no update when committers change.
# Committers can still merge a PR whose CI is red for an unrelated reason, by bypassing the rule.
#
# The required checks are not pinned to the GitHub Actions app: asfyaml passes raw values to the
# API as strings except for a fixed set of keys, and a string `integration_id` is rejected.
rulesets:
- name: "Require CI on main"
target: branch
enforcement: active
conditions:
ref_name:
include:
- "refs/heads/main"
exclude: []
bypass_actors:
- actor_id: 4
actor_type: RepositoryRole
bypass_mode: always
rules:
- type: deletion
- type: non_fast_forward
- type: required_status_checks
parameters:
strict_required_status_checks_policy: false
required_status_checks:
- context: "CI passed"
# The branches `ci-amd.yml` runs pull request CI for, apart from `main`. A release branch gets
# the "CI passed" job only when it is backported there; until then its PRs need a committer to
# bypass the rule.
- name: "Require CI on release branches"
target: branch
enforcement: active
conditions:
ref_name:
include:
- "refs/heads/v*-test"
- "refs/heads/v*-stable"
- "refs/heads/providers-*/v*"
- "refs/heads/chart/v*-test"
- "refs/heads/chart/v*-stable"
- "refs/heads/airflow-ctl/v*-test"
- "refs/heads/airflow-ctl/v*-stable"
exclude: []
bypass_actors:
- actor_id: 4
actor_type: RepositoryRole
bypass_mode: always
rules:
- type: deletion
- type: non_fast_forward
- type: required_status_checks
parameters:
strict_required_status_checks_policy: false
required_status_checks:
- context: "CI passed"
- name: "Branch protection"
type: branch
branches:
Expand Down
38 changes: 38 additions & 0 deletions .github/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!-- SPDX-License-Identifier: Apache-2.0
https://www.apache.org/licenses/LICENSE-2.0 -->

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [The `.github` folder — Agent Instructions](#the-github-folder--agent-instructions)
- [Keep the CI-minutes estimates in sync with the workflows](#keep-the-ci-minutes-estimates-in-sync-with-the-workflows)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# The `.github` folder — Agent Instructions

## Keep the CI-minutes estimates in sync with the workflows

`breeze ci approve-workflow-runs` (run by `workflows/auto-approve-workflow-runs.yml`) decides whether
to approve an external contributor's CI runs from an estimate of the job-minutes they take. The
numbers live in `dev/breeze/src/airflow_breeze/utils/ci_minutes_estimate.py` and are medians
measured on recent `Tests (AMD)` PR runs on public runners.

After you change the CI workflows in a way that adds, removes, splits or resizes jobs (new test
groups, a changed matrix, new composite workflows, a move between runner types), refresh the
estimates once the change has run on enough PRs, and in any case about once a month:

1. Run `uv run dev/calibrate_ci_minutes_estimates.py --since <date>`
from the repository root with an authenticated `gh` CLI. Pick a date that covers at least a
week of runs after the workflow change.
2. Copy the medians and fits it prints into the constants of `ci_minutes_estimate.py`, and update
the "Last calibrated" line next to them.
3. When you add a new job group to the workflows, add a matching group to both
`ci_minutes_estimate.py` (with the selective-check output that turns it on) and the
`JOB_GROUPS` patterns of the calibration script. Unmatched jobs fall into the base group.
4. Run `uv run --project dev/breeze pytest dev/breeze/tests/test_ci_minutes_estimate.py
dev/breeze/tests/test_workflow_run_approval.py -xvs`.

The estimates cover public runners only. Self-hosted (RunsOn) runners need their own set once there
is enough data from them.
2 changes: 2 additions & 0 deletions .github/actions/breeze/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ outputs:
runs:
using: "composite"
steps:
- name: "RunsOn cost summary"
uses: ./.github/actions/runs-on-cost-summary
- name: "Setup python"
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
Expand Down
5 changes: 3 additions & 2 deletions .github/actions/prepare_breeze_and_image/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,13 @@ runs:
- name: >
Restore ${{ inputs.image-type }} docker image ${{ inputs.platform }}:${{ inputs.python }}
${{ inputs.image-stash-ref != '' && format('built for ref {0}', inputs.image-stash-ref) || '' }}
# yamllint disable-line rule:line-length
uses: apache/infrastructure-actions/stash/restore@61dcea11f19e2bbe1263f14d72235e8da17d3ad0 # restore/v1.0.0
uses: ./.github/actions/stash-restore
with:
key: "${{ inputs.image-type }}-image-save-v3-${{ inputs.platform }}-${{ inputs.python }}\
${{ inputs.image-stash-ref != '' && format('-{0}', inputs.image-stash-ref) || '' }}"
path: "/mnt/"
# Must stay true: runs on RunsOn (canaries and release-branch pushes) save these image
# stashes as S3 digests only.
only-current-branch: 'true'
fail-on-download: 'true'
- name: "Load ${{ inputs.image-type }} image ${{ inputs.platform }}:${{ inputs.python }}"
Expand Down
5 changes: 3 additions & 2 deletions .github/actions/prepare_single_ci_image/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ runs:
using: "composite"
steps:
- name: "Restore CI docker images ${{ inputs.platform }}:${{ inputs.python }}"
# yamllint disable-line rule:line-length
uses: apache/infrastructure-actions/stash/restore@61dcea11f19e2bbe1263f14d72235e8da17d3ad0 # restore/v1.0.0
uses: ./.github/actions/stash-restore
with:
key: ci-image-save-v3-${{ inputs.platform }}-${{ inputs.python }}
path: "/mnt/"
# Must stay true: runs on RunsOn (canaries and release-branch pushes) save these image
# stashes as S3 digests only.
only-current-branch: 'true'
fail-on-download: 'true'
if: contains(inputs.python-versions-list-as-string, inputs.python)
Expand Down
30 changes: 30 additions & 0 deletions .github/actions/runs-on-cost-summary/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
---
# Puts the job's EC2 cost next to the GitHub-hosted price in the job summary. Used by every job
# that can run on RunsOn: through the breeze action, or directly by jobs that do not install Breeze.
name: 'RunsOn cost summary'
description: 'Add the EC2 cost of a RunsOn job to its summary; a no-op elsewhere.'
runs:
using: 'composite'
steps:
- name: "RunsOn cost summary"
if: runner.environment == 'self-hosted'
uses: runs-on/action@17b59092eb37ebfdbb034460892887c09100eaa3 # v2.5.0
with:
show_costs: summary
137 changes: 137 additions & 0 deletions .github/actions/stash-restore/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
---
# apache/infrastructure-actions/stash/restore on GitHub-hosted runners. On RunsOn (the only
# self-hosted runners) multi-GB image tarballs stay in the RunsOn stack's in-region S3 cache
# bucket instead of leaving AWS as GitHub artifacts.
#
# Every RunsOn job can write anywhere in that bucket, so the bucket is not trusted: objects are
# named by their sha256, and the digest itself travels as a small ASF stash artifact, which
# GitHub scopes to the run / branch exactly like a regular stash. A blob that does not match the
# digest the ASF restore found for this run, branch and repository is never extracted. The bucket's
# lifecycle rule (S3CacheExpirationInDays) must outlive the longest retention-days of a digest
# (6 days today), or a digest hit finds no blob.
name: 'Restore stash'
description: 'Restore a stash from GitHub artifacts, or from S3 on RunsOn runners.'
inputs:
key:
description: 'Stash key.'
required: true
path:
description: >
Directory to restore into (GitHub-hosted only; the S3 tarball restores entries to the
paths they were saved from, and the restore then fails if any of them is outside this directory).
required: false
default: ${{ github.workspace }}
only-current-branch:
description: 'Do not fall back to the base branch stash.'
required: false
default: 'false'
fail-on-download:
description: 'Fail when a stash was found but could not be restored.'
required: false
default: 'false'
outputs:
stash-hit:
description: "'true' if a stash was restored, 'false' otherwise."
value: ${{ steps.s3.outputs.stash-hit || steps.artifact.outputs.stash-hit }}
runs:
using: 'composite'
steps:
- name: "Restore stash from GitHub artifacts"
id: artifact
if: runner.environment != 'self-hosted'
# yamllint disable-line rule:line-length
uses: apache/infrastructure-actions/stash/restore@c968777141a2afc98d1a09c9f6979455bfebaae3 # restore/v1.0.1
with:
key: ${{ inputs.key }}
path: ${{ inputs.path }}
only-current-branch: ${{ inputs.only-current-branch }}
fail-on-download: ${{ inputs.fail-on-download }}
- name: "Restore stash digest from GitHub artifacts"
id: digest
if: runner.environment == 'self-hosted'
# yamllint disable-line rule:line-length
uses: apache/infrastructure-actions/stash/restore@c968777141a2afc98d1a09c9f6979455bfebaae3 # restore/v1.0.1
with:
key: ${{ inputs.key }}-s3
path: ${{ runner.temp }}/stash-digest-restore/${{ inputs.key }}
only-current-branch: ${{ inputs.only-current-branch }}
fail-on-download: ${{ inputs.fail-on-download }}
- name: "Restore stash from S3"
id: s3
if: runner.environment == 'self-hosted'
shell: bash
env:
STASH_KEY: ${{ inputs.key }}
STASH_PATH: ${{ inputs.path }}
DIGEST_HIT: ${{ steps.digest.outputs.stash-hit }}
DIGEST_FILE: ${{ runner.temp }}/stash-digest-restore/${{ inputs.key }}/sha256
FAIL_ON_DOWNLOAD: ${{ inputs.fail-on-download }}
run: |
set -uo pipefail
payload="${RUNNER_TEMP}/stash-restore-$$.tar"
entries="${RUNNER_TEMP}/stash-restore-$$.entries"
miss() {
rm -f "${payload}" "${entries}"
echo "stash-hit=false" >> "${GITHUB_OUTPUT}"
if [[ "${FAIL_ON_DOWNLOAD}" == "true" && "${DIGEST_HIT}" == "true" ]]; then
echo "::error::$1"
exit 1
fi
echo "$1"
exit 0
}
if [[ "${DIGEST_HIT}" != "true" ]]; then
miss "No stash '${STASH_KEY}'"
fi
digest="$(cat "${DIGEST_FILE}")"
if [[ ! "${digest}" =~ ^[0-9a-f]{64}$ ]]; then
miss "Malformed digest for stash '${STASH_KEY}'"
fi
bucket="${RUNS_ON_S3_BUCKET_CACHE:?not running on a RunsOn runner}"
export AWS_DEFAULT_REGION="${RUNS_ON_AWS_REGION:?not running on a RunsOn runner}"
object="s3://${bucket}/cache/airflow-stash/sha256/${digest}.tar"
if ! aws s3 cp --only-show-errors "${object}" "${payload}"; then
miss "Could not download ${object} for stash '${STASH_KEY}'"
fi
if ! echo "${digest} ${payload}" | sha256sum --check --status; then
miss "${object} does not match the digest recorded for stash '${STASH_KEY}'"
fi
# GNU tar detects the compression stash-save chose.
if ! tar -xPvf "${payload}" > "${entries}"; then
miss "Could not extract ${object} for stash '${STASH_KEY}'"
fi
rm -f "${payload}"
# The S3 tarball ignores `path`: fail loudly if a caller saves and restores different
# directories, which would work on GitHub-hosted runners only.
restore_dir="$(realpath -ms "${STASH_PATH}")"
restore_dir="${restore_dir%/}"
outside=()
while IFS= read -r entry; do
[[ "${entry}" == /* ]] || entry="${GITHUB_WORKSPACE}/${entry}"
[[ "${entry}" == "${restore_dir}/"* ]] || outside+=("${entry}")
done < "${entries}"
rm -f "${entries}"
if [[ ${#outside[@]} -gt 0 ]]; then
printf '%s\n' "${outside[@]}"
echo "::error::Stash '${STASH_KEY}' restored the entries above outside of ${restore_dir}/"
exit 1
fi
echo "stash-hit=true" >> "${GITHUB_OUTPUT}"
echo "Restored stash '${STASH_KEY}' from ${object}"
Loading
Loading