Skip to content

Commit 5513306

Browse files
committed
CI: integrate alembic check
1 parent 278224f commit 5513306

File tree

4 files changed

+39
-0
lines changed

4 files changed

+39
-0
lines changed

.github/actions/migration_tests/action.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ runs:
8989
COMPOSE_PROJECT_NAME: "docker-compose"
9090
AIRFLOW__DATABASE__EXTERNAL_DB_MANAGERS: "airflow.providers.fab.auth_manager.models.db.FABDBManager"
9191
if: env.BACKEND != 'sqlite'
92+
- name: "Test model changes: ${{env.BACKEND}}"
93+
shell: bash
94+
run: >
95+
breeze shell "airflow db reset -y &&
96+
airflow db migrate --to-revision heads &&
97+
airflow db check-models"
98+
env:
99+
COMPOSE_PROJECT_NAME: "docker-compose"
100+
AIRFLOW__DATABASE__EXTERNAL_DB_MANAGERS: "airflow.providers.fab.auth_manager.models.db.FABDBManager"
92101
- name: "Bring any containers left down"
93102
shell: bash
94103
run: breeze down

airflow-core/src/airflow/cli/cli_config.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,13 @@ class GroupCommand(NamedTuple):
14061406
func=lazy_load_command("airflow.cli.commands.db_command.check"),
14071407
args=(ARG_VERBOSE, ARG_DB_RETRY, ARG_DB_RETRY_DELAY),
14081408
),
1409+
ActionCommand(
1410+
name="check-models",
1411+
help="Check if there are model changes without a corresponding migration",
1412+
description="Check if the current models require new migrations to be generated",
1413+
func=lazy_load_command("airflow.cli.commands.db_command.check_models"),
1414+
args=(ARG_VERBOSE,),
1415+
),
14091416
ActionCommand(
14101417
name="clean",
14111418
help="Purge old records in metastore tables",

airflow-core/src/airflow/cli/commands/db_command.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
from tempfile import NamedTemporaryFile
2525
from typing import TYPE_CHECKING
2626

27+
from alembic import command
2728
from packaging.version import InvalidVersion, parse as parse_version
2829
from tenacity import Retrying, stop_after_attempt, wait_fixed
2930

3031
from airflow import settings
3132
from airflow.exceptions import AirflowException
33+
from airflow.models import import_all_models
3234
from airflow.utils import cli as cli_utils, db
3335
from airflow.utils.db import _REVISION_HEADS_MAP
3436
from airflow.utils.db_cleanup import config_dict, drop_archived_tables, export_archived_records, run_cleanup
@@ -268,6 +270,21 @@ def _warn_remaining_retries(retrystate: RetryCallState):
268270
db.check()
269271

270272

273+
@cli_utils.action_cli(check_db=False)
274+
@providers_configuration_loaded
275+
def check_models(args):
276+
"""Check if there are model changes without a corresponding migration."""
277+
import_all_models()
278+
config = db._get_alembic_config()
279+
280+
try:
281+
command.check(config)
282+
print("Success: No model changes detected without migrations.")
283+
except Exception as e:
284+
print(f"Error: Model changes detected without migrations: {e}")
285+
raise SystemExit(1)
286+
287+
271288
# lazily imported by CLI parser for `help` command
272289
all_tables = sorted(config_dict)
273290

airflow-core/tests/unit/cli/commands/test_db_command.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ def test_cli_check_migrations(self, mock_wait_for_migrations):
5353

5454
mock_wait_for_migrations.assert_called_once_with(timeout=60)
5555

56+
@mock.patch("airflow.cli.commands.db_command.command.check")
57+
def test_cli_alembic_check(self, mock_check):
58+
db_command.alembic_check(self.parser.parse_args(["db", "check-models"]))
59+
60+
mock_check.assert_called_once_with(timeout=60)
61+
5662
@pytest.mark.parametrize(
5763
"args, called_with",
5864
[

0 commit comments

Comments
 (0)