Repository navigation
Conversation
|
Both red checks look unrelated to this PR. Details in case it saves anyone a dig:
That hook's
Chromium and Firefox both pass on this same commit; only WebKit fails, on a backfill column lookup and two menu-click timeouts: There is no UI, i18n or backfill code in this PR — the only UI files are the generated client, whose whole diff is the 400/404 response types for the two endpoints above. Happy to rebase if that helps it re-run. |
|
Let's just re-run the UI formatting checks to fix the static checks CI |
A route's `responses=` block is the only thing the generated OpenAPI spec and its clients have to model error responses, but the check added in apache#71647 only looked at statuses a handler raised directly. Most route code reaches its error paths through a helper, so the statuses that matter most to a client were the ones the check could not see, and six of them were undeclared across the public, UI and execution APIs. Calls are followed from a handler's body only. A route decorator's `Depends(...)` security dependencies resolve to functions that raise 400 on an invalid identifier, and those statuses come from the router rather than the route, so following them would report a status the route is not responsible for declaring.
efb6148 to
f8e74f9
Compare
|
Thanks for the approval! I had a dig before re-running, and the static check turned out not to be a UI thing at the time. The only hook failing was A re-run wouldn't have picked that up either, which took me a bit to work out. Re-runs reuse the merge commit from the original event, so it would just rebuild the same tree. Our run started about ten hours before #74028 landed, so the fix wasn't there yet whichever way we ran it. Rebasing was the only way in. So: rebased onto main. The go-sdk drift is gone and WebKit passed this time. Static checks is still red, but it's a different hook now and still not from this PR. This PR itself is green locally on the new base: 0 violations, 36 hook tests passing, mypy clean, and regenerating the specs and UI client produced no diff. |
|
Main CI fix was merged. Updated to branch to restart the CI with that fix. |
0c33c84 to
126ed58
Compare
|
I don't have merge permissions on the repo, so I can't take it from here. Would one of you be able to merge when you get a chance? It's approved, and the lint fix it was waiting on went in as #74402. Thanks for the reviews, and for the branch update earlier. |
Follow-up to #71647, which added
check-openapi-exception-doc-in-syncbut only inspected statuses a handler raised in its own body. Review on that PR asked for nested resolution, since most route code reaches its error paths through a helper:Those are exactly the statuses a client is most likely to hit and least likely to have a model for. Following helper calls found six still undeclared:
PUT /dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/state-store/{key}400_resolve_expires_at— a negativedefault_retention_daysGET /ui/calendar/{dag_id}404get_latest_version_of_dag— the Dag does not existGET /execution/hitlDetails/{task_instance_id}404_check_hitl_detail_existsPATCH /execution/hitlDetails/{task_instance_id}404_check_hitl_detail_existsGET /execution/task-instances/count404_get_group_tasks— unknown task groupGET /execution/task-instances/states404_get_group_tasks— unknown task groupThe first one is worth calling out:
_resolve_expires_at's own docstring already says "Negative values raise HTTP 400", so that response was documented in prose and absent from the spec at the same time.Two public/UI endpoints gain error models their clients had no type for; the execution API changes have no committed spec artifact.
Why plain
astand not LibCSTReview suggested LibCST's
FullyQualifiedNameProvider. I measured its two advantages against this package before adding the dependency, and neither applies here:grep -rE "^from \.+" airflow-core/src/airflow/api_fastapireturns nothing. There are none to resolve.TaskInstance as TI), never for functions that raiseHTTPException.ast.ImportFromalready exposesasname, which is what this resolver keys on.Meanwhile
libcst.parse_moduleis 17.8x slower thanast.parseover the 68 route files (599 ms vs 34 ms), before counting the imported modules a call graph also has to parse, andFullyQualifiedNameProviderneeds aMetadataWrapperwith repository-level resolution on top of that. For a hook that runs on every commit that cost buys no additional resolution power in this package.Both approaches find the same six statuses. I went with
astand kept the dependency surface unchanged. Happy to switch if relative imports or aliased helpers show up here later — the resolver is one function, and the tests pin the behaviour either way.About the check
The conservative posture from #71647 is unchanged — it gates CI, so it under-reports rather than over-reports:
dependencies=[Depends(requires_access_dag(...))]resolves to functions that raise400on an invalid identifier, and treating those as the route's own would have produced nine false positives. The router supplies those statuses, not the route.MAX_CALL_DEPTH(3), and a repeated name terminates the walk, so mutual recursion cannot loop.401,403and422are still never required, and anything unresolvable is skipped rather than guessed at.Verification
uv run --project scripts pytest scripts/tests/ci/prek/test_check_openapi_exception_doc_in_sync.py— 36 passedprek run check-openapi-exception-doc-in-sync --all-files— Passed, 0 violations remainingprek run --stage pre-commit --files <the 10 changed files>— exit 0, includingmypy for scriptspytest airflow-core/tests/unit/api_fastapi/execution_api— 669 passed, 4 skipped (postgres/mysql-only)Was generative AI tooling used to co-author this PR?