diff --git a/fellowship/apache-airflow/fellow-contribution/Eason09053360.md b/fellowship/apache-airflow/fellow-contribution/Eason09053360.md new file mode 100644 index 0000000..a18a8c3 --- /dev/null +++ b/fellowship/apache-airflow/fellow-contribution/Eason09053360.md @@ -0,0 +1,341 @@ +# Apache Airflow 開源貢獻紀錄 by Eason09053360(2026-02 ~ 2026-10-16) + +- GitHub:[@Eason09053360](https://github.com/Eason09053360) +- 專案:[apache/airflow](https://github.com/apache/airflow) +- Slack:https://opensource4you.slack.com/team/U0BQPAPCQ57 +- 日期:2026 年 2 月 ~ 2026 年 10 月 + +## Highlight:[#73813 Fix dateless dag.test and tasks test destroying unrelated Dag runs](https://github.com/apache/airflow/pull/73813) + +**簡介**:在本地跑不帶日期的 `dag.test()` 或 `airflow tasks test`,會把一個沒有日期的 Dag run(例如使用者從 UI 手動觸發的那次)連同它的 task instances 一起刪掉,而且不會有任何錯誤訊息。 + +**為什麼會這樣** + +Airflow 3 開始,手動和 asset 觸發的 run 可以沒有 logical date(存成 `NULL`),但 `dag.test()` 和 `airflow tasks test` 背後的程式還是把「沒給日期」當成「全部都符合」: + +1. `get_or_create_dagrun` 會先刪掉佔用同一個 logical date 的舊 run。查詢寫的是 `DagRun.logical_date == logical_date`,`logical_date` 是 `None` 時,SQLAlchemy 會產生 `IS NULL`,於是隨便抓到一個沒有日期的 run 就刪,`task_instances` 也跟著 cascade 刪掉。 +2. `DAG.test()` 在那之前還會呼叫 `clear_dags(start_date=logical_date, end_date=logical_date)`。兩個邊界都是 `None` 時,日期條件整個消失,變成這個 Dag **所有** run 的 task instance 都被 clear。 + +**修法裡的判斷** + +- **為什麼「沒有日期就跳過」是安全的**:原本刪舊 run,是為了避免撞到 `(dag_id, logical_date)` 這個 unique key。但 NULL 在 unique key 裡不會互相衝突,所以沒有日期時本來就不需要刪任何東西。 +- **`session.commit()` 改成 `session.flush()`**:airflow-core 的規範是被呼叫的函式不能 commit 呼叫端傳進來的 session,這行剛好在這個 diff 裡要移動,就一起改了。 +- **行為變化有寫清楚**:連續跑不帶日期的 `dag.test()`,現在每次都會多留一個 run,不會再刪掉上一次的。有帶 `--logical-date` 的情況維持原本的行為。 + +**怎麼發現的** + +這個 bug 是用 Claude Code 檢查程式碼時找到的,詳細經過已經記不清楚。它跟我之前修的 [#72291](https://github.com/apache/airflow/pull/72291) 是同一個指令:#72291 修的是 `airflow tasks test` 沒帶 `--env-vars` 時不會 export `AIRFLOW_TEST_MODE`;這次的問題則在同一個指令往下建立 Dag run 的地方(`task_test` → `_get_ti` → `_get_dag_run` → `get_or_create_dagrun`)。 + +**驗證**:兩個出問題的地方各補了一個回歸測試。 + +--- + +## 總覽:2026 年 2 月 – 10 月(截至 10/16) + +**Summary** + +- PR: apache/airflow merged 56 個([清單](https://github.com/apache/airflow/pulls?q=is%3Apr+author%3AEason09053360+is%3Amerged))+ 4 個 open + - 其中 22 個被 backport 到 release 分支(`v3-3-test` 14、`airflow-ctl/v0-1-test` 6、`chart/v1-2x-test` 2) +- Code Review: 24([清單](https://github.com/apache/airflow/pulls?q=is%3Apr+reviewed-by%3AEason09053360+-author%3AEason09053360)) +- Issue Triage / RC Testing: 7 + +### Merged PR 分類(依區域) + +| 分類 | 數量 | +| --- | --- | +| airflow CLI(`airflow ...`、`DAG.cli()`、`standalone`) | 21 | +| Providers(fab、edge、celery、google、cncf-kubernetes 等) | 17 | +| airflowctl | 7 | +| API server | 4 | +| Task SDK / Triggerer | 4 | +| Helm chart | 2 | +| UI(E2E 測試) | 1 | + +主軸是 **Airflow 3 遷移後留下的 CLI / airflowctl / API 正確性問題**,大多是「靜默出錯」型的 bug:exit 0 但結果是錯的、資料被默默改掉、操作其實成功但 CLI 噴 traceback等等。 + +--- + +## October 2026(截至 10/16) + +**Summary** + +- PR: 3 merged + 2 open +- Code Review: 10 +- Issue Triage: 1 + +### PR(merged) + +#### Task SDK + +- [Fix dateless dag.test and tasks test destroying unrelated Dag runs (#73813)](https://github.com/apache/airflow/pull/73813):`Bug 修正` + - `dag.test()` / `airflow tasks test` 不帶日期時,會刪掉使用者從 UI 觸發的 Dag run + - Airflow 3 的手動 / asset 觸發 run 沒有 logical date(`NULL`),但 `get_or_create_dagrun` 用 `==` 查詢,SQLAlchemy 會產生 `IS NULL`,於是刪掉任意一個 dateless run,連帶 cascade 刪掉 task instances + - `DAG.test()` 的 `clear_dags` 拿 `None` 當上下界,兩個條件都被丟掉,變成清掉這個 Dag **所有** run 的 TI + +#### airflow CLI + +- [Fix CLI --bundle-name finding no Dags in Git bundles (#73377)](https://github.com/apache/airflow/pull/73377):`Bug 修正` + - 4 個 CLI 呼叫點沒有先 `bundle.initialize()`(Git bundle 靠它 clone repo),`dags list --local --bundle-name X` 回傳空清單卻 exit 0、`list-import-errors` 回報「沒有錯誤」 + - `tasks test` / `dags test` / `tasks clear` 則退回掃描所有 bundle,可能拿到**另一個 bundle 裡同名的 Dag** + - [#53699](https://github.com/apache/airflow/pull/53699) 只修了當時被回報的那一處,這次把其餘呼叫點一起補齊 + +#### airflowctl + +- [Fix airflowctl pools export/import dropping pool team ownership (#73132)](https://github.com/apache/airflow/pull/73132):`Bug 修正` `backport: airflow-ctl/v0-1-test` + - `airflowctl pools export` → `import --action-on-existing-key overwrite` 會清掉 pool 的 team 歸屬,而且回報成功 + - multi-team 部署用 `team_name` 決定誰能用這個 pool;export 沒寫出這個欄位,bulk 請求又把缺少的欄位序列化成 `"team_name": null` 覆寫回去 + - 舊的 `airflow pools export / import` 本來就有處理,只有照著 deprecation 提示遷移到 airflowctl 的使用者會中招 + +### PR(open) + +#### API server + +- [Stop the JWT revocation check stalling the API server event loop (#74364)](https://github.com/apache/airflow/pull/74364):`Bug 修正` + - JWT revocation 檢查在 event loop 上做同步 DB 查詢,UI polling、worker heartbeat、airflowctl 全部排在後面,connection pool 滿了就逐一 timeout + +#### Dag processing + +- [Fix sync-perm applying permissions from every stored Dag version (#74360)](https://github.com/apache/airflow/pull/74360):`Bug 修正` + - `airflow sync-perm --include-dags` 對每個 Dag 依每個版本各 sync 一次且無排序,已撤銷的 role 權限可能被舊版本重新授予 + +### Code Review + +- [Add --asset-ids filtering to db clean (#74498)](https://github.com/apache/airflow/pull/74498) + - `db clean --asset-ids` 會連同 `asset_dag_run_queue` 刪掉還在排隊的舊 asset event,排程在 `a & b` 上的 Dag 等到 `b` 來了也不會跑 + - 指出 [#74495](https://github.com/apache/airflow/pull/74495) 對同樣情境預設是拒絕(409),建議比照處理 +- [Snowflake oauth2 password (fork repository fix) (#74804)](https://github.com/apache/airflow/pull/74804) + - `grant_type` 只在 extra 有 `grant_type` 或 `refresh_token` 時才設定,兩者都沒有的既有 OAuth 連線會從原本的明確錯誤訊息變成 `KeyError: 'grant_type'` + - `get_oauth_token(grant_type="client_credentials")` 也會一起壞 +- [Chart: Bump PgBouncer to 1.25.2 and exporter to 0.21.0 to fix CVEs (#74647)](https://github.com/apache/airflow/pull/74647) + - 指出 PgBouncer 1.25.2 仍有 1.26.x 才修掉的未認證 CVE,請作者在 PR 描述註明 +- [Fix Cloud Composer system test external task sensors (#74786)](https://github.com/apache/airflow/pull/74786) + - 本地驗證後 approve + - 另外指出範例裡的 `datetime.now()` 是本地時間卻帶 `Z` 後綴送給 API,在 UTC-7 的 worker 上時間窗會早 7 小時、抓不到剛觸發的 run,而這段是會被使用者照抄的文件範例 +- [Recover the revoked-token check from a stale DB connection (fixes idle-timeout 500) (#71444)](https://github.com/apache/airflow/pull/71444) + - 指出 FAB 3.7.0([#68100](https://github.com/apache/airflow/pull/68100))之後 `deserialize_user` 已會關閉 session,請作者確認 issue 在新版是否仍能重現 +- Approve:[#74778](https://github.com/apache/airflow/pull/74778)(本地驗證), [#74645](https://github.com/apache/airflow/pull/74645), [#74816](https://github.com/apache/airflow/pull/74816), [#74243](https://github.com/apache/airflow/pull/74243) +- 其他:[#74015](https://github.com/apache/airflow/pull/74015) + +### Issue Triage + +- [AIP-44 Migrate DagModel.deactivate_deleted_dags to Internal API (#29533)](https://github.com/apache/airflow/issues/29533) + - 2023 年的 issue 一直沒關:查出實際已由 [#29534](https://github.com/apache/airflow/pull/29534) 完成(2.6.0 釋出),GitHub 只自動關了 `closes` 寫到的 #29532 + - AIP-44 Internal API 也已在 3.0.0 整個移除([#44502](https://github.com/apache/airflow/pull/44502)、[#44549](https://github.com/apache/airflow/pull/44549)),建議關閉 + +--- + +## September 2026 + +**Summary** + +- PR: 29 merged + 2 open +- Code Review: 14 +- Issue Triage / RC Testing: 3 + +### PR(merged) + +#### airflow CLI + +- [Prevent Dag CLI subcommands from being silently dropped (#72340)](https://github.com/apache/airflow/pull/72340):`Bug 修正` `backport: v3-3-test` + - `DAG.cli()`(`python my_dag.py ...`)用過期的 command name 挑 subcommand,讓 `dags backfill`、`tasks run` 靜默消失 + - `args` 用 generator 只能走一次,parser 重建後 `dags pause` 參數從 6 個掉到 2 個 +- [Fix DAG.cli() crashing on dags pause and unpause (#72109)](https://github.com/apache/airflow/pull/72109):`Bug 修正` `backport: v3-3-test` + - `python my_dag.py dags pause / unpause` 直接 `TypeError` +- [Fix DAG.cli() crashing on dags test --show-dagrun (#72810)](https://github.com/apache/airflow/pull/72810):`Bug 修正` `backport: v3-3-test` +- [Stop airflow standalone leaking components when one fails to start (#72464)](https://github.com/apache/airflow/pull/72464):`Bug 修正` `backport: v3-3-test` + - 一個元件啟動失敗時,shutdown loop 第一個 `stop()` 就丟例外,其餘三個元件在 standalone 結束後繼續連著 metadata DB 跑 +- [Fix airflow standalone announcing readiness before the API server is up (#73025)](https://github.com/apache/airflow/pull/73025):`Bug 修正` + - 「Airflow is ready」在 API server 還沒 bind port 前就印出 + - 追到是 [#46942](https://github.com/apache/airflow/pull/46942) 刪 webserver 時把 port 檢查一起弄丟 +- [Stop airflow providers get --full mutating cached provider metadata (#72346)](https://github.com/apache/airflow/pull/72346):`Bug 修正` `backport: v3-3-test` +- [Trace the dag-processor job instead of its parent process with memray (#72367)](https://github.com/apache/airflow/pull/72367):`Bug 修正` `backport: v3-3-test` +- [Fix airflow info --file-io uploading an empty report (#72707)](https://github.com/apache/airflow/pull/72707):`Bug 修正` `backport: v3-3-test` +- [Allow airflow jobs check --allow-multiple with --limit 0 (#72677)](https://github.com/apache/airflow/pull/72677):`Bug 修正` `backport: v3-3-test` +- [Reject non-numeric --limit values in airflow dags list-jobs (#72891)](https://github.com/apache/airflow/pull/72891):`Bug 修正` `backport: v3-3-test` +- [Fix airflow dags list --columns help showing wrong default columns (#72607)](https://github.com/apache/airflow/pull/72607):`Bug 修正` +- [Remove ignored --output flag from airflow pools set and delete (#72833)](https://github.com/apache/airflow/pull/72833):`Bug 修正` +- [Fix airflow teams list --output json printing prose when no teams exist (#72945)](https://github.com/apache/airflow/pull/72945):`Bug 修正` +- [Mask the SQLite database path in airflow info --anonymize (#73179)](https://github.com/apache/airflow/pull/73179):`Bug 修正` +- [Fix airflow db check reporting one fewer retry than it will make (#72708)](https://github.com/apache/airflow/pull/72708):`Bug 修正` + +#### airflowctl + +- [Fix airflowctl backfill pause/unpause/cancel always failing with 405 (#73282)](https://github.com/apache/airflow/pull/73282):`Bug 修正` `backport: airflow-ctl/v0-1-test` + - `airflowctl backfill pause / unpause / cancel` 從來沒有成功過:server 是 `PUT`、client 送 `POST`,永遠 405;operator 無法從 CLI 停掉失控的 backfill + - 一直沒被發現是因為測試用的 `httpx.MockTransport` 沒有 route table,任何 method 都回 200 → 補上 method assertion +- [Fix airflowctl commands crashing instead of printing their result (#72675)](https://github.com/apache/airflow/pull/72675):`Bug 修正` `backport: airflow-ctl/v0-1-test` + - 5 個自動產生的指令在 server 端已經執行成功後才 crash + - `--output` 只宣告給 10 個 CRUD 動詞,其他指令(`connections test`、`assets materialize`、`backfill *`)在印結果時 `AttributeError` +- [Fix a bad retry env var taking down the whole airflowctl CLI (#72429)](https://github.com/apache/airflow/pull/72429):`Bug 修正` `backport: airflow-ctl/v0-1-test` + - module scope 的 `int()` 在 import 時就炸,一個寫錯的環境變數讓整個 airflowctl 無法啟動;負數的 wait 更糟,會在隨機一部分 retry 時才從 tenacity 丟例外 + - warning 刻意寫到 stderr 而不是 logger,避免汙染 `-o json > file` 的輸出 +- [Fix airflowctl tracebacks on redirects and non-JSON error bodies (#73307)](https://github.com/apache/airflow/pull/73307):`Bug 修正` `backport: airflow-ctl/v0-1-test` + - 遇到 SSO proxy redirect / ingress HTML 錯誤頁時,從 traceback 改成一行可行動的錯誤訊息 +- [Fix airflowctl connections test failing on stored connections (#73098)](https://github.com/apache/airflow/pull/73098):`Bug 修正` `backport: airflow-ctl/v0-1-test` +- [Make airflowctl command generation safe to read more than once (#73097)](https://github.com/apache/airflow/pull/73097):`Bug 修正` + +#### API server + +- [Fix bulk endpoints returning 500 for a malformed action entry (#73453)](https://github.com/apache/airflow/pull/73453):`Bug 修正` `backport: v3-3-test` + - 5 個 bulk endpoint(variables / pools / connections / Dag runs / TIs)對格式錯誤的 action 回 500 + - pydantic 的 callable `Discriminator` 拿到未驗證的原始輸入且不包例外 → 改為回 422 並列出可接受的 tag +- [API: Fix prefix pattern search returning rows without the prefix (#73520)](https://github.com/apache/airflow/pull/73520):`Bug 修正` + - prefix 最後一字是 `9` / `z` / `Z` 時上界會退回較短的 prefix,搜 `dag_9` 會拿到 `dag_abc` + +#### Providers + +- [Fix airflow roles import crash on a role without permissions (#72796)](https://github.com/apache/airflow/pull/72796):`Bug 修正`(fab) +- [Fix invalid command path in permissions-cleanup help examples (#73028)](https://github.com/apache/airflow/pull/73028):`Bug 修正`(fab) +- [Fix airflow celery stop crashing on stale PID file (#72817)](https://github.com/apache/airflow/pull/72817):`Bug 修正`(celery) +- [Fix airflow edge list-workers always showing null concurrency (#72959)](https://github.com/apache/airflow/pull/72959):`Bug 修正`(edge) + +#### Helm chart + +- [Fix StatsD not restarting when overrideMappings or cache.ttl changes (#72633)](https://github.com/apache/airflow/pull/72633):`Bug 修正` `backport: chart/v1-2x-test` + - StatsD 改 `overrideMappings` 或 `cache.ttl` 後 pod 不會重啟,ConfigMap 變了但設定沒生效 +- [Helm: Point flower extraNetworkPolicies deprecation at the real key (#72052)](https://github.com/apache/airflow/pull/72052):`Bug 修正` `backport: chart/v1-2x-test` + +### PR(open) + +- [Batch Team lookups when syncing Dag bundles to the database (#73154)](https://github.com/apache/airflow/pull/73154):`效能` + - Dag processor 啟動時 `team` 查詢 N+1 → 批次化 +- [Fix scheduler refusing to start when [scheduler] only_idle is enabled (#73141)](https://github.com/apache/airflow/pull/73141):`Bug 修正` + - 開啟文件上的 `[scheduler] only_idle` 會讓 scheduler 直接起不來:`--only-idle` 的預設值在 import 時就從 config 讀,guard 分不出是使用者打的還是 config 給的 + - 一旦 config 開了,command line 也關不掉,跟一般「command line 蓋過 config」的優先順序相反 + +### Code Review + +- [Fix stale DAGs affecting source authorization (#73292)](https://github.com/apache/airflow/pull/73292) + - 指出權限檢查漏洞:當請求的 Dag 本身也是 stale(檔案已刪),過濾後 `file_dag_ids` 為空、檢查被跳過,只能讀這一個 Dag 的人可以拿到整個檔案的原始碼 +- [Stop swallowing unexpected keyring errors when saving airflowctl credentials (#70991)](https://github.com/apache/airflow/pull/70991)(merged) + - 拿掉 handler 後 `None` token 會直接進 keyring,三個平台行為各不同:`keyrings.alt` 丟 `TypeError`、macOS 丟 `PasswordSetError`、Windows 默默存入字串 `"None"` +- [Ensure explicit UTF-8 encoding in prek scripts for Windows compatibility (#73679)](https://github.com/apache/airflow/pull/73679) + - 讀改成 UTF-8 但寫仍用 locale encoding,在 Windows 上反而更糟:`pyproject.toml` 的 `—` 變成非法 byte `0x97`,`AGENTS.md` 的 `→` 直接 `UnicodeEncodeError` +- [Mask sensitive values in airflow config update dry-run output (#73265)](https://github.com/apache/airflow/pull/73265) + - 用 Airflow 2 風格的 `airflow.cfg` 實測,`smtp_password` 等舊版敏感欄位在 dry-run 仍明文輸出 +- [Fix airflow variables import exiting 0 even when imports fail (#72958)](https://github.com/apache/airflow/pull/72958) + - `pytest.raises(match=)` 是 `re.search`,舊訊息也會 match,revert 修正後這個 assertion 仍然通過 +- [Report missing required API fields in airflowctl CLI (#73317)](https://github.com/apache/airflow/pull/73317) + - Pydantic 的 required 不等於 non-nullable,argparse 只該強制 required 且 non-nullable 的欄位 +- [API: Translate domain ValueError in Task State Store route (#73753)](https://github.com/apache/airflow/pull/73753) + - 建議 `autospec=True` 讓測試能抓到參數名稱打錯;並指出 PR 描述的 500 情境實際上會先被 404 擋掉 +- 找出重複的 PR:[#73759](https://github.com/apache/airflow/pull/73759), [#73771](https://github.com/apache/airflow/pull/73771)(包含一個被 open PR 上限清掉、但根因分析更完整的 [#72919](https://github.com/apache/airflow/pull/72919)) +- 驗證 revert 修正後新測試會 fail:[#72920](https://github.com/apache/airflow/pull/72920) +- Approve:[#72859](https://github.com/apache/airflow/pull/72859), [#73606](https://github.com/apache/airflow/pull/73606), [#73939](https://github.com/apache/airflow/pull/73939) +- 其他:[#69645](https://github.com/apache/airflow/pull/69645) + +### Issue Triage / RC Testing + +- [Status of testing of Apache Airflow 3.3.2rc1 (#73089)](https://github.com/apache/airflow/issues/73089) + - 在官方 Docker image 上裝 PyPI 的 RC,用 3.3.1 當對照組,自己的 11 個 backport 全部逐項驗證 +- [Status of testing Providers that were prepared on September 22, 2026 (#73658)](https://github.com/apache/airflow/issues/73658) + - 驗證 celery / edge3 / fab 共 4 項,用前一版當對照組 + - 註明沒測到的範圍:SQLite 以外的 backend、[#72817](https://github.com/apache/airflow/pull/72817) 的 race condition 只有 unit test +- [[AIP-94] airflowctl tasks: add state command (#66174)](https://github.com/apache/airflow/issues/66174)(good first issue) + - 指出 [#71206](https://github.com/apache/airflow/pull/71206) 和 [#72163](https://github.com/apache/airflow/pull/72163) 做的是同一件事,前者早三週開且已被 approve,建議收斂到前者 + - 之後 #72163 關閉、#71206 merged,issue 跟著關閉 + +--- + +## August 2026 + +**Summary** + +- PR: 9 merged +- Issue Triage / RC Testing: 1 + +### PR + +#### airflow CLI + +- [Show each Dag only once in airflow dags list (#70934)](https://github.com/apache/airflow/pull/70934):`Bug 修正` `backport: v3-3-test` + - `airflow dags list` 每個 Dag 依版本數重複顯示(closes [#60594](https://github.com/apache/airflow/issues/60594)) + - 接手先前被 stale bot 關掉、沒人 review 的 [#60637](https://github.com/apache/airflow/pull/60637) +- [Stop variables export/import from silently corrupting values (#70944)](https://github.com/apache/airflow/pull/70944):`Bug 修正` `backport: v3-3-test` + - `airflow variables export` → `import` 來回一次就把值改掉:`{"value": 1, "other": 2}` 會被當成 envelope 只剩 `1`;JSON 字串匯出後不再是合法 JSON,`deserialize_json=True` 開始炸 + - 只改 export 端讓它無損,手寫的 import 檔行為完全不變 +- [Fix airflow config lint staying silent on conditional removal rules (#70977)](https://github.com/apache/airflow/pull/70977):`Bug 修正` `backport: v3-3-test` + - `config lint` 對條件式移除規則完全沒輸出,`email.email_backend`、`elasticsearch.log_id_template` 都回報「No issues found」 +- [Export AIRFLOW_TEST_MODE from airflow tasks test without --env-vars (#72291)](https://github.com/apache/airflow/pull/72291):`Bug 修正` `backport: v3-3-test` + - 不帶 `--env-vars` 時不會 export `AIRFLOW_TEST_MODE`;帶 `--env-vars '{}'` 也沒用,因為空 dict 是 falsy +- [Stop airflow config update from writing a backup during dry-run (#70979)](https://github.com/apache/airflow/pull/70979):`Bug 修正` + +#### Providers + +- [Stop dumping every Dag to stdout when syncing FAB permissions (#70939)](https://github.com/apache/airflow/pull/70939):`Bug 修正`(fab) + - `sync-perm --include-dags` 會把每個 Dag 整個 dump 到 stdout +- [Strip only the literal properties/ prefix from GA property link IDs (#70919)](https://github.com/apache/airflow/pull/70919):`Bug 修正`(google) + - `lstrip("properties/")` 是去掉字元集合而不是 prefix,把 property ID 開頭的 `s` 吃掉:`properties/s123` 存成 `123` +- [Fix BteqOperator declaring template_fields as a bare string (#70862)](https://github.com/apache/airflow/pull/70862):`Bug 修正`(teradata) +- [Fix operators declaring template_fields/template_ext as bare strings (#70916)](https://github.com/apache/airflow/pull/70916):`Bug 修正`(telegram、edge) + +### Issue Triage / RC Testing + +- [Status of testing Providers that were prepared on August 06, 2026 (#71246)](https://github.com/apache/airflow/issues/71246) + - 在官方 Docker image 上裝 PyPI 的 RC,驗證 fab / teradata / google 共 3 項 + +--- + +## March 2026 + +**Summary** + +- PR: 3 merged + +### PR + +#### Providers + +- [Fix make SFTPOperator delete idempotent (return a warning instead of a error when file is already absent) (#62639)](https://github.com/apache/airflow/pull/62639):`Bug 修正`(sftp) + - closes [#56190](https://github.com/apache/airflow/issues/56190) +- [docs: add DAG documentation for example_bash_decorator (#62948)](https://github.com/apache/airflow/pull/62948):`文件`(standard) + +#### Task SDK + +- [cleanup completed TODO (#62177)](https://github.com/apache/airflow/pull/62177):`重構` + +--- + +## February 2026 + +**Summary** + +- PR: 12 merged +- Issue Triage / RC Testing: 2 + +### PR + +#### Providers + +- [feat(fab): Add configurable role key for Azure OAuth groups (#61585)](https://github.com/apache/airflow/pull/61585):`新功能`(fab) + - Azure AD OAuth 可設定用 `groups` claim 對應 Airflow role(closes [#61567](https://github.com/apache/airflow/issues/61567)) +- [Add Filtering to Edge UI Plugin Jobs Page (#61934)](https://github.com/apache/airflow/pull/61934):`新功能`(edge) + - Edge UI 的 Jobs 頁面加上篩選(closes [#61920](https://github.com/apache/airflow/issues/61920)) +- [Fix ModuleNotFoundError in kubernetes cleanup cronjob (#61673)](https://github.com/apache/airflow/pull/61673):`Bug 修正`(cncf-kubernetes) + - closes [#61360](https://github.com/apache/airflow/issues/61360),標為 `priority:critical` +- [Migrate jdbc connection UI metadata to YAML (#62427)](https://github.com/apache/airflow/pull/62427)、[Migrate Jenkins connection UI metadata to YAML (#62432)](https://github.com/apache/airflow/pull/62432)、[Migrate airbyte connection UI metadata to YAML (#62426)](https://github.com/apache/airflow/pull/62426):`重構` + - [#62345](https://github.com/apache/airflow/issues/62345) 的子任務,認領 jdbc、jenkins、airbyte 三個 provider +- [cleanup test_databricks_workflow (#61907)](https://github.com/apache/airflow/pull/61907):`測試`(databricks) + +#### UI + +- [Add E2E tests for Plugins page (#61057)](https://github.com/apache/airflow/pull/61057):`測試` + - Plugins 頁面 E2E 測試,用 Page Object Model,跑 Chromium / Firefox / WebKit(closes [#60571](https://github.com/apache/airflow/issues/60571)) + +#### API server + +- [Fix GZipMiddleware with correct comment placement (#61538)](https://github.com/apache/airflow/pull/61538):`重構` +- [Use contextlib.suppress instead of try-except-pass (#62156)](https://github.com/apache/airflow/pull/62156):`重構` + +#### Task SDK / Triggerer + +- [Fix serde recursion limit test by using correct MAX_RECURSION_DEPTH (#61182)](https://github.com/apache/airflow/pull/61182):`測試` + - closes [#51915](https://github.com/apache/airflow/issues/51915) +- [Fix ASYNC110 violation in TriggerRunner (#61760)](https://github.com/apache/airflow/pull/61760):`重構` + +### Issue Triage / RC Testing + +- [Status of testing Providers that were prepared on February 10, 2026 (#61766)](https://github.com/apache/airflow/issues/61766) + - 驗證 cncf-kubernetes 的 [#61673](https://github.com/apache/airflow/pull/61673) +- [Update installers improvement (#44062)](https://github.com/apache/airflow/issues/44062) + - 指出 [#54864](https://github.com/apache/airflow/pull/54864) 已經處理掉這個 issue,maintainer 確認後關閉