From c55a09f64df79538ef4dd886ed4e23b65cf54a85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:06:20 +0100 Subject: [PATCH 1/8] Bump the actions group across 1 directory with 3 updates (#22853) Bumps the actions group with 3 updates in the / directory: [github/codeql-action](https://github.com/github/codeql-action), [DataDog/datadog-static-analyzer-github-action](https://github.com/datadog/datadog-static-analyzer-github-action) and [tj-actions/changed-files](https://github.com/tj-actions/changed-files). Updates `github/codeql-action` from 0ec47d036c68ae0cf94c629009b1029407111281 to babab88e549fbc29e9b0058b5d63e2817a135c17 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0ec47d036c68ae0cf94c629009b1029407111281...0ec47d036c68ae0cf94c629009b1029407111281) Updates `DataDog/datadog-static-analyzer-github-action` from 447086f347f225f777e409c8f2dfbd0e3b1a452d to c0e10d1c37e5b306b85e5bcf29b06bb233a71dc8 - [Release notes](https://github.com/datadog/datadog-static-analyzer-github-action/releases) - [Commits](https://github.com/datadog/datadog-static-analyzer-github-action/compare/447086f347f225f777e409c8f2dfbd0e3b1a452d...c0e10d1c37e5b306b85e5bcf29b06bb233a71dc8) Updates `tj-actions/changed-files` from 47.0.4 to 47.0.5 - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/7dee1b0c1557f278e5c7dc244927139d78c0e22a...22103cc46bda19c2b464ffe86db46df6922fd323) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 0ec47d036c68ae0cf94c629009b1029407111281 dependency-type: direct:production dependency-group: actions - dependency-name: DataDog/datadog-static-analyzer-github-action dependency-version: c0e10d1c37e5b306b85e5bcf29b06bb233a71dc8 dependency-type: direct:production dependency-group: actions - dependency-name: tj-actions/changed-files dependency-version: 47.0.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/datadog-static-analysis.yml | 2 +- .github/workflows/release-hash-check.yml | 2 +- .github/workflows/validate-skip-qa.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 665327a9ace46..932c851e592f6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,7 +31,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0ec47d036c68ae0cf94c629009b1029407111281 + uses: github/codeql-action/init@babab88e549fbc29e9b0058b5d63e2817a135c17 with: languages: ${{ matrix.language }} config-file: .github/codeql_config.yml @@ -41,7 +41,7 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main - name: Autobuild - uses: github/codeql-action/autobuild@0ec47d036c68ae0cf94c629009b1029407111281 + uses: github/codeql-action/autobuild@babab88e549fbc29e9b0058b5d63e2817a135c17 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0ec47d036c68ae0cf94c629009b1029407111281 + uses: github/codeql-action/analyze@babab88e549fbc29e9b0058b5d63e2817a135c17 diff --git a/.github/workflows/datadog-static-analysis.yml b/.github/workflows/datadog-static-analysis.yml index 893aa7dc25052..94166aa0fc793 100644 --- a/.github/workflows/datadog-static-analysis.yml +++ b/.github/workflows/datadog-static-analysis.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check code meets quality and security standards id: datadog-static-analysis - uses: DataDog/datadog-static-analyzer-github-action@447086f347f225f777e409c8f2dfbd0e3b1a452d # v3.0.0 + uses: DataDog/datadog-static-analyzer-github-action@c0e10d1c37e5b306b85e5bcf29b06bb233a71dc8 # v3.0.0 with: dd_api_key: ${{ secrets.DD_API_KEY }} dd_app_key: ${{ secrets.DD_STATIC_ANALYSIS_APP_KEY }} diff --git a/.github/workflows/release-hash-check.yml b/.github/workflows/release-hash-check.yml index 470a6ab057582..6c1d6c4cd91fe 100644 --- a/.github/workflows/release-hash-check.yml +++ b/.github/workflows/release-hash-check.yml @@ -25,7 +25,7 @@ jobs: - name: Get changed files id: changed-files - uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4 + uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 with: files: .in-toto/*.link diff --git a/.github/workflows/validate-skip-qa.yml b/.github/workflows/validate-skip-qa.yml index 59239db1a8860..f335ebc72ecb4 100644 --- a/.github/workflows/validate-skip-qa.yml +++ b/.github/workflows/validate-skip-qa.yml @@ -18,7 +18,7 @@ jobs: - name: Get files changed id: changed_files - uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # v47.0.4 + uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 with: files: | **/datadog_checks/** From 752021464a5df7c0d188665c8461ed93c26442ce Mon Sep 17 00:00:00 2001 From: NouemanKHAL Date: Tue, 10 Mar 2026 10:46:26 +0100 Subject: [PATCH 2/8] Add branch version suggestion to ddev release branch create (#22824) * add branch suggestion to ddev release branch create * changelog --- ddev/changelog.d/22824.added | 1 + ddev/src/ddev/cli/release/branch/create.py | 45 +++++++++++++++++- ddev/tests/cli/release/branch/test_create.py | 48 +++++++++++++++++++- 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 ddev/changelog.d/22824.added diff --git a/ddev/changelog.d/22824.added b/ddev/changelog.d/22824.added new file mode 100644 index 0000000000000..6afc670bc5c18 --- /dev/null +++ b/ddev/changelog.d/22824.added @@ -0,0 +1 @@ +Add release branch suggestion for `ddev release branch create`. diff --git a/ddev/src/ddev/cli/release/branch/create.py b/ddev/src/ddev/cli/release/branch/create.py index 10f5b4908036a..f4f88fb4a5869 100644 --- a/ddev/src/ddev/cli/release/branch/create.py +++ b/ddev/src/ddev/cli/release/branch/create.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING import click +from packaging.version import Version if TYPE_CHECKING: from ddev.cli.application import Application @@ -19,20 +20,33 @@ @click.command @click.pass_obj -@click.argument('branch_name') -def create(app: Application, branch_name): +@click.argument('branch_name', required=False) +def create(app: Application, branch_name: str | None): r""" Create a branch for a release of the Agent. BRANCH_NAME should match this pattern: ^\d+\.\d+\.x$`, for example `7.52.x`. + If BRANCH_NAME is not provided, the command will suggest the next version based on existing branches. + This command will also create the `backport/` label in GitHub for this release branch. """ + if branch_name is None: + branch_name = click.prompt( + 'What branch name should we create? (hit ENTER to accept suggestion)', + type=str, + default=suggest_next_branch(app), + ) + assert branch_name is not None + if not BRANCH_NAME_REGEX.match(branch_name): app.abort(f'Invalid branch name: {branch_name}. Branch name must match the pattern {BRANCH_NAME_PATTERN}') + if not click.confirm(f'Create and push release branch: {branch_name}?'): + app.abort('Did not get confirmation, aborting. Did not create or push the branch.') + app.display_waiting("Checking out the master branch...") app.repo.git.run('checkout', 'master') app.display_success("Done.") @@ -66,6 +80,33 @@ def create(app: Application, branch_name): app.display_success("All done.") +def suggest_next_branch(app: Application) -> str: + app.display_waiting("Fetching remote branches...") + app.repo.git.run('fetch', 'origin') + + output = app.repo.git.capture('branch', '-r', '--sort=-version:refname', '--list', 'origin/7.*.x') + branches = [line.strip().replace('origin/', '') for line in output.splitlines() if line.strip()] + valid_branches = [b for b in branches if BRANCH_NAME_REGEX.match(b)] + + if not valid_branches: + return '7.0.x' + + major = Version(valid_branches[0].replace('.x', '.0')).major + minors = sorted(Version(b.replace('.x', '.0')).minor for b in valid_branches) + + for i in range(len(minors) - 1): + if minors[i + 1] - minors[i] > 1: + missing = minors[i] + 1 + suggestion = f'{major}.{missing}.x' + app.display_warning( + f'Gap detected: {major}.{minors[i]}.x is followed by {major}.{minors[i + 1]}.x. ' + f'Suggesting {suggestion} to fill the gap.' + ) + return suggestion + + return f'{major}.{minors[-1] + 1}.x' + + def ensure_build_agent_yaml_updated(app: Application, branch_name: str) -> bool: """ Ensure build_agent.yaml points to the correct agent branch for release builds. diff --git a/ddev/tests/cli/release/branch/test_create.py b/ddev/tests/cli/release/branch/test_create.py index 3905dbfc91159..64181f5930a0a 100644 --- a/ddev/tests/cli/release/branch/test_create.py +++ b/ddev/tests/cli/release/branch/test_create.py @@ -15,7 +15,10 @@ pytest.param("7.x", id='not enough parts'), ], ) -def test_create_invalid_branch_name(ddev, name): +def test_create_invalid_branch_name(ddev, name, mocker): + # Mock the confirmation to bypass it (we're testing validation, not confirmation) + mocker.patch('click.confirm', return_value=True) + result = ddev('release', 'branch', 'create', name) assert result.exit_code == 1, result.output assert f'Invalid branch name: {name}. Branch name must match the pattern ^\\d+\\.\\d+\\.x$\n' in result.output @@ -33,6 +36,8 @@ def test_create_branch(ddev, mocker, yaml_updated, expected_git_call_count): run_mock = mocker.patch('ddev.utils.git.GitRepository.run') mocker.patch('ddev.utils.github.GitHubManager.create_label') mocker.patch('ddev.cli.release.branch.create.ensure_build_agent_yaml_updated', return_value=yaml_updated) + # Mock the confirmation prompt to return True + mocker.patch('click.confirm', return_value=True) result = ddev('release', 'branch', 'create', '5.5.x') @@ -91,3 +96,44 @@ def test_ensure_build_agent_yaml_updated_file_not_found(mocker, tmp_path): assert result is False app_mock.display_warning.assert_called_once() + + +def test_create_branch_confirmation_required(ddev, mocker): + mocker.patch('ddev.utils.git.GitRepository.run') + mocker.patch('ddev.utils.github.GitHubManager.create_label') + mocker.patch('ddev.cli.release.branch.create.ensure_build_agent_yaml_updated', return_value=False) + mocker.patch('click.confirm', return_value=False) + + result = ddev('release', 'branch', 'create', '5.5.x') + + assert result.exit_code == 1, result.output + assert 'Did not get confirmation' in result.output + + +def test_create_branch_with_suggestion(ddev, mocker): + mocker.patch('ddev.utils.git.GitRepository.run') + mocker.patch('ddev.utils.git.GitRepository.capture', return_value=' origin/7.77.x\n origin/7.76.x\n') + mocker.patch('ddev.utils.github.GitHubManager.create_label') + mocker.patch('ddev.cli.release.branch.create.ensure_build_agent_yaml_updated', return_value=False) + mocker.patch('click.prompt', return_value='7.78.x') + mocker.patch('click.confirm', return_value=True) + + result = ddev('release', 'branch', 'create') + + assert result.exit_code == 0, result.output + assert 'Creating the release branch `7.78.x`' in result.output + + +def test_create_branch_with_gap_suggests_missing_branch(ddev, mocker): + mocker.patch('ddev.utils.git.GitRepository.run') + mocker.patch('ddev.utils.git.GitRepository.capture', return_value=' origin/7.62.x\n origin/7.60.x\n') + mocker.patch('ddev.utils.github.GitHubManager.create_label') + mocker.patch('ddev.cli.release.branch.create.ensure_build_agent_yaml_updated', return_value=False) + mocker.patch('click.prompt', return_value='7.61.x') + mocker.patch('click.confirm', return_value=True) + + result = ddev('release', 'branch', 'create') + + assert result.exit_code == 0, result.output + assert 'Gap detected' in result.output + assert 'Creating the release branch `7.61.x`' in result.output From 5db74c0e788acad6afec6cb80a00c07317779f64 Mon Sep 17 00:00:00 2001 From: "datadog-agent-integrations-bot[bot]" <159767151+datadog-agent-integrations-bot[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 09:46:59 +0000 Subject: [PATCH 3/8] Update dependencies (#22837) * Update dependencies * Fix changelog number --------- Co-authored-by: FlorentClarret <1266346+FlorentClarret@users.noreply.github.com> Co-authored-by: Juanpe Araque --- LICENSE-3rdparty.csv | 2 +- agent_requirements.in | 22 ++++++++++----------- amazon_msk/changelog.d/22837.added | 1 + amazon_msk/pyproject.toml | 2 +- clickhouse/changelog.d/22837.added | 1 + clickhouse/pyproject.toml | 2 +- datadog_checks_base/changelog.d/22837.added | 1 + datadog_checks_base/pyproject.toml | 14 ++++++------- kafka_actions/changelog.d/22837.added | 1 + kafka_actions/pyproject.toml | 2 +- kafka_consumer/changelog.d/22837.added | 1 + kafka_consumer/pyproject.toml | 6 +++--- mongo/changelog.d/22837.added | 1 + mongo/pyproject.toml | 2 +- mysql/changelog.d/22837.added | 1 + mysql/pyproject.toml | 4 ++-- postgres/changelog.d/22837.added | 1 + postgres/pyproject.toml | 4 ++-- redisdb/changelog.d/22837.added | 1 + redisdb/pyproject.toml | 2 +- riakcs/changelog.d/22837.added | 1 + riakcs/pyproject.toml | 2 +- snowflake/changelog.d/22837.added | 1 + snowflake/pyproject.toml | 2 +- 24 files changed, 44 insertions(+), 33 deletions(-) create mode 100644 amazon_msk/changelog.d/22837.added create mode 100644 clickhouse/changelog.d/22837.added create mode 100644 datadog_checks_base/changelog.d/22837.added create mode 100644 kafka_actions/changelog.d/22837.added create mode 100644 kafka_consumer/changelog.d/22837.added create mode 100644 mongo/changelog.d/22837.added create mode 100644 mysql/changelog.d/22837.added create mode 100644 postgres/changelog.d/22837.added create mode 100644 redisdb/changelog.d/22837.added create mode 100644 riakcs/changelog.d/22837.added create mode 100644 snowflake/changelog.d/22837.added diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index f0b3b35a6310e..289ec2c29d73b 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -35,7 +35,7 @@ lazy-loader,PyPI,BSD-3-Clause,"Copyright (c) 2022--2023, Scientific Python proje ldap3,PyPI,LGPL-3.0-only,Copyright 2013 - 2020 Giovanni Cannata lxml,PyPI,BSD-3-Clause,Copyright (c) 2004 Infrae. All rights reserved. lz4,PyPI,BSD-3-Clause,"Copyright (c) 2012-2013, Steeve Morin" -mmh3,PyPI,CC0-1.0,Copyright (c) 2011-2025 Hajime Senuma +mmh3,PyPI,CC0-1.0,Copyright (c) 2011-2026 Hajime Senuma oauthlib,PyPI,BSD-3-Clause,Copyright (c) The OAuthlib Community openstacksdk,PyPI,Apache-2.0,Copyright OpenStack orjson,PyPI,Apache-2.0, diff --git a/agent_requirements.in b/agent_requirements.in index 7a400181b0372..abc7cb8880e79 100644 --- a/agent_requirements.in +++ b/agent_requirements.in @@ -4,14 +4,14 @@ aws-requests-auth==0.4.3 azure-identity==1.25.2 beautifulsoup4==4.14.3 binary==1.0.2 -boto3==1.42.54 -botocore==1.42.54 -cachetools==7.0.1 -clickhouse-connect==0.11.0 +boto3==1.42.63 +botocore==1.42.63 +cachetools==7.0.4 +clickhouse-connect==0.13.0 cm-client==45.0.4 confluent-kafka==2.13.0 cryptography==46.0.5 -ddtrace==3.19.5 +ddtrace==4.5.1 dnspython==2.8.0 fastavro==1.12.1 foundationdb==6.3.25 @@ -19,18 +19,18 @@ hazelcast-python-client==5.6.0 in-toto==2.0.0 jellyfish==1.2.1 kubernetes==35.0.0 -lazy-loader==0.4 +lazy-loader==0.5 ldap3==2.9.1 lxml==6.0.1 lz4==4.4.5 -mmh3==5.2.0 +mmh3==5.2.1 oauthlib==3.3.1 openstacksdk==4.10.0 orjson==3.11.7 packaging==26.0 paramiko==4.0.0 prometheus-client==0.24.1 -protobuf==6.33.5 +protobuf==7.34.0 psutil==6.0.0 psycopg[c,pool]==3.3.3 pyasn1==0.4.8 @@ -50,7 +50,7 @@ python3-gearman==0.1.0; sys_platform != 'win32' pyvmomi==8.0.3.0.1 pywin32==311; sys_platform == 'win32' pyyaml==6.0.3 -redis==7.2.0 +redis==7.3.0 requests-kerberos==0.15.0 requests-ntlm==1.3.0 requests-oauthlib==2.0.0 @@ -62,9 +62,9 @@ securesystemslib[crypto,pynacl]==0.28.0 semver==3.0.4 service-identity[idna]==24.2.0 simplejson==3.20.2 -snowflake-connector-python==4.0.0 +snowflake-connector-python==4.3.0 supervisor==4.3.0 tuf==4.0.0 urllib3==2.6.3 vertica-python==1.4.0 -wrapt==2.1.1 +wrapt==2.1.2 diff --git a/amazon_msk/changelog.d/22837.added b/amazon_msk/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/amazon_msk/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/amazon_msk/pyproject.toml b/amazon_msk/pyproject.toml index d2af9a2a91c50..9f8f7491a97f9 100644 --- a/amazon_msk/pyproject.toml +++ b/amazon_msk/pyproject.toml @@ -36,7 +36,7 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ - "boto3==1.42.54", + "boto3==1.42.63", ] [project.urls] diff --git a/clickhouse/changelog.d/22837.added b/clickhouse/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/clickhouse/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/clickhouse/pyproject.toml b/clickhouse/pyproject.toml index f150b4640281f..07de790962a61 100644 --- a/clickhouse/pyproject.toml +++ b/clickhouse/pyproject.toml @@ -36,7 +36,7 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ - "clickhouse-connect==0.11.0", + "clickhouse-connect==0.13.0", "lz4==4.4.5", ] diff --git a/datadog_checks_base/changelog.d/22837.added b/datadog_checks_base/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/datadog_checks_base/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/datadog_checks_base/pyproject.toml b/datadog_checks_base/pyproject.toml index 034181eb3493a..1b66d5475e802 100644 --- a/datadog_checks_base/pyproject.toml +++ b/datadog_checks_base/pyproject.toml @@ -31,17 +31,17 @@ license = "BSD-3-Clause" [project.optional-dependencies] db = [ - "mmh3==5.2.0", + "mmh3==5.2.1", ] deps = [ "binary==1.0.2", - "cachetools==7.0.1", + "cachetools==7.0.4", "cryptography==46.0.5", - "ddtrace==3.19.5", + "ddtrace==4.5.1", "jellyfish==1.2.1", - "lazy-loader==0.4", + "lazy-loader==0.5", "prometheus-client==0.24.1", - "protobuf==6.33.5", + "protobuf==7.34.0", "pydantic==2.12.5", "python-dateutil==2.9.0.post0", "pywin32==311; sys_platform == 'win32'", @@ -51,11 +51,11 @@ deps = [ "requests==2.32.5", "simplejson==3.20.2", "urllib3==2.6.3", - "wrapt==2.1.1", + "wrapt==2.1.2", ] http = [ "aws-requests-auth==0.4.3", - "botocore==1.42.54", + "botocore==1.42.63", "oauthlib==3.3.1", "pyjwt==2.11.0", "pyopenssl==25.3.0", diff --git a/kafka_actions/changelog.d/22837.added b/kafka_actions/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/kafka_actions/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/kafka_actions/pyproject.toml b/kafka_actions/pyproject.toml index 9ca3c99c63401..6f7b25c4460ec 100644 --- a/kafka_actions/pyproject.toml +++ b/kafka_actions/pyproject.toml @@ -39,7 +39,7 @@ dynamic = [ deps = [ "confluent-kafka==2.13.0", "fastavro==1.12.1", - "protobuf==6.33.5", + "protobuf==7.34.0", "pymongo[srv]==4.8.0; python_version >= '3.9'", ] diff --git a/kafka_consumer/changelog.d/22837.added b/kafka_consumer/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/kafka_consumer/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/kafka_consumer/pyproject.toml b/kafka_consumer/pyproject.toml index 7ae493cc16594..ecb94e517df85 100644 --- a/kafka_consumer/pyproject.toml +++ b/kafka_consumer/pyproject.toml @@ -36,11 +36,11 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ - "confluent-kafka==2.13.0", "aws-msk-iam-sasl-signer-python==1.0.2", - "boto3==1.42.54", + "boto3==1.42.63", + "confluent-kafka==2.13.0", "fastavro==1.12.1", - "protobuf==6.33.5", + "protobuf==7.34.0", ] [project.urls] diff --git a/mongo/changelog.d/22837.added b/mongo/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/mongo/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/mongo/pyproject.toml b/mongo/pyproject.toml index a3a335b003f94..fa60fa768c0f5 100644 --- a/mongo/pyproject.toml +++ b/mongo/pyproject.toml @@ -37,7 +37,7 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ - "cachetools==7.0.1", + "cachetools==7.0.4", "psutil==6.0.0", "pymongo[srv]==4.8.0; python_version >= '3.9'", ] diff --git a/mysql/changelog.d/22837.added b/mysql/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/mysql/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/mysql/pyproject.toml b/mysql/pyproject.toml index 460183089cc2d..a3a9a39b1cfdf 100644 --- a/mysql/pyproject.toml +++ b/mysql/pyproject.toml @@ -36,8 +36,8 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ - "boto3==1.42.54", - "cachetools==7.0.1", + "boto3==1.42.63", + "cachetools==7.0.4", "cryptography==46.0.5", "pymysql==1.1.2", ] diff --git a/postgres/changelog.d/22837.added b/postgres/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/postgres/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/postgres/pyproject.toml b/postgres/pyproject.toml index 6b7d06cb84d85..d236fd0358f49 100644 --- a/postgres/pyproject.toml +++ b/postgres/pyproject.toml @@ -38,8 +38,8 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ "azure-identity==1.25.2", - "boto3==1.42.54", - "cachetools==7.0.1", + "boto3==1.42.63", + "cachetools==7.0.4", "psycopg[c,pool]==3.3.3", "semver==3.0.4", ] diff --git a/redisdb/changelog.d/22837.added b/redisdb/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/redisdb/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/redisdb/pyproject.toml b/redisdb/pyproject.toml index 9f90bc25aa45b..bdbb8e57b3b88 100644 --- a/redisdb/pyproject.toml +++ b/redisdb/pyproject.toml @@ -36,7 +36,7 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ - "redis==7.2.0", + "redis==7.3.0", ] [project.urls] diff --git a/riakcs/changelog.d/22837.added b/riakcs/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/riakcs/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/riakcs/pyproject.toml b/riakcs/pyproject.toml index 3fede4a7d3ca2..2635ec64bddb9 100644 --- a/riakcs/pyproject.toml +++ b/riakcs/pyproject.toml @@ -36,7 +36,7 @@ dynamic = [ [project.optional-dependencies] deps = [ - "boto3==1.42.54", + "boto3==1.42.63", ] [project.urls] diff --git a/snowflake/changelog.d/22837.added b/snowflake/changelog.d/22837.added new file mode 100644 index 0000000000000..af47fee9d6a90 --- /dev/null +++ b/snowflake/changelog.d/22837.added @@ -0,0 +1 @@ +Update dependencies \ No newline at end of file diff --git a/snowflake/pyproject.toml b/snowflake/pyproject.toml index 85929264881d3..d47450811cf4d 100644 --- a/snowflake/pyproject.toml +++ b/snowflake/pyproject.toml @@ -37,7 +37,7 @@ license = "BSD-3-Clause" [project.optional-dependencies] deps = [ - "snowflake-connector-python==4.0.0", + "snowflake-connector-python==4.3.0", ] [project.urls] From b823450eaf251381d95957cd8852a4c8b23debc5 Mon Sep 17 00:00:00 2001 From: Ilia Kurenkov Date: Tue, 10 Mar 2026 11:26:25 +0100 Subject: [PATCH 4/8] First property test for OpenMetrics base class. (#22850) * First property test for OpenMetrics base class. * address feedback --- datadog_checks_base/hatch.toml | 1 + .../test_v2/test_property_based.py | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 datadog_checks_base/tests/base/checks/openmetrics/test_v2/test_property_based.py diff --git a/datadog_checks_base/hatch.toml b/datadog_checks_base/hatch.toml index 8406056f46a35..5c01f9358cecb 100644 --- a/datadog_checks_base/hatch.toml +++ b/datadog_checks_base/hatch.toml @@ -9,6 +9,7 @@ python = ["3.13"] features = ["db", "deps", "http", "json", "kube"] dependencies = [ "datadog_checks_tests_helper @ {root:uri}/../datadog_checks_tests_helper", + "hypothesis", ] e2e-env = false diff --git a/datadog_checks_base/tests/base/checks/openmetrics/test_v2/test_property_based.py b/datadog_checks_base/tests/base/checks/openmetrics/test_v2/test_property_based.py new file mode 100644 index 0000000000000..b9064bee2a299 --- /dev/null +++ b/datadog_checks_base/tests/base/checks/openmetrics/test_v2/test_property_based.py @@ -0,0 +1,60 @@ +# (C) Datadog, Inc. 2026-present +# All rights reserved +# Licensed under a 3-clause BSD style license (see LICENSE) +"""Property-based tests for OpenMetricsBaseCheckV2.""" + +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from .utils import get_check + +pytestmark = pytest.mark.unit + +metric_names = st.from_regex(r'[a-z][0-9a-z]*(?:_[0-9a-z]+)*', fullmatch=True) +metric_values = st.floats(min_value=-1e15, max_value=1e15, allow_nan=False, allow_infinity=False) + + +@st.composite +def gauge_payload_and_mapping(draw): + """Generate a Prometheus gauge payload with unique metric names and a subset mapping.""" + names = draw(st.lists(metric_names, min_size=1, max_size=20, unique=True)) + + lines = [] + for name in names: + value = draw(metric_values) + lines.append(f"# HELP {name} generated") + lines.append(f"# TYPE {name} gauge") + # We want to avoid float formatting like "1e+15", so we force the full number. + lines.append(f"{name} {value:.17g}") + + payload = "\n".join(lines) + mapped = draw(st.lists(st.sampled_from(names), min_size=1, unique=True)) + + return payload, names, mapped + + +@given(data=gauge_payload_and_mapping()) +@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]) +def test_gauge_submission_count_lower_bound(aggregator, dd_run_check, mock_http_response, data): + """The aggregator receives at least one submission per mapped gauge metric. + + For gauge metrics the relationship is exact: each mapped metric name in + the payload produces exactly one gauge submission. We assert the weaker + '>=' bound so the property generalises to other metric types too. + """ + payload, _all_names, mapped = data + + aggregator.reset() + mock_http_response(payload) + check = get_check({"metrics": list(mapped)}) + dd_run_check(check) + + submitted = set(aggregator.metric_names) + expected = {f"test.{name}" for name in mapped} + + assert expected <= submitted, ( + f"Mapped metric(s) missing from aggregator.\n" + f" Expected (at least): {sorted(expected)}\n" + f" Got: {sorted(submitted)}" + ) From cb7d9e95c2416555f60dfd7c0bb79b5cfbb64df9 Mon Sep 17 00:00:00 2001 From: Alexey Pilyugin Date: Tue, 10 Mar 2026 12:24:52 +0100 Subject: [PATCH 5/8] Add dataflows definition for airflow (#22805) Add dataflows definition for airflow --- airflow/assets/dataflows.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 airflow/assets/dataflows.yaml diff --git a/airflow/assets/dataflows.yaml b/airflow/assets/dataflows.yaml new file mode 100644 index 0000000000000..4e282650f4aae --- /dev/null +++ b/airflow/assets/dataflows.yaml @@ -0,0 +1,9 @@ +provides: + - id: airflow-metrics + always_on: true + data_type: metrics + direction: inbound + - id: airflow-logs + always_on: false + data_type: logs + direction: inbound From 1fb463664b3f52bc25aba7499deecac3f73c0d13 Mon Sep 17 00:00:00 2001 From: Alexey Pilyugin Date: Tue, 10 Mar 2026 12:30:44 +0100 Subject: [PATCH 6/8] Try out the new registry (#22202) * Try out the new registry * Fix expression * Fix some formatting * Lint * Fix ddev e2e * Fix lint and add changelog * Few more images * Remove py2-windows * Fix one in test-all * Revert e5bb3541fadebbc4d81298300b32dd2fc49d2b11 Remove todo's * Changelog changed -> fixed * Remove to-do * Try keeping hatch up to date * Try pinning virtualenv * master-py3 --- .github/workflows/test-agent-target.yml | 4 +- .github/workflows/test-agent-windows.yml | 6 +- .github/workflows/test-agent.yml | 6 +- .github/workflows/test-all-windows.yml | 4 +- .github/workflows/test-all.yml | 6 +- .github/workflows/test-fips-e2e.yml | 4 +- .github/workflows/test-target.yml | 4 +- .../kerberos/kerberos-agent/Dockerfile | 2 +- datadog_checks_dev/changelog.d/22202.fixed | 1 + .../datadog_checks/dev/tooling/config.py | 6 +- ddev/changelog.d/22202.fixed | 1 + ddev/src/ddev/config/model.py | 4 +- ddev/src/ddev/e2e/agent/docker.py | 4 +- ddev/tests/cli/config/test_set.py | 8 +- ddev/tests/cli/config/test_show.py | 8 +- ddev/tests/cli/env/test_start.py | 32 ++--- ddev/tests/config/test_model.py | 14 +-- ddev/tests/e2e/agent/test_docker.py | 109 ++++++++++-------- 18 files changed, 121 insertions(+), 102 deletions(-) create mode 100644 datadog_checks_dev/changelog.d/22202.fixed create mode 100644 ddev/changelog.d/22202.fixed diff --git a/.github/workflows/test-agent-target.yml b/.github/workflows/test-agent-target.yml index 940254d77efd1..5b13976ce3381 100644 --- a/.github/workflows/test-agent-target.yml +++ b/.github/workflows/test-agent-target.yml @@ -20,7 +20,7 @@ on: agent-image: required: false description: Agent 7 image - default: "datadog/agent:7-rc" + default: "registry.datadoghq.com/agent:7-rc" type: string test-py2: required: false @@ -30,7 +30,7 @@ on: agent-image-py2: required: false description: Agent 6 image - default: "datadog/agent:6-rc" + default: "registry.datadoghq.com/agent:6-rc" type: string platform: required: true diff --git a/.github/workflows/test-agent-windows.yml b/.github/workflows/test-agent-windows.yml index 98979b521dbac..dba54b173a1fe 100644 --- a/.github/workflows/test-agent-windows.yml +++ b/.github/workflows/test-agent-windows.yml @@ -11,12 +11,12 @@ on: agent-image: required: false description: Agent 7 image - default: "datadog/agent:7-rc" + default: "registry.datadoghq.com/agent:7-rc" type: string agent-image-windows: required: false description: Agent 7 image on Windows - default: "datadog/agent:7-rc-servercore" + default: "registry.datadoghq.com/agent:7-rc-servercore" type: string test-py2: required: false @@ -26,7 +26,7 @@ on: agent-image-py2: required: false description: Agent 6 image - default: "datadog/agent:6-rc" + default: "registry.datadoghq.com/agent:6-rc" type: string agent-image-windows-py2: required: false diff --git a/.github/workflows/test-agent.yml b/.github/workflows/test-agent.yml index f862769e98f33..e04504ab428e8 100644 --- a/.github/workflows/test-agent.yml +++ b/.github/workflows/test-agent.yml @@ -11,12 +11,12 @@ on: agent-image: required: false description: Agent 7 image - default: "datadog/agent:7-rc" + default: "registry.datadoghq.com/agent:7-rc" type: string agent-image-windows: required: false description: Agent 7 image on Windows - default: "datadog/agent:7-rc-servercore" + default: "registry.datadoghq.com/agent:7-rc-servercore" type: string test-py2: required: false @@ -26,7 +26,7 @@ on: agent-image-py2: required: false description: Agent 6 image - default: "datadog/agent:6-rc" + default: "registry.datadoghq.com/agent:6-rc" type: string agent-image-windows-py2: required: false diff --git a/.github/workflows/test-all-windows.yml b/.github/workflows/test-all-windows.yml index 90afb07a57b65..1a3c40450a563 100644 --- a/.github/workflows/test-all-windows.yml +++ b/.github/workflows/test-all-windows.yml @@ -35,7 +35,7 @@ on: type: boolean agent-image: required: false - default: "datadog/agent-dev:master-py3" + default: "registry.datadoghq.com/agent-dev:master-py3" type: string agent-image-py2: required: false @@ -43,7 +43,7 @@ on: type: string agent-image-windows: required: false - default: "datadog/agent-dev:master-py3-win-servercore" + default: "registry.datadoghq.com/agent:7-rc-servercore" type: string agent-image-windows-py2: required: false diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index edc4270081353..6044ca874190f 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -33,15 +33,15 @@ on: type: boolean agent-image: required: false - default: "datadog/agent-dev:master-py3" + default: "registry.datadoghq.com/agent-dev:master-py3" type: string agent-image-py2: required: false - default: "datadog/agent-dev:master-py2" + default: "registry.datadoghq.com/agent:6-rc" type: string agent-image-windows: required: false - default: "datadog/agent-dev:master-py3-win-servercore" + default: "registry.datadoghq.com/agent:7-rc-servercore" type: string agent-image-windows-py2: required: false diff --git a/.github/workflows/test-fips-e2e.yml b/.github/workflows/test-fips-e2e.yml index 174fcbc91c461..bc03a976d7cf7 100644 --- a/.github/workflows/test-fips-e2e.yml +++ b/.github/workflows/test-fips-e2e.yml @@ -104,14 +104,14 @@ jobs: - name: Run E2E tests with FIPS disabled env: - DDEV_E2E_AGENT: "${{ inputs.agent-image || 'datadog/agent-dev:master-py3' }}" + DDEV_E2E_AGENT: "${{ inputs.agent-image || 'registry.datadoghq.com/agent-dev:master-py3' }}" DD_API_KEY: "${{ secrets.DD_API_KEY }}" run: | ddev env test --base --new-env --junit ${{ inputs.target || 'tls' }} -- all -m "fips_off" - name: Run E2E tests with FIPS enabled env: - DDEV_E2E_AGENT: "${{ inputs.agent-image-fips || 'datadog/agent-dev:master-fips' }}" + DDEV_E2E_AGENT: "${{ inputs.agent-image-fips || 'registry.datadoghq.com/agent-dev:master-fips' }}" DD_API_KEY: "${{ secrets.DD_API_KEY }}" run: | ddev env test --base --new-env --junit ${{ inputs.target || 'tls' }} -- all -k "fips_on" diff --git a/.github/workflows/test-target.yml b/.github/workflows/test-target.yml index 5bbfc1968e45d..1b2c92814609f 100644 --- a/.github/workflows/test-target.yml +++ b/.github/workflows/test-target.yml @@ -56,7 +56,7 @@ on: type: boolean agent-image: required: false - default: "datadog/agent-dev:master-py3" + default: "registry.datadoghq.com/agent-dev:master-py3" type: string agent-image-py2: required: false @@ -64,7 +64,7 @@ on: type: string agent-image-windows: required: false - default: "datadog/agent-dev:master-py3-win-servercore" + default: "registry.datadoghq.com/agent:7-rc-servercore" type: string agent-image-windows-py2: required: false diff --git a/datadog_checks_base/tests/compose/kerberos/kerberos-agent/Dockerfile b/datadog_checks_base/tests/compose/kerberos/kerberos-agent/Dockerfile index 4ab19e8d6c36d..5f83816f952d7 100644 --- a/datadog_checks_base/tests/compose/kerberos/kerberos-agent/Dockerfile +++ b/datadog_checks_base/tests/compose/kerberos/kerberos-agent/Dockerfile @@ -1,4 +1,4 @@ -FROM datadog/agent:7.25.0-rc.4 +FROM registry.datadoghq.com/agent:7.25.0-rc.4 ENV DEBIAN_FRONTEND=noninteractive diff --git a/datadog_checks_dev/changelog.d/22202.fixed b/datadog_checks_dev/changelog.d/22202.fixed new file mode 100644 index 0000000000000..f84217226c2a9 --- /dev/null +++ b/datadog_checks_dev/changelog.d/22202.fixed @@ -0,0 +1 @@ +Migrate integrations-core tests to the new Datadog Docker registry diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/config.py b/datadog_checks_dev/datadog_checks/dev/tooling/config.py index 432e20660abd6..263a346c07b1a 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/config.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/config.py @@ -43,9 +43,9 @@ 'integrations-internal-core': os.path.join('~', 'dd', 'integrations-internal-core'), }, 'agents': { - 'master': {'docker': 'datadog/agent-dev:master', 'local': 'latest'}, - '7': {'docker': 'datadog/agent:7', 'local': '7'}, - '6': {'docker': 'datadog/agent:6', 'local': '6'}, + 'master': {'docker': 'registry.datadoghq.com/agent-dev:master-py3', 'local': 'latest'}, + '7': {'docker': 'registry.datadoghq.com/agent:7', 'local': '7'}, + '6': {'docker': 'registry.datadoghq.com/agent:6', 'local': '6'}, }, 'orgs': { 'default': { diff --git a/ddev/changelog.d/22202.fixed b/ddev/changelog.d/22202.fixed new file mode 100644 index 0000000000000..f84217226c2a9 --- /dev/null +++ b/ddev/changelog.d/22202.fixed @@ -0,0 +1 @@ +Migrate integrations-core tests to the new Datadog Docker registry diff --git a/ddev/src/ddev/config/model.py b/ddev/src/ddev/config/model.py index 80242e36b184e..493cc089a4938 100644 --- a/ddev/src/ddev/config/model.py +++ b/ddev/src/ddev/config/model.py @@ -201,8 +201,8 @@ def agents(self): self._field_agents = agents else: self._field_agents = self.raw_data['agents'] = { - 'dev': {'docker': 'datadog/agent-dev:master', 'local': 'latest'}, - '7': {'docker': 'datadog/agent:7', 'local': '7'}, + 'dev': {'docker': 'registry.datadoghq.com/agent-dev:master-py3', 'local': 'latest'}, + '7': {'docker': 'registry.datadoghq.com/agent:7', 'local': '7'}, } return self._field_agents diff --git a/ddev/src/ddev/e2e/agent/docker.py b/ddev/src/ddev/e2e/agent/docker.py index 6ec9b390a9a53..5ba3b61969837 100644 --- a/ddev/src/ddev/e2e/agent/docker.py +++ b/ddev/src/ddev/e2e/agent/docker.py @@ -47,12 +47,12 @@ def disable_integration_before_install(config_file): def _normalize_agent_image_name(agent_build: str | None, python_major: int, use_jmx: bool) -> str: if not agent_build: - return 'datadog/agent-dev:master-py3' + return 'registry.datadoghq.com/agent-dev:master-py3' if match := re.match(AGENT_IMAGE_REGEX, agent_build): org, image, tag = match.groups() - if org != 'datadog': + if org != 'datadog' and org != 'registry.datadoghq.com': # Some non datadog image has been selected return agent_build diff --git a/ddev/tests/cli/config/test_set.py b/ddev/tests/cli/config/test_set.py index baa9b40481353..47246e35cb3b7 100644 --- a/ddev/tests/cli/config/test_set.py +++ b/ddev/tests/cli/config/test_set.py @@ -37,20 +37,22 @@ def test_standard_deep(ddev, config_file, helpers): def test_standard_complex(ddev, config_file, helpers): - result = ddev('config', 'set', 'agents.latest', "{'docker': 'datadog/agent:latest', 'local': 'latest'}") + result = ddev( + 'config', 'set', 'agents.latest', "{'docker': 'registry.datadoghq.com/agent:latest', 'local': 'latest'}" + ) assert result.exit_code == 0, result.output assert result.output == helpers.dedent( """ New setting: [agents.latest] - docker = "datadog/agent:latest" + docker = "registry.datadoghq.com/agent:latest" local = "latest" """ ) config_file.load() - assert config_file.model.agents["latest"] == {"docker": "datadog/agent:latest", "local": "latest"} + assert config_file.model.agents["latest"] == {"docker": "registry.datadoghq.com/agent:latest", "local": "latest"} def test_standard_hidden(ddev, config_file, helpers): diff --git a/ddev/tests/cli/config/test_show.py b/ddev/tests/cli/config/test_show.py index 6cc75bc494774..c33ec3fe92f95 100644 --- a/ddev/tests/cli/config/test_show.py +++ b/ddev/tests/cli/config/test_show.py @@ -23,11 +23,11 @@ agent = "{AGENT_PATH}" [agents.dev] -docker = "datadog/agent-dev:master" +docker = "registry.datadoghq.com/agent-dev:master-py3" local = "latest" [agents.7] -docker = "datadog/agent:7" +docker = "registry.datadoghq.com/agent:7" local = "7" [orgs.default] @@ -71,11 +71,11 @@ agent = "{AGENT_PATH}" [agents.dev] -docker = "datadog/agent-dev:master" +docker = "registry.datadoghq.com/agent-dev:master-py3" local = "latest" [agents.7] -docker = "datadog/agent:7" +docker = "registry.datadoghq.com/agent:7" local = "7" [orgs.default] diff --git a/ddev/tests/cli/env/test_start.py b/ddev/tests/cli/env/test_start.py index 2399f37340a92..1ecab0a0256ad 100644 --- a/ddev/tests/cli/env/test_start.py +++ b/ddev/tests/cli/env/test_start.py @@ -91,7 +91,7 @@ def test_stop_on_error(ddev, helpers, data_dir, write_result_file, mocker): assert not env_data.exists() start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com'}, ) @@ -129,7 +129,7 @@ def test_basic(ddev, helpers, data_dir, write_result_file, mocker): assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com'}, ) @@ -169,7 +169,7 @@ def test_agent_build_config(ddev, config_file, helpers, data_dir, write_result_f assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent:7', + agent_build='registry.datadoghq.com/agent:7', local_packages={}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com'}, ) @@ -188,7 +188,7 @@ def test_agent_build_env_var(ddev, config_file, helpers, data_dir, write_result_ environment = 'py3.12' env_data = EnvDataStorage(data_dir).get(integration, environment) - with EnvVars({E2EEnvVars.AGENT_BUILD: 'datadog/agent:6'}): + with EnvVars({E2EEnvVars.AGENT_BUILD: 'registry.datadoghq.com/agent:6'}): result = ddev('env', 'start', integration, environment) assert result.exit_code == 0, result.output @@ -210,7 +210,7 @@ def test_agent_build_env_var(ddev, config_file, helpers, data_dir, write_result_ assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent:6', + agent_build='registry.datadoghq.com/agent:6', local_packages={}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com'}, ) @@ -229,8 +229,8 @@ def test_agent_build_flag(ddev, config_file, helpers, data_dir, write_result_fil environment = 'py3.12' env_data = EnvDataStorage(data_dir).get(integration, environment) - with EnvVars({E2EEnvVars.AGENT_BUILD: 'datadog/agent:6'}): - result = ddev('env', 'start', integration, environment, '-a', 'datadog/agent:7-rc') + with EnvVars({E2EEnvVars.AGENT_BUILD: 'registry.datadoghq.com/agent:6'}): + result = ddev('env', 'start', integration, environment, '-a', 'registry.datadoghq.com/agent:7-rc') assert result.exit_code == 0, result.output assert result.output == helpers.dedent( @@ -251,7 +251,7 @@ def test_agent_build_flag(ddev, config_file, helpers, data_dir, write_result_fil assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent:7-rc', + agent_build='registry.datadoghq.com/agent:7-rc', local_packages={}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com'}, ) @@ -288,7 +288,7 @@ def test_local_dev(ddev, helpers, local_repo, data_dir, write_result_file, mocke assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={local_repo / integration: '[deps]'}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com'}, ) @@ -325,7 +325,7 @@ def test_local_base(ddev, helpers, local_repo, data_dir, write_result_file, mock assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={ local_repo / 'datadog_checks_base': '[db,deps,http,json,kube]', local_repo / integration: '[deps]', @@ -365,7 +365,7 @@ def test_env_vars(ddev, helpers, data_dir, write_result_file, mocker): assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com', 'FOO': 'BAR', 'BAZ': 'BAR'}, ) @@ -402,7 +402,7 @@ def test_env_vars_apm_enabled_from_metadata(ddev, helpers, data_dir, write_resul assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={ 'DD_DD_URL': 'https://app.datadoghq.com', @@ -459,7 +459,7 @@ def test_env_vars_override_config(ddev, helpers, data_dir, write_result_file, mo assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={ 'DD_DD_URL': 'url', @@ -503,7 +503,7 @@ def test_logs_detection(ddev, helpers, data_dir, write_result_file, mocker): assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={'DD_DD_URL': 'https://app.datadoghq.com', 'DD_SITE': 'datadoghq.com', 'DD_LOGS_ENABLED': 'true'}, ) @@ -540,7 +540,7 @@ def test_dogstatsd(ddev, helpers, data_dir, write_result_file, mocker): assert env_data.read_metadata() == metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={ 'DD_DD_URL': 'https://app.datadoghq.com', @@ -598,7 +598,7 @@ def test_mount_log(ddev, helpers, data_dir, write_result_file, mocker): assert env_data.read_metadata() == expected_metadata start.assert_called_once_with( - agent_build='datadog/agent-dev:master', + agent_build='registry.datadoghq.com/agent-dev:master-py3', local_packages={}, env_vars={ 'DD_DD_URL': 'https://app.datadoghq.com', diff --git a/ddev/tests/config/test_model.py b/ddev/tests/config/test_model.py index 37c1f4d13222d..6170b4cd4abac 100644 --- a/ddev/tests/config/test_model.py +++ b/ddev/tests/config/test_model.py @@ -23,8 +23,8 @@ def test_default(): 'agent': os.path.join('~', 'dd', 'datadog-agent'), }, 'agents': { - 'dev': {'docker': 'datadog/agent-dev:master', 'local': 'latest'}, - '7': {'docker': 'datadog/agent:7', 'local': '7'}, + 'dev': {'docker': 'registry.datadoghq.com/agent-dev:master-py3', 'local': 'latest'}, + '7': {'docker': 'registry.datadoghq.com/agent:7', 'local': '7'}, }, 'orgs': { 'default': { @@ -191,7 +191,7 @@ class TestAgent: def test_default(self): config = RootConfig({}) - agent_config = {'docker': 'datadog/agent-dev:master', 'local': 'latest'} + agent_config = {'docker': 'registry.datadoghq.com/agent-dev:master-py3', 'local': 'latest'} assert config.agent.name == config.agent.name == 'dev' assert config.agent.config == config.agent.config == agent_config assert config.agent.raw_data == {'name': 'dev', 'config': agent_config} @@ -213,7 +213,7 @@ def test_invalid_type(self, helpers): def test_defined(self): config = RootConfig({'agent': '7'}) - agent_config = {'docker': 'datadog/agent:7', 'local': '7'} + agent_config = {'docker': 'registry.datadoghq.com/agent:7', 'local': '7'} assert config.agent.name == config.agent.name == '7' assert config.agent.config == config.agent.config == agent_config assert config.agent.raw_data == {'name': '7', 'config': agent_config} @@ -271,7 +271,7 @@ def test_name_set_lazy_error_not_string(self, helpers): config.agent.name = 9000 assert config.agent.raw_data == { 'name': 9000, - 'config': {'docker': 'datadog/agent-dev:master', 'local': 'latest'}, + 'config': {'docker': 'registry.datadoghq.com/agent-dev:master-py3', 'local': 'latest'}, } with pytest.raises( @@ -548,8 +548,8 @@ def test_default(self): config = RootConfig({}) agents = { - 'dev': {'docker': 'datadog/agent-dev:master', 'local': 'latest'}, - '7': {'docker': 'datadog/agent:7', 'local': '7'}, + 'dev': {'docker': 'registry.datadoghq.com/agent-dev:master-py3', 'local': 'latest'}, + '7': {'docker': 'registry.datadoghq.com/agent:7', 'local': '7'}, } assert config.agents == agents assert config.raw_data == {'agents': agents} diff --git a/ddev/tests/e2e/agent/test_docker.py b/ddev/tests/e2e/agent/test_docker.py index 513f3abf0c80d..809f025c909ea 100644 --- a/ddev/tests/e2e/agent/test_docker.py +++ b/ddev/tests/e2e/agent/test_docker.py @@ -31,11 +31,26 @@ class TestStart: @pytest.mark.parametrize( 'agent_build, agent_image, use_jmx', [ - pytest.param('', 'datadog/agent-dev:master-py3', False, id='default'), - pytest.param('datadog/agent:7', 'datadog/agent:7', False, id='release'), - pytest.param('datadog/agent-dev:master-py3', 'datadog/agent-dev:master-py3', False, id='exact'), - pytest.param('datadog/agent-dev:master', 'datadog/agent-dev:master-py3-jmx', True, id='jmx'), - pytest.param('datadog/agent-dev:master-py3-jmx', 'datadog/agent-dev:master-py3-jmx', True, id='jmx exact'), + pytest.param('', 'registry.datadoghq.com/agent-dev:master-py3', False, id='default'), + pytest.param('registry.datadoghq.com/agent:7', 'registry.datadoghq.com/agent:7', False, id='release'), + pytest.param( + 'registry.datadoghq.com/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', + False, + id='exact', + ), + pytest.param( + 'registry.datadoghq.com/agent-dev:master', + 'registry.datadoghq.com/agent-dev:master-py3-jmx', + True, + id='jmx', + ), + pytest.param( + 'registry.datadoghq.com/agent-dev:master-py3-jmx', + 'registry.datadoghq.com/agent-dev:master-py3-jmx', + True, + id='jmx exact', + ), pytest.param( 'my-custom-build-that-I-have-locally', 'my-custom-build-that-I-have-locally', False, id='custom build' ), @@ -46,32 +61,32 @@ class TestStart: id='custom build with jmx', ), pytest.param( - 'datadog/agent:7.46.0', - 'datadog/agent:7.46.0', + 'registry.datadoghq.com/agent:7.46.0', + 'registry.datadoghq.com/agent:7.46.0', False, id='Specific stable release', ), pytest.param( - 'datadog/agent:7.45.0', - 'datadog/agent:7.45.0-jmx', + 'registry.datadoghq.com/agent:7.45.0', + 'registry.datadoghq.com/agent:7.45.0-jmx', True, id='Specific stable release with jmx', ), pytest.param( - 'datadog/agent:6.44.0-jmx', - 'datadog/agent:6.44.0-jmx', + 'registry.datadoghq.com/agent:6.44.0-jmx', + 'registry.datadoghq.com/agent:6.44.0-jmx', True, id='Specific stable release with jmx exact', ), pytest.param( - 'datadog/agent:latest', - 'datadog/agent:latest', + 'registry.datadoghq.com/agent:latest', + 'registry.datadoghq.com/agent:latest', False, id='Latest stable release', ), pytest.param( - 'datadog/agent-dev:master-jmx-win-servercore', - 'datadog/agent-dev:master-py3-jmx-win-servercore', + 'registry.datadoghq.com/agent-dev:master-jmx-win-servercore', + 'registry.datadoghq.com/agent-dev:master-py3-jmx-win-servercore', False, id='Servercore without version', ), @@ -166,7 +181,7 @@ def test_env_vars( ) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -194,7 +209,7 @@ def test_env_vars( 'DD_LOGS_ENABLED=true', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -222,7 +237,7 @@ def test_no_config_file( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -246,7 +261,7 @@ def test_no_config_file( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -278,7 +293,7 @@ def test_windows_container( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -300,7 +315,7 @@ def test_windows_container( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -333,7 +348,7 @@ def test_docker_volumes_linux( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -361,7 +376,7 @@ def test_docker_volumes_linux( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -394,7 +409,7 @@ def test_docker_volumes_windows_running_linux( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -424,7 +439,7 @@ def test_docker_volumes_windows_running_linux( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -457,7 +472,7 @@ def test_docker_volumes_windows_running_windows( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -481,7 +496,7 @@ def test_docker_volumes_windows_running_windows( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -517,9 +532,9 @@ def test_retry_pull_image( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -543,7 +558,7 @@ def test_retry_pull_image( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -575,7 +590,7 @@ def test_custom_hosts( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -605,7 +620,7 @@ def test_custom_hosts( 'host2:127.0.0.1', '--add-host', 'host1:127.0.0.1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -637,7 +652,7 @@ def test_dogstatsd_port( agent.start(agent_build='', local_packages={}, env_vars={'DD_DOGSTATSD_PORT': '9000'}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -667,7 +682,7 @@ def test_dogstatsd_port( 'DD_TELEMETRY_ENABLED=1', '-p', '9000:9000/udp', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -699,7 +714,7 @@ def test_proxies( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -729,7 +744,7 @@ def test_proxies( 'DD_PROXY_HTTPS=https://localhost:4443', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -761,7 +776,7 @@ def test_start_commands( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -787,7 +802,7 @@ def test_start_commands( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -826,7 +841,7 @@ def test_post_install_commands( agent.start(agent_build='', local_packages={}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -852,7 +867,7 @@ def test_post_install_commands( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -891,7 +906,7 @@ def test_local_packages_linux_container( agent.start(agent_build='', local_packages={temp_dir / 'foo': '[deps]'}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -919,7 +934,7 @@ def test_local_packages_linux_container( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -972,7 +987,7 @@ def test_local_packages_windows_container( agent.start(agent_build='', local_packages={temp_dir / 'foo': '[deps]'}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -996,7 +1011,7 @@ def test_local_packages_windows_container( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, @@ -1049,7 +1064,7 @@ def test_all_post_run_logic( agent.start(agent_build='', local_packages={temp_dir / 'foo': '[deps]'}, env_vars={}) assert run.call_args_list == [ - mocker.call([docker_path, 'pull', 'datadog/agent-dev:master-py3'], shell=False), + mocker.call([docker_path, 'pull', 'registry.datadoghq.com/agent-dev:master-py3'], shell=False), mocker.call( [ docker_path, @@ -1077,7 +1092,7 @@ def test_all_post_run_logic( f'DD_HOSTNAME={default_hostname}', '-e', 'DD_TELEMETRY_ENABLED=1', - 'datadog/agent-dev:master-py3', + 'registry.datadoghq.com/agent-dev:master-py3', ], shell=False, stdout=subprocess.PIPE, From 0bbf23e4d2abbc6113ceed4fb5c1efe9a4f0dff6 Mon Sep 17 00:00:00 2001 From: Victor Sprengel Date: Tue, 10 Mar 2026 13:46:02 +0100 Subject: [PATCH 7/8] chore: rename team ndm-core to network-device-monitoring-core (#22804) Co-authored-by: Claude Opus 4.6 --- .ddqa/config.toml | 4 ++-- .github/CODEOWNERS | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.ddqa/config.toml b/.ddqa/config.toml index 85eea44846d4d..489dca741880e 100644 --- a/.ddqa/config.toml +++ b/.ddqa/config.toml @@ -79,8 +79,8 @@ jira_statuses = [ "In Progress", "Done", ] -github_team = "ndm-core" -github_labels = ["team/ndm-core"] +github_team = "network-device-monitoring-core" +github_labels = ["team/network-device-monitoring-core"] [teams."Network Device Monitoring Integrations"] jira_project = "NDINT" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f52d84b2b320f..27cb547ad32aa 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -118,20 +118,20 @@ manifest.json @DataDog/documentation @DataDog/agent-integrations /cisco_sdwan/ @DataDog/ndm-integrations @DataDog/agent-integrations /cisco_sdwan/*.md @DataDog/ndm-integrations @DataDog/agent-integrations @DataDog/documentation /cisco_sdwan/manifest.json @DataDog/ndm-integrations @DataDog/agent-integrations @DataDog/documentation -/snmp/ @DataDog/ndm-core @DataDog/agent-integrations -/snmp/*.md @DataDog/ndm-core @DataDog/agent-integrations @DataDog/documentation -/snmp/manifest.json @DataDog/ndm-core @DataDog/agent-integrations @DataDog/documentation -/snmp_*/ @DataDog/ndm-core @DataDog/agent-integrations @DataDog/documentation -/snmp_*/*.md @DataDog/ndm-core @DataDog/agent-integrations @DataDog/documentation -/snmp_*/manifest.json @DataDog/ndm-core @DataDog/agent-integrations @DataDog/documentation +/snmp/ @DataDog/network-device-monitoring-core @DataDog/agent-integrations +/snmp/*.md @DataDog/network-device-monitoring-core @DataDog/agent-integrations @DataDog/documentation +/snmp/manifest.json @DataDog/network-device-monitoring-core @DataDog/agent-integrations @DataDog/documentation +/snmp_*/ @DataDog/network-device-monitoring-core @DataDog/agent-integrations @DataDog/documentation +/snmp_*/*.md @DataDog/network-device-monitoring-core @DataDog/agent-integrations @DataDog/documentation +/snmp_*/manifest.json @DataDog/network-device-monitoring-core @DataDog/agent-integrations @DataDog/documentation /network_path/ @DataDog/network-path @DataDog/Networks @DataDog/agent-integrations /network_path/*.md @DataDog/network-path @DataDog/Networks @DataDog/agent-integrations @DataDog/documentation /network_path/assets @DataDog/network-path @DataDog/Networks @DataDog/agent-integrations @DataDog/documentation /network_path/manifest.json @DataDog/network-path @DataDog/Networks @DataDog/agent-integrations @DataDog/documentation /versa/ @DataDog/ndm-integrations @DataDog/agent-integrations @DataDog/documentation -/datadog_checks_dev/datadog_checks/dev/tooling/commands/meta/snmp/ @DataDog/ndm-core @DataDog/agent-integrations -/docs/developer/tutorials/snmp/ @DataDog/ndm-core @DataDog/agent-integrations +/datadog_checks_dev/datadog_checks/dev/tooling/commands/meta/snmp/ @DataDog/network-device-monitoring-core @DataDog/agent-integrations +/docs/developer/tutorials/snmp/ @DataDog/network-device-monitoring-core @DataDog/agent-integrations # System checks /disk/ @DataDog/agent-integrations @DataDog/windows-products From ac25bd8ad1ef3127bc37e42c94ccb94cc6891a3b Mon Sep 17 00:00:00 2001 From: Juanpe Araque Date: Tue, 10 Mar 2026 15:10:23 +0100 Subject: [PATCH 8/8] Add dependency updates report to the dep updates command and improve dep update workflow (#22855) * Add dependency updates report to the dep updates command and improve dep update workflow * Add changelog * Update changelog since I used a previous PR number to generate it * Fix formatting * Updated the behavior of the report to get the report printed on screen if passed without a path --- .github/workflows/update-dependencies.yml | 39 ++++++- ddev/changelog.d/22855.added | 3 + ddev/src/ddev/cli/dep/updates.py | 89 +++++++++++++-- ddev/tests/cli/test_dep.py | 129 ++++++++++++++++++++++ 4 files changed, 246 insertions(+), 14 deletions(-) create mode 100644 ddev/changelog.d/22855.added diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index a10d06adb8d95..d34627f9f8faa 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -37,7 +37,13 @@ jobs: repositories: integrations-core - name: Update dependencies run: |- - ddev dep updates --sync + ddev dep updates --sync --report /tmp/dep-report.md --report-type markdown + - name: Read dependency report + id: dep-summary + run: |- + echo "summary<> "$GITHUB_OUTPUT" + cat /tmp/dep-report.md >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" - name: Update licenses run: |- ddev validate licenses --sync @@ -62,11 +68,11 @@ jobs: ### What does this PR do? Update the dependencies + ${{ steps.dep-summary.outputs.summary }} + This PR was automatically generated by the following workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - **THE CHANGELOG FILES OFTEN HAVE THE WRONG PR NUMBER. MAKE SURE TO CHECK THEM!** - ### Review checklist (to be filled by reviewers) - [ ] Feature or bugfix MUST have appropriate tests (unit, integration, e2e) @@ -79,3 +85,30 @@ jobs: base: master labels: bot,qa/skip-qa draft: false + - name: Fix changelog PR numbers + if: steps.cpr.outputs.pull-request-number != '' + env: + GITHUB_TOKEN: ${{ steps.token-generator.outputs.token }} + run: |- + actual_pr="${{ steps.cpr.outputs.pull-request-number }}" + branch="${{ steps.cpr.outputs.pull-request-branch }}" + + # Resolve the actual base branch from the PR (avoids hardcoding 'master') + base_branch=$(gh pr view "$actual_pr" --json baseRefName -q '.baseRefName') + + git fetch origin "$branch" "$base_branch" + git checkout "$branch" + + git diff "origin/$base_branch"...HEAD --name-only --diff-filter=A | grep 'changelog\.d/' | while read -r file; do + ext="${file##*.}" + dir=$(dirname "$file") + git mv "$file" "$dir/$actual_pr.$ext" 2>/dev/null || true + done + + git diff --cached --quiet || ( + git config user.email "github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git" + git commit -m "Fix changelog PR numbers" + git push origin "$branch" + ) diff --git a/ddev/changelog.d/22855.added b/ddev/changelog.d/22855.added new file mode 100644 index 0000000000000..ce0d60dee6160 --- /dev/null +++ b/ddev/changelog.d/22855.added @@ -0,0 +1,3 @@ +Added `--report` and `--report-type` options to `ddev dep updates`: + - Pass `--report PATH` to write a dependency update report to a file (JSON or Markdown via `--report-type`). + - Pass `--report` without a path to print the report as a Rich table directly in the terminal. diff --git a/ddev/src/ddev/cli/dep/updates.py b/ddev/src/ddev/cli/dep/updates.py index 371826b5da8d4..e47e6ac45c870 100644 --- a/ddev/src/ddev/cli/dep/updates.py +++ b/ddev/src/ddev/cli/dep/updates.py @@ -16,15 +16,31 @@ scrape_version_data, update_agent_dependencies, ) +from ddev.utils.fs import Path @click.command(short_help='Automatically check for dependency updates') @click.option('--sync', '-s', 'sync_dependencies', is_flag=True, help='Update the dependency definitions') @click.option('--include-security-deps', '-i', is_flag=True, help="Attempt to update security dependencies") @click.option('--batch-size', '-b', type=int, help='The maximum number of dependencies to upgrade if syncing') +@click.option( + '--report', + is_flag=False, + flag_value='', + default=None, + metavar='PATH', + help='Write a dependency update report to PATH, or omit PATH to print to screen.', +) +@click.option( + '--report-type', + type=click.Choice(['json', 'markdown']), + default='json', + show_default=True, + help='Format of the report file (only applies when a PATH is given).', +) @click.pass_context @click.pass_obj -def updates(app, ctx, sync_dependencies, include_security_deps, batch_size): +def updates(app, ctx, sync_dependencies, include_security_deps, batch_size, report, report_type): ignore_deps = set(app.repo.config.get('/overrides/dep/updates/exclude', [])) if not include_security_deps: @@ -45,6 +61,7 @@ def updates(app, ctx, sync_dependencies, include_security_deps, batch_size): new_dependencies = copy.deepcopy(dependencies) version_updates = defaultdict(lambda: defaultdict(set)) updated_packages = set() + report_entries: list[dict] = [] for name, python_versions in sorted(new_dependencies.items()): if name in ignore_deps: continue @@ -67,20 +84,70 @@ def updates(app, ctx, sync_dependencies, include_security_deps, batch_size): if dependency_definition != new_dependency_definition: version_updates[name][package_version].add(python_version) updated_packages.add(name) + if report is not None: + report_entries.append( + { + 'package': name, + 'old_version': str(Requirement(dependency_definition).specifier).lstrip('='), + 'new_version': str(package_version), + } + ) + + if report is None: + pass + elif report == '': + _print_table_report(app, report_entries) + elif report_type == 'json': + _write_json_report(report_entries, report) + else: + _write_markdown_report(report_entries, report) if sync_dependencies: if updated_packages: update_agent_dependencies(app.repo, new_dependencies) ctx.invoke(sync) app.display_info(f'Updated {len(updated_packages)} dependencies') + elif updated_packages: + app.display_error(f"{len(updated_packages)} dependencies are out of sync:") + for name, versions in version_updates.items(): + for package_version, python_versions in versions.items(): + app.display_error( + f'{name} can be updated to version {package_version} on {" and ".join(sorted(python_versions))}' + ) + app.abort() else: - if updated_packages: - app.display_error(f"{len(updated_packages)} dependencies are out of sync:") - for name, versions in version_updates.items(): - for package_version, python_versions in versions.items(): - app.display_error( - f'{name} can be updated to version {package_version} on {" and ".join(sorted(python_versions))}' - ) - app.abort() - else: - app.display_info('All dependencies are up to date') + app.display_info('All dependencies are up to date') + + +def _print_table_report(app, entries: list[dict]) -> None: + sorted_entries = sorted(entries, key=lambda e: e['package']) + if not sorted_entries: + app.display_info('No dependency version changes detected.') + return + columns = { + 'Package': {i: e['package'] for i, e in enumerate(sorted_entries)}, + 'Old Version': {i: e['old_version'] for i, e in enumerate(sorted_entries)}, + 'New Version': {i: e['new_version'] for i, e in enumerate(sorted_entries)}, + } + app.display_table('Dependency Bumps', columns, show_lines=True) + + +def _write_json_report(entries: list[dict], path: str) -> None: + import json + + Path(path).write_text(json.dumps(sorted(entries, key=lambda e: e['package']), indent=2)) + + +def _write_markdown_report(entries: list[dict], path: str) -> None: + if sorted_entries := sorted(entries, key=lambda e: e['package']): + lines = [ + '### Dependency Bumps', + '', + '| Package | Old Version | New Version |', + '|---------|-------------|-------------|', + ] + lines.extend(f"| {e['package']} | {e['old_version']} | {e['new_version']} |" for e in sorted_entries) + content = '\n'.join(lines) + else: + content = '_No dependency version changes detected._' + Path(path).write_text(content) diff --git a/ddev/tests/cli/test_dep.py b/ddev/tests/cli/test_dep.py index 895b258600c0d..552929898dd6f 100644 --- a/ddev/tests/cli/test_dep.py +++ b/ddev/tests/cli/test_dep.py @@ -254,6 +254,135 @@ def test_batch_size(self, ddev): assert result.exit_code != 0 +def test_report_json(ddev, fake_repo, mock_async_http_get_json, tmp_path): + create_integration(fake_repo, 'foo', ['dep-a==1.0.0', 'dep-b==3.1.4']) + create_integration(fake_repo, 'datadog_checks_base', ['dep-a==1.0.0', 'dep-b==3.1.4']) + create_integration(fake_repo, 'datadog_checks_downloader', ['dep-a==1.0.0', 'dep-b==3.1.4']) + (fake_repo / 'agent_requirements.in').write_text('dep-a==1.0.0\ndep-b==3.1.4') + + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-a/json', + { + 'info': {'name': 'dep-a'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['1.0.0', '1.2.3']}, + }, + ) + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-b/json', + { + 'info': {'name': 'dep-b'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['3.1.0', '3.1.4']}, + }, + ) + + report_path = tmp_path / 'report.json' + result = ddev('dep', 'updates', '--sync', '--report', str(report_path), '--report-type', 'json') + + assert result.exit_code == 0 + data = json.loads(report_path.read_text()) + assert len(data) == 1 + assert data[0]['package'] == 'dep-a' + assert data[0]['old_version'] == '1.0.0' + assert data[0]['new_version'] == '1.2.3' + + +def test_report_markdown(ddev, fake_repo, mock_async_http_get_json, tmp_path): + create_integration(fake_repo, 'foo', ['dep-a==1.0.0', 'dep-b==3.1.4']) + create_integration(fake_repo, 'datadog_checks_base', ['dep-a==1.0.0', 'dep-b==3.1.4']) + create_integration(fake_repo, 'datadog_checks_downloader', ['dep-a==1.0.0', 'dep-b==3.1.4']) + (fake_repo / 'agent_requirements.in').write_text('dep-a==1.0.0\ndep-b==3.1.4') + + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-a/json', + { + 'info': {'name': 'dep-a'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['1.0.0', '1.2.3']}, + }, + ) + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-b/json', + { + 'info': {'name': 'dep-b'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['3.1.0', '3.1.4']}, + }, + ) + + report_path = tmp_path / 'report.md' + result = ddev('dep', 'updates', '--sync', '--report', str(report_path), '--report-type', 'markdown') + + assert result.exit_code == 0 + content = report_path.read_text() + assert '### Dependency Bumps' in content + assert '| Package | Old Version | New Version |' in content + assert '| dep-a | 1.0.0 | 1.2.3 |' in content + + +def test_report_screen(ddev, fake_repo, mock_async_http_get_json): + create_integration(fake_repo, 'foo', ['dep-a==1.0.0', 'dep-b==3.1.4']) + create_integration(fake_repo, 'datadog_checks_base', ['dep-a==1.0.0', 'dep-b==3.1.4']) + create_integration(fake_repo, 'datadog_checks_downloader', ['dep-a==1.0.0', 'dep-b==3.1.4']) + (fake_repo / 'agent_requirements.in').write_text('dep-a==1.0.0\ndep-b==3.1.4') + + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-a/json', + { + 'info': {'name': 'dep-a'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['1.0.0', '1.2.3']}, + }, + ) + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-b/json', + { + 'info': {'name': 'dep-b'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['3.1.0', '3.1.4']}, + }, + ) + + result = ddev('dep', 'updates', '--sync', '--report') + + assert result.exit_code == 0 + assert 'dep-a' in result.output + assert '1.0.0' in result.output + assert '1.2.3' in result.output + + +def test_report_screen_no_updates(ddev, fake_repo, mock_async_http_get_json): + create_integration(fake_repo, 'foo', ['dep-a==1.2.3']) + (fake_repo / 'agent_requirements.in').write_text('dep-a==1.2.3') + + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-a/json', + { + 'info': {'name': 'dep-a'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['1.0.0', '1.2.3']}, + }, + ) + + result = ddev('dep', 'updates', '--sync', '--report') + + assert result.exit_code == 0 + assert 'No dependency version changes detected.' in result.output + + +def test_report_no_updates(ddev, fake_repo, mock_async_http_get_json, tmp_path): + create_integration(fake_repo, 'foo', ['dep-a==1.2.3']) + (fake_repo / 'agent_requirements.in').write_text('dep-a==1.2.3') + + mock_async_http_get_json( + 'https://pypi.org/pypi/dep-a/json', + { + 'info': {'name': 'dep-a'}, + 'releases': {v: [{'python_version': 'py2.py3', 'requires_python': '>=2.7'}] for v in ['1.0.0', '1.2.3']}, + }, + ) + + report_path = tmp_path / 'report.md' + result = ddev('dep', 'updates', '--sync', '--report', str(report_path), '--report-type', 'markdown') + + assert result.exit_code == 0 + assert report_path.read_text() == '_No dependency version changes detected._' + + @pytest.fixture def mock_async_http_get_json(): """Mock `get` responses assuming a JSON value is returned in the body.