| applyTo | ** |
|---|---|
| excludeAgent | coding-agent |
Use these rules when reviewing pull requests to the Apache Airflow repository.
- Scheduler must never run user code. It only processes serialized Dags. Flag any scheduler-path code that deserializes or executes Dag/task code.
- Flag any task execution code that accesses the metadata DB directly instead of through the Execution API (
/executionendpoints). - Flag any code in Dag Processor or Triggerer that breaks process isolation — these components run user code in separate processes from the Scheduler and API Server, but note that they potentially have direct metadata database access and potentially bypass JWT authentication via in-process Execution API transport. This is an intentional design choice documented in the security model, not a security vulnerability.
- Flag any provider importing core internals like
SUPERVISOR_COMMSor task-runner plumbing. Providers interact through the public SDK and execution API only.
- Flag any SQLAlchemy relationship access inside a loop without
joinedload()orselectinload()— this is an N+1 query. - Flag any query on
run_idwithoutdag_id.run_idis only unique per Dag. Queries that filter, group, partition, or join onrun_idalone will silently collide across Dags. - Flag any
session.commit()call inairflow-corecode that receives asessionparameter. Session lifecycle is managed by the caller, not the callee. - Flag any
sessionparameter that is not keyword-only (*, session) inairflow-core. - Flag any database-specific SQL (e.g.,
LATERALjoins, PostgreSQL-only functions, MySQL-only syntax) without cross-DB handling. SQL must work on PostgreSQL, MySQL, and SQLite.
- Flag any
assertin non-test code.assertis stripped in optimized Python (python -O), making it a silent no-op in production. - Flag any
time.time()used for measuring durations. Usetime.monotonic()instead —time.time()is affected by system clock adjustments. - Flag any
fromorimportstatement inside a function or method body. Imports must be at the top of the file. The only valid exceptions are: (1) circular import avoidance, (2) lazy loading for worker isolation, (3)TYPE_CHECKINGblocks. If the import is inside a function, ask the author to justify why it cannot be at module level. - Flag any
@lru_cache(maxsize=None). This creates an unbounded cache — every unique argument set is cached forever. Note:@lru_cache()without arguments defaults tomaxsize=128and is fine. - Flag any heavy import (e.g.,
kubernetes.client) in multi-process code paths that is not behind aTYPE_CHECKINGguard. - Flag any file, connection, or session opened without a context manager or
try/finally. - Flag any new
raise AirflowExceptionusage. The community has stopped adding new ones (enforced by thecheck-no-new-airflow-exceptionsprek hook) — prefer Python's standard exceptions (ValueError,TypeError,OSError), or a dedicated class in the appropriateexceptions.py. Do not suggest changing specific exceptions back toAirflowException.
- Flag any new public method or behavior without corresponding tests. Tests must cover success, failure, and edge cases.
- Flag any
unittest.TestCasesubclass. Use pytest patterns instead. - Flag any
mock.Mock()ormock.MagicMock()withoutspecorautospec. Unspec'd mocks silently accept any attribute access, hiding real bugs. - Flag any
time.sleepordatetime.now()in tests. Usetime_machinefor time-dependent tests. - Flag any issue number in test docstrings (e.g.,
"""Fix for #12345""") — test names should describe behavior, not track tickets.
- Flag any query on mapped task instances that does not filter on
map_index. Without it, queries may return arbitrary instances from the mapped set. - Flag any Execution API change without a Cadwyn version migration (CalVer format).
- Avoid
useState + useEffectto sync derived state. Use nullish coalescing or nullable override patterns instead. - Extract shared logic into custom hooks rather than copy-pasting across components.
- Flag any manual edits to files in
openapi-gen/or Task SDK generated models. These must be regenerated, not hand-edited.
Flag these patterns that indicate low-quality AI-generated contributions:
- Fabricated diffs: Changes to files or code paths that don't exist in the repository.
- Unrelated files included: Changes to files that have nothing to do with the stated purpose of the PR.
- Description doesn't match code: PR description describes something different from what the code actually does.
- No evidence of testing: Claims of fixes without test evidence, or author admitting they cannot run the test suite.
- Over-engineered solutions: Adding caching layers, complex locking, or benchmark scripts for problems that don't exist or are misunderstood.
- Narrating comments: Comments that restate what the next line does (e.g.,
# Add the item to the listbeforelist.append(item)). - Empty PR descriptions: PRs with just the template filled in and no actual description of the changes.
- For bug-fix PRs, flag if there is no regression test — a test that fails without the fix and passes with it.
- Flag any existing test modified to accommodate new behavior — this may indicate a behavioral regression rather than a genuine fix.