This is an automated email from the ASF dual-hosted git repository.
vincbeck 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 fa00af4d044 Update multi-team docs to match the teams CLI and name
rules (#72045)
fa00af4d044 is described below
commit fa00af4d0444315c6b4cc925191b0db90841e1b1
Author: PoAn Yang <[email protected]>
AuthorDate: Tue Aug 25 21:54:29 2026 +0900
Update multi-team docs to match the teams CLI and name rules (#72045)
---
airflow-core/docs/core-concepts/multi-team.rst | 50 +++++++++++++++++++---
airflow-core/src/airflow/cli/cli_config.py | 3 +-
.../always/test_secrets_environment_variables.py | 4 +-
3 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/airflow-core/docs/core-concepts/multi-team.rst
b/airflow-core/docs/core-concepts/multi-team.rst
index 6d6c8493e73..da1ca415a0e 100644
--- a/airflow-core/docs/core-concepts/multi-team.rst
+++ b/airflow-core/docs/core-concepts/multi-team.rst
@@ -54,7 +54,8 @@ A **Team** is a logical grouping that represents a group of
users within your or
Teams within the Airflow database have a very simple structure, only
containing one field:
-- **name**: A unique identifier for the team (3-50 characters, alphanumeric
with hyphens and underscores)
+- **name**: A unique identifier for the team (3-50 characters, lower case
letters, digits, hyphens and
+ underscores, with no two consecutive underscores)
Teams are associated with Dag bundles through a separate association table,
which links team names to Dag bundle names.
@@ -118,8 +119,10 @@ implement two methods:
used primarily to check whether a user belongs to a team.
- ``_get_teams``: Returns the set of teams defined in the auth manager.
-During initialization, Airflow validates that all teams defined in the auth
manager are also present in the
-Airflow metadata database. If any team is missing, Airflow will raise an error.
+During initialization, Airflow compares the teams defined in the auth manager
with the teams in the Airflow
+metadata database. A mismatch in either direction -- a team the auth manager
defines that the database does
+not have, or a team the database has that the auth manager does not define --
emits a ``UserWarning``.
+Startup is not blocked, so watch the startup log for these warnings.
If the auth manager you are using does not implement these methods, Airflow
will raise a
``NotImplementedError`` at runtime.
@@ -161,7 +164,8 @@ Creating a Team
airflow teams create <team_name>
-Team names must be 3-50 characters long and contain only alphanumeric
characters, hyphens, and underscores.
+Team names must be 3-50 characters long and contain only lower case letters,
digits, hyphens and underscores.
+Two consecutive underscores are not allowed.
Listing Teams
^^^^^^^^^^^^^
@@ -189,6 +193,38 @@ Or to skip the confirmation prompt:
A team cannot be deleted if it has associated resources (Dag bundles,
Variables, Connections, or Pools). You must remove these associations first.
+.. _multi-team-teams-sync:
+
+Syncing Teams from the Dag Bundle Config
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.3.0
+
+.. code-block:: bash
+
+ airflow teams sync
+
+Creates a team for every ``team_name`` in the :ref:`Dag bundle config
<multi-team-dag-bundles>` that the
+database does not have yet, so the bundle config can be the one place teams
are declared instead of running
+``airflow teams create`` once per team. It also creates the default pool of
any configured team that is
+missing one, including teams that already existed.
+
+.. _multi-team-teams-verify:
+
+Verifying the Configuration
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.4.0
+
+.. code-block:: bash
+
+ airflow teams verify
+
+Checks the multi-team configuration against the database and reports any of
these problems:
+
+- a team that has no default pool
+- a team referenced by a Dag bundle but missing from the database
+
Configuring Team Resources
--------------------------
@@ -516,6 +552,8 @@ name followed by an equals sign:
broker_url = redis://team-b-redis:6379/0
result_backend = db+postgresql+psycopg://team-b-db/celery_results
+.. _multi-team-dag-bundles:
+
Dag Bundle to Team Association
------------------------------
@@ -552,7 +590,9 @@ In this example:
.. note::
- The team specified in ``team_name`` must exist in the database before
syncing the Dag bundles. Create teams first using ``airflow teams create``.
+ The team specified in ``team_name`` must exist in the database before
syncing the Dag bundles. Create the
+ teams first with ``airflow teams create``, or let ``airflow teams sync``
create them from this config
+ (see :ref:`multi-team-teams-sync`).
How Scheduling Works
--------------------
diff --git a/airflow-core/src/airflow/cli/cli_config.py
b/airflow-core/src/airflow/cli/cli_config.py
index 1a83af7a272..06c8819136b 100644
--- a/airflow-core/src/airflow/cli/cli_config.py
+++ b/airflow-core/src/airflow/cli/cli_config.py
@@ -1657,7 +1657,8 @@ TEAMS_COMMANDS = (
name="create",
help="Create a team",
description=(
- "Create a team. Team names must be 3-50 characters long and
contain only alphanumeric characters, hyphens, and underscores.\n"
+ "Create a team. Team names must be 3-50 characters long and
contain only lower case letters, "
+ "digits, hyphens and underscores, with no two consecutive
underscores.\n"
),
func=lazy_load_command("airflow.cli.commands.team_command.team_create"),
args=(ARG_TEAM_NAME, ARG_VERBOSE),
diff --git
a/airflow-core/tests/unit/always/test_secrets_environment_variables.py
b/airflow-core/tests/unit/always/test_secrets_environment_variables.py
index 200b545bf03..692827a3ab9 100644
--- a/airflow-core/tests/unit/always/test_secrets_environment_variables.py
+++ b/airflow-core/tests/unit/always/test_secrets_environment_variables.py
@@ -28,8 +28,8 @@ from airflow.secrets.environment_variables import (
from tests_common.test_utils.config import conf_vars
-# A team specific secret is stored as ``<PREFIX>_<TEAM_NAME>___<SECRET_ID>``.
Team names may contain
-# underscores (they are validated against ``^[a-zA-Z0-9_-]{3,50}$``), so both
shapes are exercised.
+# A team specific secret is stored as ``<PREFIX>_<TEAM_NAME>___<SECRET_ID>``.
Team names may contain a
+# single underscore (they are validated against ``TEAM_NAME_PATTERN``), so
both shapes are exercised.
TEAM_NAMES = ["team_a", "teama"]
OTHER_TEAM_NAME = "team_b"
SECRET_ID = "dbconn"