From 31e886e64199a57990736ed4b98d8ff71cffc06f Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Thu, 30 Apr 2026 15:34:03 -0400 Subject: [PATCH 01/12] Skip unpinned deps for non integrations-core repos --- .../dev/tooling/commands/validate/dep.py | 88 ++++++++++--------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py index c44c36a4da4b8..3f28348e46fed 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py @@ -105,7 +105,7 @@ def verify_base_dependency(source, check_name, dependency, force_pinned=True, mi return not failed -def verify_dependency(source, name, python_versions, file): +def verify_dependency(source, name, python_versions, file, repo_core): for dependency_definitions in python_versions.values(): # Identify dependencies that are defined multiple times for the same set of environment markers requirements = [Requirement(dep) for dep in dependency_definitions] @@ -142,30 +142,31 @@ def verify_dependency(source, name, python_versions, file): return False return True + + if repo_core: + if not specifier_set: + message = f'Unpinned version found for dependency `{name}`: {format_check_usage(checks, source)}' + echo_failure(message) + annotate_error(file, message) + return False + elif len(specifier_set) > 1: + message = ( + f'Multiple unstable version pins `{specifier_set}` found for dependency `{name}` ' + f'(use a single == explicitly): {format_check_usage(checks, source)}' + ) + echo_failure(message) + annotate_error(file, message) + return False - if not specifier_set: - message = f'Unpinned version found for dependency `{name}`: {format_check_usage(checks, source)}' - echo_failure(message) - annotate_error(file, message) - return False - elif len(specifier_set) > 1: - message = ( - f'Multiple unstable version pins `{specifier_set}` found for dependency `{name}` ' - f'(use a single == explicitly): {format_check_usage(checks, source)}' - ) - echo_failure(message) - annotate_error(file, message) - return False - - specifier = get_next(specifier_set) - if specifier.operator != '==': - message = ( - f'Unstable version pin `{specifier}` found for dependency `{name}` ' - f'(use == explicitly): {format_check_usage(checks, source)}' - ) - echo_failure(message) - annotate_error(file, message) - return False + specifier = get_next(specifier_set) + if specifier.operator != '==': + message = ( + f'Unstable version pin `{specifier}` found for dependency `{name}` ' + f'(use == explicitly): {format_check_usage(checks, source)}' + ) + echo_failure(message) + annotate_error(file, message) + return False return True @@ -184,7 +185,7 @@ def dep(check, require_base_check_version, min_base_check_version): \b * Verify the uniqueness of dependency versions across all checks, or optionally a single check - * Verify all the dependencies are pinned. + * Verify all the dependencies are pinned when validating from integrations-core. * Verify the embedded Python environment defined in the base check and requirements listed in every integration are compatible. * Verify each check specifies a `CHECKS_BASE_REQ` variable for `datadog-checks-base` requirement @@ -197,6 +198,7 @@ def dep(check, require_base_check_version, min_base_check_version): agent_dependencies, agent_errors = read_agent_dependencies() agent_dependencies_file = get_agent_requirements() annotate_errors(agent_dependencies_file, agent_errors) + repo_core = "integrations-core" in root if agent_errors: for agent_error in agent_errors: echo_failure(agent_error) @@ -225,18 +227,17 @@ def dep(check, require_base_check_version, min_base_check_version): echo_failure(check_error) for name, versions in sorted(check_dependencies.items()): - if not verify_dependency('Checks', name, versions, req_source): + if not verify_dependency('Checks', name, versions, req_source, repo_core): failed = True - - if name not in agent_dependencies: - failed = True - message = ( - f'Dependency {name} found in the {check_name} integration requirements ' - 'but not in the agent requirements, run `ddev dep freeze` to sync them.' - ) - echo_failure(message) - annotate_error(req_source, message) - + if repo_core: + if name not in agent_dependencies: + failed = True + message = ( + f'Dependency {name} found in the {check_name} integration requirements ' + 'but not in the agent requirements, run `ddev dep freeze` to sync them.' + ) + echo_failure(message) + annotate_error(req_source, message) check_base_dependencies, check_base_errors = read_check_base_dependencies(checks) check_dependencies, check_errors = read_check_dependencies(checks) @@ -247,17 +248,18 @@ def dep(check, require_base_check_version, min_base_check_version): failed = True for name, python_versions in sorted(agent_dependencies.items()): - if not verify_dependency('Agent', name, python_versions, agent_dependencies_file): + if not verify_dependency('Agent', name, python_versions, agent_dependencies_file, repo_core): failed = True # Check that this dependency defined on the agent requirements is actually used # This only makes sense when we take all check dependencies into account - if check is None and name not in check_dependencies: - failed = True - message = f'Stale dependency needs to be removed by syncing: {name}' - echo_failure(message) - annotate_error(agent_dependencies_file, message) - continue + if repo_core: + if check is None and name not in check_dependencies: + failed = True + message = f'Stale dependency needs to be removed by syncing: {name}' + echo_failure(message) + annotate_error(agent_dependencies_file, message) + continue # Look for version mismatches for this dependency against individual checks agent_dependency_definitions = get_dependency_set(python_versions) From abed450f68ff43bb7aa590aeb7d33d94240d3660 Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Thu, 30 Apr 2026 18:26:17 -0400 Subject: [PATCH 02/12] Adding tests to detect repo path --- ddev/tests/cli/validate/conftest.py | 22 +++++++++++++++ ddev/tests/cli/validate/test_dep.py | 42 +++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/ddev/tests/cli/validate/conftest.py b/ddev/tests/cli/validate/conftest.py index 81a25215b93c8..a817e66b7a491 100644 --- a/ddev/tests/cli/validate/conftest.py +++ b/ddev/tests/cli/validate/conftest.py @@ -95,6 +95,28 @@ def fake_repo( ) +@pytest.fixture +def fake_integrations_core_repo( + tmp_path_factory, + config_file, + mocker, +): + """Like ``fake_repo``, but path includes ``integrations-core`` so ``validate dep`` sets ``repo_core`` true.""" + mocker.patch('ddev.utils.git.GitRepository.worktrees', return_value=[]) + + set_root('') + repo_path = tmp_path_factory.mktemp('integrations-core') + repo = Repository('core', str(repo_path)) + + config_file.model.repos['core'] = str(repo.path) + config_file.model.repo = 'core' + config_file.save() + for file_path, file_name, content in FILES_IN_FAKE_REPO: + write_file(repo_path / file_path, file_name, content) + + yield repo + + @pytest.fixture def fake_extras_repo( request, diff --git a/ddev/tests/cli/validate/test_dep.py b/ddev/tests/cli/validate/test_dep.py index a4a223b5baed8..1a1f9c3bcae83 100644 --- a/ddev/tests/cli/validate/test_dep.py +++ b/ddev/tests/cli/validate/test_dep.py @@ -105,3 +105,45 @@ def test_one_valid_one_invalid_integration(fake_repo, ddev): assert match_regex.match(result.output), f"Unexpected output: {result.output}" assert result_2.exit_code == 1 assert error_regex.search(result_2.output), f"Unexpected output: {result_2.output}" + + +def _write_git_dep_check(repo_path, check_name: str) -> None: + git_dep = 'sample_git_pkg @ git+https://github.com/pypa/pip.git@24.0' + write_file( + repo_path, + 'agent_requirements.in', + f"""datadog-checks-base==37.21.0 +{git_dep} +""", + ) + write_file( + repo_path / check_name, + 'pyproject.toml', + f""" + [project] + dependencies = [ + "datadog-checks-base>=37.21.0", + ] + + [project.optional-dependencies] + libs = [ + "{git_dep}", + ] + """, + ) + + +def test_validate_dep_core_path(fake_integrations_core_repo, ddev): + assert 'integrations-core' in str(fake_integrations_core_repo.path) + _write_git_dep_check(fake_integrations_core_repo.path, 'git_dep_check') + result = ddev('validate', 'dep', 'git_dep_check') + assert result.exit_code == 0 + assert match_regex.match(result.output), f"Unexpected output: {result.output}" + + +def test_validate_dep_non_core_path(fake_repo, ddev): + assert 'integrations-core' not in str(fake_repo.path) + _write_git_dep_check(fake_repo.path, 'git_dep_check') + result = ddev('validate', 'dep', 'git_dep_check') + assert result.exit_code == 0 + assert match_regex.match(result.output), f"Unexpected output: {result.output}" From 9715263aeaadca75c9e4e38172895200ef2d9f52 Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Mon, 4 May 2026 15:54:19 -0400 Subject: [PATCH 03/12] Define integrations-core repo more accurately --- .../dev/tooling/commands/validate/dep.py | 3 +- ddev/tests/cli/validate/conftest.py | 22 ------ ddev/tests/cli/validate/test_dep.py | 70 ++++++++++++++++--- 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py index 3f28348e46fed..ddd0b709bfc0f 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py @@ -198,7 +198,8 @@ def dep(check, require_base_check_version, min_base_check_version): agent_dependencies, agent_errors = read_agent_dependencies() agent_dependencies_file = get_agent_requirements() annotate_errors(agent_dependencies_file, agent_errors) - repo_core = "integrations-core" in root + ctx = click.get_current_context() + repo_core = ctx.obj['repo_choice'] == 'core' if agent_errors: for agent_error in agent_errors: echo_failure(agent_error) diff --git a/ddev/tests/cli/validate/conftest.py b/ddev/tests/cli/validate/conftest.py index a817e66b7a491..81a25215b93c8 100644 --- a/ddev/tests/cli/validate/conftest.py +++ b/ddev/tests/cli/validate/conftest.py @@ -95,28 +95,6 @@ def fake_repo( ) -@pytest.fixture -def fake_integrations_core_repo( - tmp_path_factory, - config_file, - mocker, -): - """Like ``fake_repo``, but path includes ``integrations-core`` so ``validate dep`` sets ``repo_core`` true.""" - mocker.patch('ddev.utils.git.GitRepository.worktrees', return_value=[]) - - set_root('') - repo_path = tmp_path_factory.mktemp('integrations-core') - repo = Repository('core', str(repo_path)) - - config_file.model.repos['core'] = str(repo.path) - config_file.model.repo = 'core' - config_file.save() - for file_path, file_name, content in FILES_IN_FAKE_REPO: - write_file(repo_path / file_path, file_name, content) - - yield repo - - @pytest.fixture def fake_extras_repo( request, diff --git a/ddev/tests/cli/validate/test_dep.py b/ddev/tests/cli/validate/test_dep.py index 1a1f9c3bcae83..08a2d6ab28903 100644 --- a/ddev/tests/cli/validate/test_dep.py +++ b/ddev/tests/cli/validate/test_dep.py @@ -107,6 +107,22 @@ def test_one_valid_one_invalid_integration(fake_repo, ddev): assert error_regex.search(result_2.output), f"Unexpected output: {result_2.output}" +UNPINNED_OPT_CHECK = 'unpinned_opt_check' + +_UNPINNED_OPTIONAL_DEP = 'acme-unpinned-lib' +_PYPROJECT_UNPINNED_OPTIONAL = f""" + [project] + dependencies = [ + "datadog-checks-base>=37.21.0", + ] + + [project.optional-dependencies] + libs = [ + "{_UNPINNED_OPTIONAL_DEP}", + ] + """ + + def _write_git_dep_check(repo_path, check_name: str) -> None: git_dep = 'sample_git_pkg @ git+https://github.com/pypa/pip.git@24.0' write_file( @@ -133,17 +149,55 @@ def _write_git_dep_check(repo_path, check_name: str) -> None: ) -def test_validate_dep_core_path(fake_integrations_core_repo, ddev): - assert 'integrations-core' in str(fake_integrations_core_repo.path) - _write_git_dep_check(fake_integrations_core_repo.path, 'git_dep_check') - result = ddev('validate', 'dep', 'git_dep_check') - assert result.exit_code == 0 +def test_core_rejects_unpinned_optional_dependency(fake_repo, ddev): + """With `-c`, unpinned PyPI deps under optional-dependencies fail validation.""" + write_file( + fake_repo.path, + 'agent_requirements.in', + f"""datadog-checks-base==37.21.0 +{_UNPINNED_OPTIONAL_DEP}==1.0.0 +""", + ) + write_file(fake_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + result = ddev('-c', 'validate', 'dep', UNPINNED_OPT_CHECK) + assert result.exit_code == 1 + assert 'Unpinned version' in result.output + + +def test_extras_allows_unpinned_optional_dependency(fake_extras_repo, ddev): + """With `-e`, unpinned optional PyPI deps are allowed (no integrations-core pin rules).""" + write_file( + fake_extras_repo.path, + 'agent_requirements.in', + """datadog-checks-base>=37.21.0 +""", + ) + write_file(fake_extras_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + result = ddev('-e', 'validate', 'dep', UNPINNED_OPT_CHECK) + assert result.exit_code == 0, result.output + assert 'Unpinned version' not in result.output + assert match_regex.match(result.output), f"Unexpected output: {result.output}" + + +def test_marketplace_allows_unpinned_optional_dependency(fake_marketplace_repo, ddev): + """With `-m`, unpinned optional PyPI deps are allowed (no integrations-core pin rules).""" + write_file( + fake_marketplace_repo.path, + 'agent_requirements.in', + """datadog-checks-base>=37.21.0 +""", + ) + write_file(fake_marketplace_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + result = ddev('-m', 'validate', 'dep', UNPINNED_OPT_CHECK) + assert result.exit_code == 0, result.output + assert 'Unpinned version' not in result.output assert match_regex.match(result.output), f"Unexpected output: {result.output}" -def test_validate_dep_non_core_path(fake_repo, ddev): - assert 'integrations-core' not in str(fake_repo.path) +def test_validate_dep_git_url_succeeds_on_core(fake_repo, ddev): + """Git URL deps return early from verify_dependency and are not treated as unpinned PyPI.""" _write_git_dep_check(fake_repo.path, 'git_dep_check') - result = ddev('validate', 'dep', 'git_dep_check') + result = ddev('-c', 'validate', 'dep', 'git_dep_check') assert result.exit_code == 0 + assert 'Unpinned version' not in result.output assert match_regex.match(result.output), f"Unexpected output: {result.output}" From 7529475e2e64dd49e35d543be32c17140e37d1dc Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Mon, 4 May 2026 16:02:46 -0400 Subject: [PATCH 04/12] Add changelog --- datadog_checks_dev/changelog.d/23584.fixed | 1 + 1 file changed, 1 insertion(+) create mode 100644 datadog_checks_dev/changelog.d/23584.fixed diff --git a/datadog_checks_dev/changelog.d/23584.fixed b/datadog_checks_dev/changelog.d/23584.fixed new file mode 100644 index 0000000000000..9a8e9d0c3c27e --- /dev/null +++ b/datadog_checks_dev/changelog.d/23584.fixed @@ -0,0 +1 @@ +Fixed Detection of Unpinned Dependencies for integrations-extras and marketplace repos From 9ed46e3a47f6bdd014b8bfe8845947b1dc90c7ec Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Mon, 4 May 2026 16:07:22 -0400 Subject: [PATCH 05/12] Fix lint issue --- .../datadog_checks/dev/tooling/commands/validate/dep.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py index ddd0b709bfc0f..81d5dbec529e1 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py @@ -142,7 +142,7 @@ def verify_dependency(source, name, python_versions, file, repo_core): return False return True - + if repo_core: if not specifier_set: message = f'Unpinned version found for dependency `{name}`: {format_check_usage(checks, source)}' From 009ff5a2da064da5076a52632a014c1e622189d7 Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Mon, 4 May 2026 16:48:30 -0400 Subject: [PATCH 06/12] Using repo.name instead of repo.choice --- .../datadog_checks/dev/tooling/commands/validate/dep.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py index 81d5dbec529e1..b5599843f1f6a 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py @@ -199,7 +199,7 @@ def dep(check, require_base_check_version, min_base_check_version): agent_dependencies_file = get_agent_requirements() annotate_errors(agent_dependencies_file, agent_errors) ctx = click.get_current_context() - repo_core = ctx.obj['repo_choice'] == 'core' + repo_core = ctx.obj.repo.name == 'core' if agent_errors: for agent_error in agent_errors: echo_failure(agent_error) From 7a7e1fd9f0ca2434994973b4c4fb2670cb995084 Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Tue, 5 May 2026 10:50:28 -0400 Subject: [PATCH 07/12] Fix repo detection in validate dep so it works across ddev and legacy CLI contexts --- .../dev/tooling/commands/validate/dep.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py index b5599843f1f6a..096281127a477 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py @@ -199,7 +199,15 @@ def dep(check, require_base_check_version, min_base_check_version): agent_dependencies_file = get_agent_requirements() annotate_errors(agent_dependencies_file, agent_errors) ctx = click.get_current_context() - repo_core = ctx.obj.repo.name == 'core' + obj = ctx.obj + repo_choice = None + + if hasattr(obj, 'get'): + repo_choice = obj.get('repo_choice') or obj.get('repo') + if not repo_choice and hasattr(obj, 'repo'): + repo_choice = getattr(obj.repo, 'name', None) + repo_core = repo_choice == 'core' + if agent_errors: for agent_error in agent_errors: echo_failure(agent_error) From 383958a0206b3b49867181249eed16ddc8f866c0 Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Thu, 7 May 2026 17:30:46 -0400 Subject: [PATCH 08/12] Add coverage for ddev validate dep without -c --- ddev/tests/cli/validate/test_dep.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ddev/tests/cli/validate/test_dep.py b/ddev/tests/cli/validate/test_dep.py index 08a2d6ab28903..4841b09dc5800 100644 --- a/ddev/tests/cli/validate/test_dep.py +++ b/ddev/tests/cli/validate/test_dep.py @@ -164,6 +164,21 @@ def test_core_rejects_unpinned_optional_dependency(fake_repo, ddev): assert 'Unpinned version' in result.output +def test_core_rejects_unpinned_optional_dependency_default_repo(fake_repo, ddev): + """Default repo is core: unpinned optional PyPI deps fail without passing `-c`.""" + write_file( + fake_repo.path, + 'agent_requirements.in', + f"""datadog-checks-base==37.21.0 +{_UNPINNED_OPTIONAL_DEP}==1.0.0 +""", + ) + write_file(fake_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + result = ddev('validate', 'dep', UNPINNED_OPT_CHECK) + assert result.exit_code == 1 + assert 'Unpinned version' in result.output + + def test_extras_allows_unpinned_optional_dependency(fake_extras_repo, ddev): """With `-e`, unpinned optional PyPI deps are allowed (no integrations-core pin rules).""" write_file( From f95f26fc64e693c0fe50da6443fc8491467e497b Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Thu, 7 May 2026 17:31:37 -0400 Subject: [PATCH 09/12] Replace duplicate tests with a single parametrized test over repo fixture --- ddev/tests/cli/validate/test_dep.py | 35 +++++++++++++---------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/ddev/tests/cli/validate/test_dep.py b/ddev/tests/cli/validate/test_dep.py index 4841b09dc5800..8ec15b5ae858e 100644 --- a/ddev/tests/cli/validate/test_dep.py +++ b/ddev/tests/cli/validate/test_dep.py @@ -3,6 +3,8 @@ # Licensed under a 3-clause BSD style license (see LICENSE) import re +import pytest + from tests.helpers.api import write_file error_regex = re.compile(r"(?s)^\s*[A-Za-z0-9_\/.-]+\.toml has the following errors:\n(?: - .+\n)+") @@ -179,31 +181,24 @@ def test_core_rejects_unpinned_optional_dependency_default_repo(fake_repo, ddev) assert 'Unpinned version' in result.output -def test_extras_allows_unpinned_optional_dependency(fake_extras_repo, ddev): - """With `-e`, unpinned optional PyPI deps are allowed (no integrations-core pin rules).""" - write_file( - fake_extras_repo.path, - 'agent_requirements.in', - """datadog-checks-base>=37.21.0 -""", - ) - write_file(fake_extras_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) - result = ddev('-e', 'validate', 'dep', UNPINNED_OPT_CHECK) - assert result.exit_code == 0, result.output - assert 'Unpinned version' not in result.output - assert match_regex.match(result.output), f"Unexpected output: {result.output}" - - -def test_marketplace_allows_unpinned_optional_dependency(fake_marketplace_repo, ddev): - """With `-m`, unpinned optional PyPI deps are allowed (no integrations-core pin rules).""" +@pytest.mark.parametrize( + 'repo_fixture, flag', + [ + pytest.param('fake_extras_repo', '-e', id='extras'), + pytest.param('fake_marketplace_repo', '-m', id='marketplace'), + ], +) +def test_non_core_repo_allows_unpinned_optional_dependency(repo_fixture, flag, ddev, request): + """Non-core repos allow unpinned optional PyPI deps (no integrations-core pin rules).""" + repo = request.getfixturevalue(repo_fixture) write_file( - fake_marketplace_repo.path, + repo.path, 'agent_requirements.in', """datadog-checks-base>=37.21.0 """, ) - write_file(fake_marketplace_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) - result = ddev('-m', 'validate', 'dep', UNPINNED_OPT_CHECK) + write_file(repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + result = ddev(flag, 'validate', 'dep', UNPINNED_OPT_CHECK) assert result.exit_code == 0, result.output assert 'Unpinned version' not in result.output assert match_regex.match(result.output), f"Unexpected output: {result.output}" From c3ba20c798c71e4b01b7075aeef0733509ea60a8 Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Thu, 7 May 2026 17:32:12 -0400 Subject: [PATCH 10/12] removing leading underscores on unpinned optional dep constants --- ddev/tests/cli/validate/test_dep.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ddev/tests/cli/validate/test_dep.py b/ddev/tests/cli/validate/test_dep.py index 8ec15b5ae858e..374bf85055b75 100644 --- a/ddev/tests/cli/validate/test_dep.py +++ b/ddev/tests/cli/validate/test_dep.py @@ -111,8 +111,8 @@ def test_one_valid_one_invalid_integration(fake_repo, ddev): UNPINNED_OPT_CHECK = 'unpinned_opt_check' -_UNPINNED_OPTIONAL_DEP = 'acme-unpinned-lib' -_PYPROJECT_UNPINNED_OPTIONAL = f""" +UNPINNED_OPTIONAL_DEP = 'acme-unpinned-lib' +PYPROJECT_UNPINNED_OPTIONAL = f""" [project] dependencies = [ "datadog-checks-base>=37.21.0", @@ -120,7 +120,7 @@ def test_one_valid_one_invalid_integration(fake_repo, ddev): [project.optional-dependencies] libs = [ - "{_UNPINNED_OPTIONAL_DEP}", + "{UNPINNED_OPTIONAL_DEP}", ] """ @@ -157,10 +157,10 @@ def test_core_rejects_unpinned_optional_dependency(fake_repo, ddev): fake_repo.path, 'agent_requirements.in', f"""datadog-checks-base==37.21.0 -{_UNPINNED_OPTIONAL_DEP}==1.0.0 +{UNPINNED_OPTIONAL_DEP}==1.0.0 """, ) - write_file(fake_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + write_file(fake_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', PYPROJECT_UNPINNED_OPTIONAL) result = ddev('-c', 'validate', 'dep', UNPINNED_OPT_CHECK) assert result.exit_code == 1 assert 'Unpinned version' in result.output @@ -172,10 +172,10 @@ def test_core_rejects_unpinned_optional_dependency_default_repo(fake_repo, ddev) fake_repo.path, 'agent_requirements.in', f"""datadog-checks-base==37.21.0 -{_UNPINNED_OPTIONAL_DEP}==1.0.0 +{UNPINNED_OPTIONAL_DEP}==1.0.0 """, ) - write_file(fake_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + write_file(fake_repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', PYPROJECT_UNPINNED_OPTIONAL) result = ddev('validate', 'dep', UNPINNED_OPT_CHECK) assert result.exit_code == 1 assert 'Unpinned version' in result.output @@ -197,7 +197,7 @@ def test_non_core_repo_allows_unpinned_optional_dependency(repo_fixture, flag, d """datadog-checks-base>=37.21.0 """, ) - write_file(repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', _PYPROJECT_UNPINNED_OPTIONAL) + write_file(repo.path, f'{UNPINNED_OPT_CHECK}/pyproject.toml', PYPROJECT_UNPINNED_OPTIONAL) result = ddev(flag, 'validate', 'dep', UNPINNED_OPT_CHECK) assert result.exit_code == 0, result.output assert 'Unpinned version' not in result.output From 95f6fb49738eefb3395f632e18f84a278967e10d Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Fri, 8 May 2026 16:04:04 -0400 Subject: [PATCH 11/12] Use ctx.obj['repo_choice'] instead --- .../datadog_checks/dev/tooling/commands/validate/dep.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py index 096281127a477..b59063f67bebf 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/dep.py @@ -199,14 +199,7 @@ def dep(check, require_base_check_version, min_base_check_version): agent_dependencies_file = get_agent_requirements() annotate_errors(agent_dependencies_file, agent_errors) ctx = click.get_current_context() - obj = ctx.obj - repo_choice = None - - if hasattr(obj, 'get'): - repo_choice = obj.get('repo_choice') or obj.get('repo') - if not repo_choice and hasattr(obj, 'repo'): - repo_choice = getattr(obj.repo, 'name', None) - repo_core = repo_choice == 'core' + repo_core = ctx.obj['repo_choice'] == 'core' if agent_errors: for agent_error in agent_errors: From efa826bfaf0127e520b2ccd504cf5457175e1118 Mon Sep 17 00:00:00 2001 From: ddog-nasirthomas Date: Fri, 8 May 2026 16:09:14 -0400 Subject: [PATCH 12/12] parametrize validate dep tests that used two CLI invokes --- ddev/tests/cli/validate/test_dep.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ddev/tests/cli/validate/test_dep.py b/ddev/tests/cli/validate/test_dep.py index 374bf85055b75..feaf577175b14 100644 --- a/ddev/tests/cli/validate/test_dep.py +++ b/ddev/tests/cli/validate/test_dep.py @@ -44,7 +44,8 @@ def test_invalid_third_party_integration(fake_repo, ddev): assert error_regex.search(result.output), f"Unexpected output: {result.output}" -def test_multiple_invalid_third_party_integrations(fake_repo, ddev): +@pytest.mark.parametrize('check_name', ['bad_check_2', 'bad_check_3']) +def test_multiple_invalid_third_party_integrations(fake_repo, ddev, check_name): write_file( fake_repo.path / 'bad_check_2', 'pyproject.toml', @@ -69,15 +70,13 @@ def test_multiple_invalid_third_party_integrations(fake_repo, ddev): """, ) - result = ddev('validate', 'dep', 'bad_check_2') - result_2 = ddev('validate', 'dep', 'bad_check_3') + result = ddev('validate', 'dep', check_name) assert result.exit_code == 1 assert error_regex.search(result.output), f"Unexpected output: {result.output}" - assert result_2.exit_code == 1 - assert error_regex.search(result_2.output), f"Unexpected output: {result_2.output}" -def test_one_valid_one_invalid_integration(fake_repo, ddev): +@pytest.mark.parametrize('check_name', ['valid_check_2', 'bad_check_4']) +def test_one_valid_one_invalid_integration(fake_repo, ddev, check_name): write_file( fake_repo.path / 'valid_check_2', 'pyproject.toml', @@ -101,12 +100,13 @@ def test_one_valid_one_invalid_integration(fake_repo, ddev): """, ) - result = ddev('validate', 'dep', 'valid_check_2') - result_2 = ddev('validate', 'dep', 'bad_check_4') - assert result.exit_code == 0 - assert match_regex.match(result.output), f"Unexpected output: {result.output}" - assert result_2.exit_code == 1 - assert error_regex.search(result_2.output), f"Unexpected output: {result_2.output}" + result = ddev('validate', 'dep', check_name) + if check_name == 'valid_check_2': + assert result.exit_code == 0 + assert match_regex.match(result.output), f"Unexpected output: {result.output}" + else: + assert result.exit_code == 1 + assert error_regex.search(result.output), f"Unexpected output: {result.output}" UNPINNED_OPT_CHECK = 'unpinned_opt_check'