Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,40 @@ repos:
files: ^go-sdk/
types: [go]
language: golang
- id: ts-compile-lint-ui
name: Compile / format / lint UI
description: TS types generation / ESLint / Prettier new UI files
language: node
files: |
(?x)
^airflow-core/src/airflow/ui/.*\.(js|ts|tsx|yaml|css|json)|
^airflow-core/src/airflow/api_fastapi/core_api/openapi/.*\.yaml$|
^airflow-core/src/airflow/api_fastapi/auth/managers/simple/openapi/v1.*\.yaml$
exclude: |
(?x)
^airflow-core/src/airflow/ui/node-modules/.*|
^airflow-core/src/airflow/ui/.pnpm-store
entry: ./scripts/ci/pre_commit/ts_compile_lint_ui.py
additional_dependencies: ['pnpm@9.7.1']
pass_filenames: true
require_serial: true
- id: ts-compile-lint-simple-auth-manager-ui
name: Compile / format / lint simple auth manager UI
description: TS types generation / ESLint / Prettier new UI files
language: node
files: |
(?x)
^airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/.*\.(js|ts|tsx|yaml|css|json)|
^airflow-core/src/airflow/api_fastapi/core_api/openapi/.*\.yaml$|
^airflow-core/src/airflow/api_fastapi/auth/managers/simple/openapi/v1.*\.yaml$
exclude: |
(?x)
^airflow-core/src/airflow/api_fastapi/node-modules/.*|
^airflow-core/src/airflow/api_fastapi/.pnpm-store
entry: ./scripts/ci/pre_commit/ts_compile_lint_simple_auth_manager_ui.py
additional_dependencies: ['pnpm@9.7.1']
pass_filenames: true
require_serial: true
## ADD MOST PRE-COMMITS ABOVE THAT LINE
# The below pre-commits are those requiring CI image to be built
- id: mypy-dev
Expand Down Expand Up @@ -1406,20 +1440,6 @@ repos:
entry: ./scripts/ci/pre_commit/check_i18n_json.py
additional_dependencies: ['rich>=12.4.4']
pass_filenames: false
- id: ts-compile-format-lint-ui
name: Compile / format / lint UI
description: TS types generation / ESLint / Prettier new UI files
language: node
types_or: [javascript, ts, tsx, yaml, css, json]
files: |
(?x)
^airflow-core/src/airflow/ui/|
^airflow-core/src/airflow/api_fastapi/core_api/openapi/.*\.yaml$|
^airflow-core/src/airflow/api_fastapi/auth/managers/simple/ui/|
^airflow-core/src/airflow/api_fastapi/auth/managers/simple/openapi/v1.*\.yaml$
entry: ./scripts/ci/pre_commit/compile_lint_ui.py
additional_dependencies: ['pnpm@9.7.1']
pass_filenames: false
- id: check-provider-yaml-valid
name: Validate provider.yaml files
entry: ./scripts/ci/pre_commit/check_provider_yaml_files.py
Expand Down
4 changes: 3 additions & 1 deletion contributing-docs/08_static_code_checks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,9 @@ require Breeze Docker image to be built locally.
+-----------------------------------------------------------+--------------------------------------------------------+---------+
| trailing-whitespace | Remove trailing whitespace at end of line | |
+-----------------------------------------------------------+--------------------------------------------------------+---------+
| ts-compile-format-lint-ui | Compile / format / lint UI | * |
| ts-compile-lint-simple-auth-manager-ui | Compile / format / lint simple auth manager UI | |
+-----------------------------------------------------------+--------------------------------------------------------+---------+
| ts-compile-lint-ui | Compile / format / lint UI | |
+-----------------------------------------------------------+--------------------------------------------------------+---------+
| update-black-version | Update black versions everywhere (manual) | |
+-----------------------------------------------------------+--------------------------------------------------------+---------+
Expand Down
86 changes: 45 additions & 41 deletions dev/breeze/doc/images/output_static-checks.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion dev/breeze/doc/images/output_static-checks.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ee8959251523eb709f6691c49563ecbd
ac247e5230b4d84d3bae755149c945f7
3 changes: 2 additions & 1 deletion dev/breeze/src/airflow_breeze/pre_commit_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@
"ruff-format",
"shellcheck",
"trailing-whitespace",
"ts-compile-format-lint-ui",
"ts-compile-lint-simple-auth-manager-ui",
"ts-compile-lint-ui",
"update-black-version",
"update-breeze-cmd-output",
"update-breeze-readme-config-hash",
Expand Down
3 changes: 2 additions & 1 deletion dev/breeze/src/airflow_breeze/utils/selective_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,8 @@ def skip_pre_commits(self) -> str:
self._matching_files(FileGroupForCi.UI_FILES, CI_FILE_GROUP_MATCHES)
or self._matching_files(FileGroupForCi.API_CODEGEN_FILES, CI_FILE_GROUP_MATCHES)
):
pre_commits_to_skip.add("ts-compile-format-lint-ui")
pre_commits_to_skip.add("ts-compile-lint-ui")
pre_commits_to_skip.add("ts-compile-lint-simple-auth-manager-ui")
if not self._matching_files(FileGroupForCi.ALL_PYTHON_FILES, CI_FILE_GROUP_MATCHES):
pre_commits_to_skip.add("flynt")
if not self._matching_files(
Expand Down
21 changes: 13 additions & 8 deletions dev/breeze/tests/test_selective_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@

ALL_SKIPPED_COMMITS_ON_NO_CI_IMAGE = (
"check-provider-yaml-valid,flynt,identity,lint-helm-chart,mypy-airflow-core,mypy-airflow-ctl,"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,"
"ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
)

ALL_SKIPPED_COMMITS_BY_DEFAULT_ON_ALL_TESTS_NEEDED = (
Expand All @@ -121,7 +122,7 @@

ALL_SKIPPED_COMMITS_IF_NO_UI = (
"identity,mypy-airflow-core,mypy-airflow-ctl,mypy-dev,mypy-devel-common,"
"mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui"
"mypy-providers,mypy-task-sdk,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
)
ALL_SKIPPED_COMMITS_IF_NO_HELM_TESTS = (
"identity,lint-helm-chart,mypy-airflow-core,mypy-airflow-ctl,mypy-dev,mypy-devel-common,"
Expand All @@ -130,23 +131,26 @@

ALL_SKIPPED_COMMITS_IF_NO_UI_AND_HELM_TESTS = (
"identity,lint-helm-chart,mypy-airflow-core,mypy-airflow-ctl,mypy-dev,mypy-devel-common,"
"mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui"
"mypy-providers,mypy-task-sdk,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
)

ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_AND_UI = (
"check-provider-yaml-valid,identity,mypy-airflow-core,mypy-airflow-ctl,"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,"
"ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
)

ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS = (
"check-provider-yaml-valid,identity,lint-helm-chart,mypy-airflow-core,mypy-airflow-ctl,"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,"
"ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
)


ALL_SKIPPED_COMMITS_IF_NO_PROVIDERS_UI_AND_HELM_TESTS = (
"check-provider-yaml-valid,identity,lint-helm-chart,mypy-airflow-core,mypy-airflow-ctl,"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,"
"ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
)

ALL_SKIPPED_COMMITS_IF_NO_CODE_PROVIDERS_AND_HELM_TESTS = (
Expand All @@ -156,7 +160,8 @@

ALL_SKIPPED_COMMITS_IF_NOT_IMPORTANT_FILES_CHANGED = (
"check-provider-yaml-valid,flynt,identity,lint-helm-chart,mypy-airflow-core,mypy-airflow-ctl,"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui"
"mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,"
"ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui"
)


Expand Down Expand Up @@ -1215,7 +1220,7 @@ def assert_outputs_are_printed(expected_outputs: dict[str, str], stderr: str):
"run-tests": "true",
"run-amazon-tests": "false",
"docs-build": "true",
"skip-pre-commits": "check-provider-yaml-valid,flynt,identity,mypy-airflow-core,mypy-airflow-ctl,mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,ts-compile-format-lint-ui",
"skip-pre-commits": "check-provider-yaml-valid,flynt,identity,mypy-airflow-core,mypy-airflow-ctl,mypy-dev,mypy-devel-common,mypy-providers,mypy-task-sdk,ts-compile-lint-simple-auth-manager-ui,ts-compile-lint-ui",
"upgrade-to-newer-dependencies": "false",
"core-test-types-list-as-strings-in-json": None,
"providers-test-types-list-as-strings-in-json": None,
Expand Down
54 changes: 54 additions & 0 deletions scripts/ci/pre_commit/common_precommit_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
import subprocess
import sys
import textwrap
import time
from collections.abc import Generator
from contextlib import contextmanager
from pathlib import Path
from tempfile import NamedTemporaryFile, _TemporaryFileWrapper

AIRFLOW_ROOT_PATH = Path(__file__).parents[3].resolve()
AIRFLOW_CORE_ROOT_PATH = AIRFLOW_ROOT_PATH / "airflow-core"
Expand All @@ -47,6 +51,56 @@
console = None # type: ignore[assignment]


@contextmanager
def temporary_tsc_project(
tsconfig_path: Path, files: list[str]
) -> Generator[_TemporaryFileWrapper, None, None]:
"""
Create a temporary tsconfig.json file that extends the main tsconfig.json file.
This is needed to run TypeScript compiler with specific files included only
"""
if not tsconfig_path.exists():
raise RuntimeError(f"Cannot find {tsconfig_path}")
temp_tsconfig_path = NamedTemporaryFile(mode="wt", suffix=".json", dir=tsconfig_path.parent, delete=True)
files_joined = ", ".join([f'"{file}"' for file in files])
content = f'{{"extends": "./{tsconfig_path.name}", "include": [{files_joined}]}}'
if console:
console.print(f"[magenta]Creating temporary tsconfig.json at {temp_tsconfig_path.name}[/]")
console.print(content)
else:
print(f"Creating temporary tsconfig.json at {temp_tsconfig_path.name}", file=sys.stderr)
print(content, file=sys.stderr)
temp_tsconfig_path.write(content)
temp_tsconfig_path.flush()
yield temp_tsconfig_path


def run_command(*args, **kwargs) -> None:
"""
Run command with given arguments and return the result.
"""
cmd = " ".join([shlex.quote(arg) for arg in args[0]])
cwd = kwargs.get("cwd", os.getcwd())
text = f"Running command: `{cmd}` in directory: `{cwd}`"
if console:
console.print(f"[magenta]{text}[/]")
else:
print("#" * min(len(text), 200), file=sys.stderr)
print(text, file=sys.stderr)
print("#" * min(len(text), 200), file=sys.stderr)
time_start = time.time()
subprocess.check_call(*args, **kwargs)
time_end = time.time()
if console:
console.print(f"[green]After {text}[/]")
console.print(f"[green]Command finished in {time_end - time_start:.2f} seconds[/]")
else:
print("#" * min(len(text), 200), file=sys.stderr)
print(f"After {text}")
print(f"Command finished in {time_end - time_start:.2f} seconds", file=sys.stderr)
print("#" * min(len(text), 200), file=sys.stderr)


def read_airflow_version() -> str:
ast_obj = ast.parse((AIRFLOW_CORE_SOURCES_PATH / "airflow" / "__init__.py").read_text())
for node in ast_obj.body:
Expand Down
51 changes: 0 additions & 51 deletions scripts/ci/pre_commit/compile_lint_ui.py

This file was deleted.

61 changes: 61 additions & 0 deletions scripts/ci/pre_commit/ts_compile_lint_simple_auth_manager_ui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
# 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.
from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.resolve())) # make sure common_precommit_utils is imported
from common_precommit_utils import (
AIRFLOW_CORE_SOURCES_PATH,
AIRFLOW_ROOT_PATH,
run_command,
temporary_tsc_project,
)

if __name__ not in ("__main__", "__mp_main__"):
raise SystemExit(
"This file is intended to be executed as an executable program. You cannot use it as a module."
f"To run this script, run the ./{__file__} command"
)

if __name__ == "__main__":
original_files = sys.argv[1:]
print("Original files:", original_files)
dir = AIRFLOW_CORE_SOURCES_PATH / "airflow" / "api_fastapi" / "auth" / "managers" / "simple" / "ui"
relative_dir = Path(dir).relative_to(AIRFLOW_ROOT_PATH)
files = [
file[len(relative_dir.as_posix()) + 1 :]
for file in original_files
if Path(file).is_relative_to(relative_dir)
]
all_non_yaml_files = [file for file in files if not file.endswith(".yaml")]
print("All non-YAML files:", all_non_yaml_files)
all_ts_files = [file for file in files if file.endswith(".ts") or file.endswith(".tsx")]
print("All TypeScript files:", all_ts_files)

run_command(["pnpm", "config", "set", "store-dir", ".pnpm-store"], cwd=dir)
run_command(["pnpm", "install", "--frozen-lockfile", "--config.confirmModulesPurge=false"], cwd=dir)
if any("/openapi/" in file for file in original_files):
run_command(["pnpm", "codegen"], cwd=dir)
if all_non_yaml_files:
run_command(["pnpm", "prettier", "--write", *all_non_yaml_files], cwd=dir)
run_command(["pnpm", "eslint", "--fix", *all_non_yaml_files], cwd=dir)
if all_ts_files:
with temporary_tsc_project(dir / "tsconfig.app.json", all_ts_files) as tsc_project:
run_command(["pnpm", "tsc", "--p", tsc_project.name], cwd=dir)
Loading