Skip to content

Fix flaky test caused by detector name collision in parallel CI jobs#417

Merged
timmarkhuff merged 11 commits intomainfrom
tim/fix-flaky-detector-name-collision
Mar 18, 2026
Merged

Fix flaky test caused by detector name collision in parallel CI jobs#417
timmarkhuff merged 11 commits intomainfrom
tim/fix-flaky-detector-name-collision

Conversation

@timmarkhuff
Copy link
Contributor

@timmarkhuff timmarkhuff commented Mar 18, 2026

Problem

Test detector names were generated with f"Test {datetime.utcnow()}", which has second-level precision and is evaluated at module import time. When parallel CI matrix jobs imported the same module within the same second, they produced identical detector names. This caused get_or_create_detector calls to fail with a unique_undeleted_name_per_set constraint violation. Additionally, we have a lot of duplicated code for creating detector names, which could benefit from centralization.

Fix

Added a detector_name pytest fixture in conftest.py that returns a callable which appends a random UUID suffix to the timestamp, guaranteeing uniqueness across parallel runs. Replaced all inline detector name formatting across the test suite with calls to this fixture.

return gl


@pytest.fixture(name="retry_detector_name")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I renamed this local fixture to avoid collision with the detector_name fixture I created in conftest.py.

)
assert completed_process.returncode == 0
det_id_on_create = re.search("id='([^']+)'", completed_process.stdout).group(1)
match = re.search("id='([^']+)'", completed_process.stdout)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Callable type annotation we added to this function promoted it from "untyped" to "typed" in mypy's eyes. Since check_untyped_defs is not enabled in our mypy config, mypy was previously skipping this function body entirely. The re.search().group() pattern was always unsafe, just invisible to the linter. Extracting the match and asserting it's not None satisfies mypy and also gives a clearer test failure message if the regex ever doesn't match.

)
assert completed_process.returncode == 0
det_id_on_get = re.search("id='([^']+)'", completed_process.stdout).group(1)
match = re.search("id='([^']+)'", completed_process.stdout)
Copy link
Contributor Author

@timmarkhuff timmarkhuff Mar 18, 2026

Choose a reason for hiding this comment

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

Copy link
Collaborator

@brandon-wada brandon-wada left a comment

Choose a reason for hiding this comment

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

LGTM

@timmarkhuff timmarkhuff merged commit bc7d739 into main Mar 18, 2026
8 checks passed
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.

2 participants