This is an automated email from the ASF dual-hosted git repository.

Lee-W pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 54d9a8e5fb5 Standardize Alembic migration descriptions and add a style 
lint (#69537)
54d9a8e5fb5 is described below

commit 54d9a8e5fb5691215a381dbc665aba094d98e2ba
Author: PoAn Yang <[email protected]>
AuthorDate: Thu Jul 23 10:59:04 2026 +0900

    Standardize Alembic migration descriptions and add a style lint (#69537)
    
    Co-authored-by: Wei Lee <[email protected]>
    Signed-off-by: PoAn Yang <[email protected]>
---
 .pre-commit-config.yaml                            |  2 +-
 airflow-core/docs/migrations-ref.rst               | 34 +++++------
 ...03_2_7_0_add_include_deferred_column_to_pool.py |  2 +-
 .../0004_2_8_0_add_clear_number_to_dag_run.py      |  2 +-
 ...011_2_9_0_add_dataset_expression_in_dagmodel.py |  2 +-
 ...2_9_0_adding_adding_max_failure_runs_column_.py |  2 +-
 ...014_2_9_0_add_display_name_for_dag_and_task_.py |  2 +-
 .../0015_2_9_0_update_trigger_kwargs_type.py       |  2 +-
 .../0019_2_10_0_add_new_executor_field_to_db.py    |  2 +-
 ...2_10_0_added_dagpriorityparsingrequest_table.py |  2 +-
 .../0043_3_0_0_remove_scheduler_lock_column.py     |  2 +-
 .../versions/0047_3_0_0_add_dag_versioning.py      |  2 +-
 ...task_instance_trigger_timeout_to_utcdatetime.py |  2 +-
 ..._3_0_0_remove_pickled_data_from_dagrun_table.py |  2 +-
 ...3_0_0_add_new_task_instance_field_scheduled_.py |  2 +-
 .../0059_3_0_0_remove_external_trigger_field.py    |  2 +-
 ...4_3_1_0_add_last_parse_duration_to_dag_model.py |  2 +-
 ...3_2_0_replace_asset_trigger_table_with_asset.py |  2 +-
 ...0_3_2_0_add_timetable_type_to_dag_table_for_.py |  2 +-
 contributing-docs/14_metadata_database_updates.rst |  4 +-
 providers/.pre-commit-config.yaml                  |  8 +++
 scripts/ci/prek/check_migration_patterns.py        | 52 ++++++++++++++++-
 .../tests/ci/prek/test_check_migration_patterns.py | 67 +++++++++++++++++++++-
 23 files changed, 159 insertions(+), 42 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index adcc9c11c0f..0d31a6069fc 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1339,7 +1339,7 @@ repos:
         files: ^shared/.*|^scripts/ci/prek/check_shared_mypy_hooks\.py$
         require_serial: true
       - id: check-migration-patterns
-        name: Check migration files for anti-patterns (MIG001/MIG002/MIG003)
+        name: Check migration files for anti-patterns and style (MIG001-MIG004)
         entry: ./scripts/ci/prek/check_migration_patterns.py
         language: python
         pass_filenames: true
diff --git a/airflow-core/docs/migrations-ref.rst 
b/airflow-core/docs/migrations-ref.rst
index de64f8123f0..dfc96be7901 100644
--- a/airflow-core/docs/migrations-ref.rst
+++ b/airflow-core/docs/migrations-ref.rst
@@ -100,7 +100,7 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 | ``55297ae24532``        | ``e79fc784f145`` | ``3.2.0``         | Add 
required fields to enable UI integrations for the        |
 |                         |                  |                   | Deadline 
Alerts feature.                                     |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``e79fc784f145``        | ``0b112f49112d`` | ``3.2.0``         | add 
timetable_type to dag table for filtering.               |
+| ``e79fc784f145``        | ``0b112f49112d`` | ``3.2.0``         | Add 
timetable_type to dag table for filtering.               |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``0b112f49112d``        | ``c47f2e1ab9d4`` | ``3.2.0``         | Add exceeds 
max runs flag to dag model.                      |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -128,7 +128,7 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 | ``ab6dc0c82d0e``        | ``15d84ca19038`` | ``3.2.0``         | Change 
``serialized_dag`` data column to JSONB for           |
 |                         |                  |                   | PostgreSQL. 
                                                 |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``15d84ca19038``        | ``509b94a1042d`` | ``3.2.0``         | replace 
asset_trigger table with asset_watcher.              |
+| ``15d84ca19038``        | ``509b94a1042d`` | ``3.2.0``         | Replace 
asset_trigger table with asset_watcher.              |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``509b94a1042d``        | ``82dbd68e6171`` | ``3.1.8``         | Change 
``signed_url_template`` from VARCHAR(200) to TEXT.    |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -137,7 +137,7 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 | ``cc92b33c6709``        | ``eaf332f43c7c`` | ``3.1.0``         | Add 
backward compatibility for serialized DAG format v3 to   |
 |                         |                  |                   | v2.         
                                                 |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``eaf332f43c7c``        | ``a3c7f2b18d4e`` | ``3.1.0``         | add 
last_parse_duration to dag model.                        |
+| ``eaf332f43c7c``        | ``a3c7f2b18d4e`` | ``3.1.0``         | Add 
last_parse_duration to dag model.                        |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``a3c7f2b18d4e``        | ``7582ea3f3dd5`` | ``3.1.0``         | Add tables 
to store teams and associations with dag bundles. |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -193,15 +193,15 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``7645189f3479``        | ``e00344393f31`` | ``3.0.0``         | Add try_id 
to TI and TIH.                                    |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``e00344393f31``        | ``6a9e7a527a88`` | ``3.0.0``         | remove 
external_trigger field.                               |
+| ``e00344393f31``        | ``6a9e7a527a88`` | ``3.0.0``         | Remove 
external_trigger field.                               |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``6a9e7a527a88``        | ``33b04e4bfa19`` | ``3.0.0``         | Add DagRun 
run_after.                                        |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``33b04e4bfa19``        | ``8ea135928435`` | ``3.0.0``         | add new 
task_instance field scheduled_dttm.                  |
+| ``33b04e4bfa19``        | ``8ea135928435`` | ``3.0.0``         | Add new 
task_instance field scheduled_dttm.                  |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``8ea135928435``        | ``e39a26ac59f6`` | ``3.0.0``         | Add 
relative fileloc column.                                 |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``e39a26ac59f6``        | ``38770795785f`` | ``3.0.0``         | remove 
pickled data from dagrun table.                       |
+| ``e39a26ac59f6``        | ``38770795785f`` | ``3.0.0``         | Remove 
pickled data from dagrun table.                       |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``38770795785f``        | ``5c9c0231baa2`` | ``3.0.0``         | Add asset 
reference models.                                  |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -209,7 +209,7 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``237cef8dfea1``        | ``038dc8bc6284`` | ``3.0.0``         | Add 
deadline alerts table.                                   |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``038dc8bc6284``        | ``e229247a6cb1`` | ``3.0.0``         | update 
trigger_timeout column in task_instance table to UTC. |
+| ``038dc8bc6284``        | ``e229247a6cb1`` | ``3.0.0``         | Update 
trigger_timeout column in task_instance table to UTC. |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``e229247a6cb1``        | ``eed27faa34e3`` | ``3.0.0``         | Add 
DagBundleModel.                                          |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -217,7 +217,7 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``9fc3fc5de720``        | ``2b47dc6bc8df`` | ``3.0.0``         | Add 
references between assets and triggers.                  |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``2b47dc6bc8df``        | ``d03e4a635aa3`` | ``3.0.0``         | add dag 
versioning.                                          |
+| ``2b47dc6bc8df``        | ``d03e4a635aa3`` | ``3.0.0``         | Add dag 
versioning.                                          |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``d03e4a635aa3``        | ``d8cd3297971e`` | ``3.0.0``         | Drop DAG 
pickling.                                           |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -225,7 +225,7 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``5f57a45b8433``        | ``486ac7936b78`` | ``3.0.0``         | Drop 
task_fail table.                                        |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``486ac7936b78``        | ``d59cbbef95eb`` | ``3.0.0``         | remove 
scheduler_lock column.                                |
+| ``486ac7936b78``        | ``d59cbbef95eb`` | ``3.0.0``         | Remove 
scheduler_lock column.                                |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``d59cbbef95eb``        | ``05234396c6fc`` | ``3.0.0``         | Add UUID 
primary key to ``task_instance`` table.             |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -274,9 +274,9 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``d482b7261ff9``        | ``c4602ba06b4b`` | ``2.10.0``        | Add 
task_instance_history.                                   |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``c4602ba06b4b``        | ``677fdbb7fc54`` | ``2.10.0``        | Added 
DagPriorityParsingRequest table.                       |
+| ``c4602ba06b4b``        | ``677fdbb7fc54`` | ``2.10.0``        | Add 
DagPriorityParsingRequest table.                         |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``677fdbb7fc54``        | ``0fd0c178cbe8`` | ``2.10.0``        | add new 
executor field to db.                                |
+| ``677fdbb7fc54``        | ``0fd0c178cbe8`` | ``2.10.0``        | Add new 
executor field to db.                                |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``0fd0c178cbe8``        | ``686269002441`` | ``2.10.0``        | Add indexes 
on dag_id column in referencing tables.          |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
@@ -285,17 +285,17 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 | ``bff083ad727d``        | ``1949afb29106`` | ``2.9.2``         | Remove 
``idx_last_scheduling_decision`` index on             |
 |                         |                  |                   | 
last_scheduling_decision in dag_run table.                   |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``1949afb29106``        | ``ee1467d4aa35`` | ``2.9.0``         | update 
trigger kwargs type and encrypt.                      |
+| ``1949afb29106``        | ``ee1467d4aa35`` | ``2.9.0``         | Update 
trigger kwargs type and encrypt.                      |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``ee1467d4aa35``        | ``b4078ac230a1`` | ``2.9.0``         | add display 
name for dag and task instance.                  |
+| ``ee1467d4aa35``        | ``b4078ac230a1`` | ``2.9.0``         | Add display 
name for dag and task instance.                  |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``b4078ac230a1``        | ``8e1c784a4fc7`` | ``2.9.0``         | Change 
value column type to longblob in xcom table for       |
 |                         |                  |                   | mysql.      
                                                 |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``8e1c784a4fc7``        | ``ab34f260b71c`` | ``2.9.0``         | Adding 
max_consecutive_failed_dag_runs column to dag_model   |
+| ``8e1c784a4fc7``        | ``ab34f260b71c`` | ``2.9.0``         | Add 
max_consecutive_failed_dag_runs column to dag_model      |
 |                         |                  |                   | table.      
                                                 |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``ab34f260b71c``        | ``d75389605139`` | ``2.9.0``         | add 
dataset_expression in DagModel.                          |
+| ``ab34f260b71c``        | ``d75389605139`` | ``2.9.0``         | Add 
dataset_expression in DagModel.                          |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``d75389605139``        | ``1fd565369930`` | ``2.9.0``         | Add run_id 
to (Audit) log table and increase event name      |
 |                         |                  |                   | length.     
                                                 |
@@ -310,9 +310,9 @@ Here's the list of all the Database Migrations that are 
executed via when you ru
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``f7bf2a57d0a6``        | ``375a816bbbf4`` | ``2.8.0``         | Add 
owner_display_name to (Audit) Log table.                 |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``375a816bbbf4``        | ``405de8318b3a`` | ``2.8.0``         | add new 
field 'clear_number' to dagrun.                      |
+| ``375a816bbbf4``        | ``405de8318b3a`` | ``2.8.0``         | Add new 
field 'clear_number' to dagrun.                      |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
-| ``405de8318b3a``        | ``788397e78828`` | ``2.7.0``         | add 
include_deferred column to pool.                         |
+| ``405de8318b3a``        | ``788397e78828`` | ``2.7.0``         | Add 
include_deferred column to pool.                         |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
 | ``788397e78828``        | ``937cbd173ca1`` | ``2.7.0``         | Add 
custom_operator_name column.                             |
 
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
diff --git 
a/airflow-core/src/airflow/migrations/versions/0003_2_7_0_add_include_deferred_column_to_pool.py
 
b/airflow-core/src/airflow/migrations/versions/0003_2_7_0_add_include_deferred_column_to_pool.py
index 6cfae9ce36b..e0a3038114b 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0003_2_7_0_add_include_deferred_column_to_pool.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0003_2_7_0_add_include_deferred_column_to_pool.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add include_deferred column to pool.
+Add include_deferred column to pool.
 
 Revision ID: 405de8318b3a
 Revises: 788397e78828
diff --git 
a/airflow-core/src/airflow/migrations/versions/0004_2_8_0_add_clear_number_to_dag_run.py
 
b/airflow-core/src/airflow/migrations/versions/0004_2_8_0_add_clear_number_to_dag_run.py
index 94f2a14874a..6444ee381fa 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0004_2_8_0_add_clear_number_to_dag_run.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0004_2_8_0_add_clear_number_to_dag_run.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add new field 'clear_number' to dagrun.
+Add new field 'clear_number' to dagrun.
 
 Revision ID: 375a816bbbf4
 Revises: 405de8318b3a
diff --git 
a/airflow-core/src/airflow/migrations/versions/0011_2_9_0_add_dataset_expression_in_dagmodel.py
 
b/airflow-core/src/airflow/migrations/versions/0011_2_9_0_add_dataset_expression_in_dagmodel.py
index e667a1e04aa..2a55e67f899 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0011_2_9_0_add_dataset_expression_in_dagmodel.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0011_2_9_0_add_dataset_expression_in_dagmodel.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add dataset_expression in DagModel.
+Add dataset_expression in DagModel.
 
 Revision ID: ab34f260b71c
 Revises: d75389605139
diff --git 
a/airflow-core/src/airflow/migrations/versions/0012_2_9_0_adding_adding_max_failure_runs_column_.py
 
b/airflow-core/src/airflow/migrations/versions/0012_2_9_0_adding_adding_max_failure_runs_column_.py
index 1aff04a7cbe..2683110738e 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0012_2_9_0_adding_adding_max_failure_runs_column_.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0012_2_9_0_adding_adding_max_failure_runs_column_.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-Adding max_consecutive_failed_dag_runs column to dag_model table.
+Add max_consecutive_failed_dag_runs column to dag_model table.
 
 Revision ID: 8e1c784a4fc7
 Revises: ab34f260b71c
diff --git 
a/airflow-core/src/airflow/migrations/versions/0014_2_9_0_add_display_name_for_dag_and_task_.py
 
b/airflow-core/src/airflow/migrations/versions/0014_2_9_0_add_display_name_for_dag_and_task_.py
index 80ad5822ce4..43ec8985985 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0014_2_9_0_add_display_name_for_dag_and_task_.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0014_2_9_0_add_display_name_for_dag_and_task_.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add display name for dag and task instance.
+Add display name for dag and task instance.
 
 Revision ID: ee1467d4aa35
 Revises: b4078ac230a1
diff --git 
a/airflow-core/src/airflow/migrations/versions/0015_2_9_0_update_trigger_kwargs_type.py
 
b/airflow-core/src/airflow/migrations/versions/0015_2_9_0_update_trigger_kwargs_type.py
index d90cd60c79b..5e3715137ca 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0015_2_9_0_update_trigger_kwargs_type.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0015_2_9_0_update_trigger_kwargs_type.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-update trigger kwargs type and encrypt.
+Update trigger kwargs type and encrypt.
 
 Revision ID: 1949afb29106
 Revises: ee1467d4aa35
diff --git 
a/airflow-core/src/airflow/migrations/versions/0019_2_10_0_add_new_executor_field_to_db.py
 
b/airflow-core/src/airflow/migrations/versions/0019_2_10_0_add_new_executor_field_to_db.py
index 694f0f84f8f..bfbd1ab6506 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0019_2_10_0_add_new_executor_field_to_db.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0019_2_10_0_add_new_executor_field_to_db.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add new executor field to db.
+Add new executor field to db.
 
 Revision ID: 677fdbb7fc54
 Revises: 0fd0c178cbe8
diff --git 
a/airflow-core/src/airflow/migrations/versions/0020_2_10_0_added_dagpriorityparsingrequest_table.py
 
b/airflow-core/src/airflow/migrations/versions/0020_2_10_0_added_dagpriorityparsingrequest_table.py
index 6580c80973b..1be89322635 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0020_2_10_0_added_dagpriorityparsingrequest_table.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0020_2_10_0_added_dagpriorityparsingrequest_table.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-Added DagPriorityParsingRequest table.
+Add DagPriorityParsingRequest table.
 
 Revision ID: c4602ba06b4b
 Revises: 677fdbb7fc54
diff --git 
a/airflow-core/src/airflow/migrations/versions/0043_3_0_0_remove_scheduler_lock_column.py
 
b/airflow-core/src/airflow/migrations/versions/0043_3_0_0_remove_scheduler_lock_column.py
index 12d1b16d972..9dcd8ce049c 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0043_3_0_0_remove_scheduler_lock_column.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0043_3_0_0_remove_scheduler_lock_column.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-remove scheduler_lock column.
+Remove scheduler_lock column.
 
 Revision ID: 486ac7936b78
 Revises: d59cbbef95eb
diff --git 
a/airflow-core/src/airflow/migrations/versions/0047_3_0_0_add_dag_versioning.py 
b/airflow-core/src/airflow/migrations/versions/0047_3_0_0_add_dag_versioning.py
index c666a260fa7..4deedb925ce 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0047_3_0_0_add_dag_versioning.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0047_3_0_0_add_dag_versioning.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add dag versioning.
+Add dag versioning.
 
 Revision ID: 2b47dc6bc8df
 Revises: d03e4a635aa3
diff --git 
a/airflow-core/src/airflow/migrations/versions/0051_3_0_0_update_task_instance_trigger_timeout_to_utcdatetime.py
 
b/airflow-core/src/airflow/migrations/versions/0051_3_0_0_update_task_instance_trigger_timeout_to_utcdatetime.py
index 5a381577366..05872c4e259 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0051_3_0_0_update_task_instance_trigger_timeout_to_utcdatetime.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0051_3_0_0_update_task_instance_trigger_timeout_to_utcdatetime.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-update trigger_timeout column in task_instance table to UTC.
+Update trigger_timeout column in task_instance table to UTC.
 
 Revision ID: 038dc8bc6284
 Revises: e229247a6cb1
diff --git 
a/airflow-core/src/airflow/migrations/versions/0055_3_0_0_remove_pickled_data_from_dagrun_table.py
 
b/airflow-core/src/airflow/migrations/versions/0055_3_0_0_remove_pickled_data_from_dagrun_table.py
index f527dab936e..b662290ef50 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0055_3_0_0_remove_pickled_data_from_dagrun_table.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0055_3_0_0_remove_pickled_data_from_dagrun_table.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-remove pickled data from dagrun table.
+Remove pickled data from dagrun table.
 
 Revision ID: e39a26ac59f6
 Revises: 38770795785f
diff --git 
a/airflow-core/src/airflow/migrations/versions/0057_3_0_0_add_new_task_instance_field_scheduled_.py
 
b/airflow-core/src/airflow/migrations/versions/0057_3_0_0_add_new_task_instance_field_scheduled_.py
index ca071a18d0d..d3ea57cd8df 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0057_3_0_0_add_new_task_instance_field_scheduled_.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0057_3_0_0_add_new_task_instance_field_scheduled_.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add new task_instance field scheduled_dttm.
+Add new task_instance field scheduled_dttm.
 
 Revision ID: 33b04e4bfa19
 Revises: 8ea135928435
diff --git 
a/airflow-core/src/airflow/migrations/versions/0059_3_0_0_remove_external_trigger_field.py
 
b/airflow-core/src/airflow/migrations/versions/0059_3_0_0_remove_external_trigger_field.py
index 46d3cd9ca57..7ca343a2b78 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0059_3_0_0_remove_external_trigger_field.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0059_3_0_0_remove_external_trigger_field.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-remove external_trigger field.
+Remove external_trigger field.
 
 Revision ID: e00344393f31
 Revises: 6a9e7a527a88
diff --git 
a/airflow-core/src/airflow/migrations/versions/0084_3_1_0_add_last_parse_duration_to_dag_model.py
 
b/airflow-core/src/airflow/migrations/versions/0084_3_1_0_add_last_parse_duration_to_dag_model.py
index 1a922d97dee..f2ca97e42cc 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0084_3_1_0_add_last_parse_duration_to_dag_model.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0084_3_1_0_add_last_parse_duration_to_dag_model.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add last_parse_duration to dag model.
+Add last_parse_duration to dag model.
 
 Revision ID: eaf332f43c7c
 Revises: a3c7f2b18d4e
diff --git 
a/airflow-core/src/airflow/migrations/versions/0088_3_2_0_replace_asset_trigger_table_with_asset.py
 
b/airflow-core/src/airflow/migrations/versions/0088_3_2_0_replace_asset_trigger_table_with_asset.py
index e4478f58da4..81c134741f4 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0088_3_2_0_replace_asset_trigger_table_with_asset.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0088_3_2_0_replace_asset_trigger_table_with_asset.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-replace asset_trigger table with asset_watcher.
+Replace asset_trigger table with asset_watcher.
 
 Revision ID: 15d84ca19038
 Revises: 509b94a1042d
diff --git 
a/airflow-core/src/airflow/migrations/versions/0100_3_2_0_add_timetable_type_to_dag_table_for_.py
 
b/airflow-core/src/airflow/migrations/versions/0100_3_2_0_add_timetable_type_to_dag_table_for_.py
index 390b9d55bfd..6f6817a05f8 100644
--- 
a/airflow-core/src/airflow/migrations/versions/0100_3_2_0_add_timetable_type_to_dag_table_for_.py
+++ 
b/airflow-core/src/airflow/migrations/versions/0100_3_2_0_add_timetable_type_to_dag_table_for_.py
@@ -17,7 +17,7 @@
 # under the License.
 
 """
-add timetable_type to dag table for filtering.
+Add timetable_type to dag table for filtering.
 
 Revision ID: e79fc784f145
 Revises: 0b112f49112d
diff --git a/contributing-docs/14_metadata_database_updates.rst 
b/contributing-docs/14_metadata_database_updates.rst
index 2bfefa89eaa..b235f93ca5e 100644
--- a/contributing-docs/14_metadata_database_updates.rst
+++ b/contributing-docs/14_metadata_database_updates.rst
@@ -30,11 +30,11 @@ database schema that you have made. To generate a new 
migration file, run the fo
 
     # starting at the root of the project
     # Use breeze:
-    $ breeze generate-migration-file -m "add new field to db"
+    $ breeze generate-migration-file -m "Add new field to db."
     # Or, go to the airflow directory and use alembic directly:
     $ breeze --backend postgres
     $ cd airflow-core/src/airflow
-    $ alembic revision -m "add new field to db" --autogenerate
+    $ alembic revision -m "Add new field to db." --autogenerate
 
        Generating
     
~/airflow-core/src/airflow/migrations/versions/a1e23c41f123_add_new_field_to_db.py
diff --git a/providers/.pre-commit-config.yaml 
b/providers/.pre-commit-config.yaml
index 1c721ed3c4a..ab6fef5a7f0 100644
--- a/providers/.pre-commit-config.yaml
+++ b/providers/.pre-commit-config.yaml
@@ -37,6 +37,14 @@ repos:
         entry: ../scripts/ci/prek/check_trigger_serialize_init.py
         pass_filenames: true
         files: ^.*/src/airflow/providers/.*/triggers/[^/]+\.py$
+      - id: check-migration-patterns
+        name: Check migration files for anti-patterns and style (MIG001-MIG004)
+        entry: ../scripts/ci/prek/check_migration_patterns.py
+        language: python
+        pass_filenames: true
+        files: ^.*/src/airflow/providers/.*/migrations/versions/.*\.py$
+        additional_dependencies: [rich>=13.6.0]
+        require_serial: true
       - id: update-providers-dependencies
         name: Update dependencies for providers
         entry: ../scripts/ci/prek/update_providers_dependencies.py
diff --git a/scripts/ci/prek/check_migration_patterns.py 
b/scripts/ci/prek/check_migration_patterns.py
old mode 100644
new mode 100755
index 871825d2a87..7f8877efb22
--- a/scripts/ci/prek/check_migration_patterns.py
+++ b/scripts/ci/prek/check_migration_patterns.py
@@ -148,14 +148,36 @@ a NOT NULL constraint, deleting rows before dropping a 
table, etc.  The DML is
 considered a safe prerequisite for the DDL.
 
 
-Known Limitation -- Future MIG004 Candidate
+MIG004 -- Migration description style
+--------------------------------------
+
+**What it does:**
+Checks the first paragraph of the migration module docstring -- the description
+Alembic exposes as ``Script.doc``. It must start with a capital letter, use the
+imperative mood ("Add", not "Added"/"Adding"), and end with a period.
+
+**Why is this bad:**
+The description is user-facing: it is rendered into the ``migrations-ref.rst``
+documentation table (by the ``update-migration-references`` hook) and printed 
by
+``alembic history``.  Inconsistent capitalization and verb tense make those
+listings needlessly messy.
+
+**Example (bad):** a migration docstring starting with
+``Added DagPriorityParsingRequest table.`` or
+``add timetable_type to dag table for filtering.``
+
+**Use instead:** ``Add DagPriorityParsingRequest table.`` and
+``Add timetable_type to dag table for filtering.``
+
+
+Known Limitation -- Future MIG005 Candidate
 ---------------------------------------------
 
 Migrations that perform DML and use ``batch_alter_table`` but never call
 ``disable_sqlite_fkeys`` at all are NOT detected by MIG001/MIG002.  These 
migrations
 may silently break SQLite foreign key handling.  Detecting this pattern 
requires
 understanding whether foreign key relationships exist on the affected tables, 
which
-is beyond AST-level analysis.  This is tracked as a future MIG004 candidate.
+is beyond AST-level analysis.  This is tracked as a future MIG005 candidate.
 
 
 Suppression
@@ -484,6 +506,30 @@ def check_mig003(mf: MigrationFile) -> list[str]:
     return errors
 
 
+def check_mig004(mf: MigrationFile) -> list[str]:
+    """MIG004: description must be capitalized, imperative, and end with a 
period."""
+    if mf.path.name == "__init__.py":
+        return []
+    doc = ast.get_docstring(mf.tree)
+    # Same extraction as alembic's Script.doc.
+    description = re.split(r"\n\n", doc.strip())[0].strip() if doc else ""
+    if not description:
+        return ["MIG004 module docstring must start with a migration 
description"]
+
+    errors: list[str] = []
+    if not description[0].isupper():
+        errors.append(f"MIG004 description {description!r} must start with a 
capital letter")
+    first_word = re.match(r"[A-Za-z]+", description)
+    if first_word and first_word.group().lower().endswith(("ed", "ing")):
+        errors.append(
+            f"MIG004 description {description!r} must use the imperative mood "
+            f"('Add ...', not 'Added ...' or 'Adding ...')"
+        )
+    if not description.endswith("."):
+        errors.append(f"MIG004 description {description!r} must end with a 
period")
+    return errors
+
+
 # ---------------------------------------------------------------------------
 # CLI entry point
 # ---------------------------------------------------------------------------
@@ -491,7 +537,7 @@ def check_mig003(mf: MigrationFile) -> list[str]:
 
 def main() -> int:
     """Check migration files for anti-patterns. Exit 0 if clean, 1 if 
violations found."""
-    check_fns = [check_mig001, check_mig002, check_mig003]
+    check_fns = [check_mig001, check_mig002, check_mig003, check_mig004]
     has_errors = False
 
     for filepath_str in sys.argv[1:]:
diff --git a/scripts/tests/ci/prek/test_check_migration_patterns.py 
b/scripts/tests/ci/prek/test_check_migration_patterns.py
index a83bc9b751f..34868060bbc 100644
--- a/scripts/tests/ci/prek/test_check_migration_patterns.py
+++ b/scripts/tests/ci/prek/test_check_migration_patterns.py
@@ -33,6 +33,7 @@ from ci.prek.check_migration_patterns import (
     check_mig001,
     check_mig002,
     check_mig003,
+    check_mig004,
     main,
 )
 
@@ -515,13 +516,75 @@ def upgrade():
         assert any("MIG003" in e for e in errors)
 
 
+class TestCheckMig004:
+    @pytest.mark.parametrize(
+        "src",
+        [
+            pytest.param(
+                '"""\nAdd foo table.\n\nRevision ID: abc123\n"""\n\ndef 
upgrade(): pass\n',
+                id="imperative-capitalized",
+            ),
+            pytest.param(
+                '"""\nAdd foo table\nwith extra columns.\n\nRevision ID: 
abc123\n"""\n',
+                id="multi-line-description",
+            ),
+        ],
+    )
+    def test_no_violation(self, tmp_path, src):
+        assert check_mig004(parse_migration(tmp_path, src)) == []
+
+    def test_init_py_is_skipped(self, tmp_path):
+        p = tmp_path / "__init__.py"
+        p.write_text('"""not a description"""\n')
+        assert check_mig004(MigrationFile.from_path(p)) == []
+
+    @pytest.mark.parametrize(
+        ("src", "expected"),
+        [
+            pytest.param(
+                '"""\nadd foo table.\n\nRevision ID: abc123\n"""\n',
+                "capital letter",
+                id="lowercase-start",
+            ),
+            pytest.param(
+                '"""\n``foo`` cleanup.\n\nRevision ID: abc123\n"""\n',
+                "capital letter",
+                id="non-letter-start",
+            ),
+            pytest.param(
+                '"""\nAdded foo table.\n\nRevision ID: abc123\n"""\n',
+                "imperative mood",
+                id="past-tense",
+            ),
+            pytest.param(
+                '"""\nAdding foo table.\n\nRevision ID: abc123\n"""\n',
+                "imperative mood",
+                id="gerund",
+            ),
+            pytest.param(
+                '"""\nAdd foo table\n\nRevision ID: abc123\n"""\n',
+                "end with a period",
+                id="missing-period",
+            ),
+            pytest.param(
+                "def upgrade(): pass\n",
+                "migration description",
+                id="missing-docstring",
+            ),
+        ],
+    )
+    def test_violation(self, tmp_path, src, expected):
+        errors = check_mig004(parse_migration(tmp_path, src))
+        assert any("MIG004" in e and expected in e for e in errors)
+
+
 class TestMain:
     def test_no_args_exits_zero(self, monkeypatch):
         monkeypatch.setattr(sys, "argv", ["check_migration_patterns.py"])
         assert main() == 0
 
     def test_clean_file_exits_zero(self, tmp_path, monkeypatch):
-        p = write_migration(tmp_path, "def upgrade(): pass\n")
+        p = write_migration(tmp_path, '"""Add foo table."""\n\ndef upgrade(): 
pass\n')
         monkeypatch.setattr(sys, "argv", ["check_migration_patterns.py", 
str(p)])
         assert main() == 0
 
@@ -548,7 +611,7 @@ def upgrade():
 
     def test_any_violation_in_batch_exits_one(self, tmp_path, monkeypatch):
         clean = tmp_path / "0001_clean.py"
-        clean.write_text("def upgrade(): pass\n")
+        clean.write_text('"""Add foo table."""\n\ndef upgrade(): pass\n')
         violation = tmp_path / "0002_bad.py"
         violation.write_text(
             "def upgrade():\n    op.execute('UPDATE dag SET x=1')\n    with 
disable_sqlite_fkeys(op): pass\n"


Reply via email to