Skip to content

Fix test fixture cleanup for bundles and teams#68376

Open
anshuman0123 wants to merge 2 commits into
apache:mainfrom
anshuman0123:main
Open

Fix test fixture cleanup for bundles and teams#68376
anshuman0123 wants to merge 2 commits into
apache:mainfrom
anshuman0123:main

Conversation

@anshuman0123

Copy link
Copy Markdown

Summary

  • Track DAG bundle rows created by the dag_maker test fixture and remove them during fixture cleanup.
  • Add teardown for the testing_dag_bundle fixture when it creates the shared testing bundle row.
  • Add teardown for the testing_team fixture when it creates the shared testing team row.

Details

dag_maker.cleanup() already removes DAG-related rows such as DagModel, DagRun, TaskInstance, DagVersion, XCom, TaskMap, and AssetEvent, but it did not remove DagBundleModel rows that dag_maker created. This could leave bundle rows behind and force later tests to defensively call clear_db_dag_bundles().

This change records bundle names created by dag_maker and deletes those bundles after DAG model/version cleanup, preserving FK-safe cleanup order. It also converts testing_dag_bundle and testing_team into fixtures with teardown paths so rows created for a test do not leak into later tests.

Testing

  • python -m py_compile devel-common\src\tests_common\pytest_plugin.py
  • git diff --check

Targeted pytest was not run locally because uv and pytest are not installed in this environment.

Fixes: #68374

@boring-cyborg

boring-cyborg Bot commented Jun 11, 2026

Copy link
Copy Markdown

Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contributors' Guide
Here are some useful points:

  • Pay attention to the quality of your code (ruff, mypy and type annotations). Our prek-hooks will help you with that.
  • In case of a new feature add useful documentation (in docstrings or in docs/ directory). Adding a new operator? Check this short guide Consider adding an example Dag that shows how users should use it.
  • Consider using Breeze environment for testing locally, it's a heavy docker but it ships with a working Airflow and a lot of integrations.
  • Be patient and persistent. It might take some time to get a review or get the final approval from Committers.
  • Please follow ASF Code of Conduct for all communication including (but not limited to) comments on Pull Requests, Mailing list and Slack.
  • Be sure to read the Airflow Coding style.
  • Always keep your Pull Requests rebased, otherwise your build might fail due to changes not related to your commits.
    Apache Airflow is a community-driven project and together we are making it better 🚀.
    In case of doubts contact the developers at:
    Mailing List: dev@airflow.apache.org
    Slack: https://s.apache.org/airflow-slack

The _fetch_remote_logging_conn function in the supervisor was caching
None results when a connection lookup failed. In the two-token
execution model, an initial lookup with a restricted token might fail,
and caching this None result prevented subsequent lookups with an
execution token from succeeding.

This change ensures that only successful connection lookups are cached,
allowing for retries when a better token becomes available.

Fixes: apache#68366
@@ -1181,10 +1181,10 @@ def _fetch_remote_logging_conn(conn_id: str, client: Client) -> Connection | Non
from airflow.sdk.definitions.connection import Connection

@anishgirianish anishgirianish Jun 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think changes to this file is not related to the issue attached to this pr. And I think changes to this file can be dropped

@anishgirianish

anishgirianish commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Thank you so much for the PR. I think the changes to supervisor.py can be dropped, seems unrelated to the issue tagged in the description. And also, I think this is initial part(fix) of the issue, I would suggest updating the description to be related to tagged issue.

@ferruzzi ferruzzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was fast, thanks! We definitely need to get it manually tested and I left some comments to look at.

delete(DagBundleModel).where(DagBundleModel.name.in_(bundle_names))
)
self.session.commit()
self.created_bundle_names.difference_update(bundle_names)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to above, you can likely drop this. We should be deleting all bundle_names, right? The SQL above is batch-deleting ll of them, then here you remove all of them from the set. MAYBE if you wanted to do this then validate that it is now an empty set, that could be a reason for it, but as of now it's just emptying the set before teardown.

with attempt:
dag_ids = list(self.dagbag.dag_ids)
if not dag_ids:
bundle_names = set(self.created_bundle_names)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to not use self.created_bundle_names directly? I think in this case it is overly defensive; I don't see where anything is modifying the set once it reaches this point.

Comment on lines +2961 to +2964
finally:
if created:
with create_session() as session:
session.execute(delete(DagBundleModel).where(DagBundleModel.name == "testing"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure this is one of the "quick fixes" I tried before creating this issue and this will blow up. We'll see when the CI finishes. I didn't dive too deep into it once I saw it wasn't working, but I suspect that this fails because (some of??) the DagModels in tests are being created after this fixture fires and those aren't being cleaned, which causes an F-Key Reference error.

If the CI is failing, I'd suggest you start there. If the CI passes then I'm mistaken and you can resolve this with my apologies.

Comment on lines +2989 to 2992
if created:
session.rollback()
session.execute(delete(Team).where(Team.name == "testing"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SQL is one of my weak points, but this smells funny. Rolling back before deleting feels wrong here? 100% willing to be wrong here and learn something from you if this is an area you are comfortable with.

If I understand this right, we're creating the Team and yielding it, then after the test finishes with it we're rolling it back, then deleting it? I'm guessing the rollback is in case the test modified it during the yield? Which maybe makes sense, but if we're deleting it anyway, does it matter if we roll it back first? If the session is in a good/unmodified state then the rollback is unnecessary. If the session is in a bad/modified state, then the test has already failed and we should nuke it anyway, no?

Again, this is a blind spot for me, I cold absolutely be missing something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Tech Debt] Unit Test Isolation: Clean up Bundle and Team unit tests

3 participants