From 07c306e9d0931480f990d3710fce6ef3f9af02ad Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Tue, 2 Jun 2026 16:11:53 -0400 Subject: [PATCH 1/8] ci: add weekly workflow to notify when datadogpy has a new release Adds a scheduled GitHub Actions workflow (runs every Monday + on demand) that compares the vendored datadogpy version in ddtrace/vendor/__init__.py against the latest release on PyPI. When the two differ the workflow opens (or updates) a GitHub issue labelled `vendor-bump` describing the gap and linking to the changelog, so the team knows to evaluate whether a vendor bump is warranted. Also adds .github/scripts/check_datadogpy_vendor.py which can be run locally for the same check without needing GitHub Actions. --- .github/scripts/check_datadogpy_vendor.py | 90 ++++++++++++++++++++ .github/workflows/check-vendor-datadogpy.yml | 77 +++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 .github/scripts/check_datadogpy_vendor.py create mode 100644 .github/workflows/check-vendor-datadogpy.yml diff --git a/.github/scripts/check_datadogpy_vendor.py b/.github/scripts/check_datadogpy_vendor.py new file mode 100644 index 00000000000..54afb354c3d --- /dev/null +++ b/.github/scripts/check_datadogpy_vendor.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +"""Compare the vendored datadogpy version with the latest release on PyPI. + +Outputs GitHub Actions step outputs: + outdated - "true" if PyPI is ahead of the vendored version, "false" otherwise + latest_version - latest version string from PyPI + vendored_version - version string parsed from ddtrace/vendor/__init__.py + +Exit codes: + 0 - success (regardless of whether outdated) + 1 - unexpected error (e.g. PyPI unreachable, version not parseable) +""" + +from __future__ import annotations + +import json +import os +from pathlib import Path +import re +import sys +import urllib.error +import urllib.request + + +PYPI_URL = "https://pypi.org/pypi/datadog/json" +VENDOR_INIT = Path(__file__).parent.parent.parent / "ddtrace" / "vendor" / "__init__.py" + + +def _set_output(name: str, value: str) -> None: + """Write a GitHub Actions step output.""" + github_output = os.environ.get("GITHUB_OUTPUT") + if github_output: + with open(github_output, "a") as fh: + fh.write(f"{name}={value}\n") + else: + # Running locally — just print + print(f" {name}={value}") + + +def _latest_pypi_version() -> str: + try: + req = urllib.request.Request(PYPI_URL) + with urllib.request.urlopen(req, timeout=10) as resp: # nosec B310 + data: dict[str, dict[str, str]] = json.load(resp) + version: str = data["info"]["version"] + return version + except (urllib.error.URLError, KeyError, json.JSONDecodeError) as exc: + print(f"ERROR: could not fetch latest datadogpy version from PyPI: {exc}", file=sys.stderr) + sys.exit(1) + + +def _vendored_version() -> str: + try: + content = VENDOR_INIT.read_text() + except FileNotFoundError: + print(f"ERROR: {VENDOR_INIT} not found", file=sys.stderr) + sys.exit(1) + + # Match the "Version: X.Y.Z" line inside the dogstatsd section + match = re.search( + r"dogstatsd\b.*?Version:\s*(\d+\.\d+(?:\.\d+)?)", + content, + re.DOTALL | re.IGNORECASE, + ) + if not match: + print(f"ERROR: could not parse vendored datadogpy version from {VENDOR_INIT}", file=sys.stderr) + sys.exit(1) + return match.group(1) + + +def main() -> None: + latest = _latest_pypi_version() + vendored = _vendored_version() + + print(f"Vendored datadogpy version : {vendored}") + print(f"Latest PyPI version : {latest}") + + outdated = latest != vendored + if outdated: + print("⚠ Vendored version is behind PyPI — consider a vendor bump.") + else: + print("✓ Vendored version is up to date.") + + _set_output("outdated", str(outdated).lower()) + _set_output("latest_version", latest) + _set_output("vendored_version", vendored) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/check-vendor-datadogpy.yml b/.github/workflows/check-vendor-datadogpy.yml new file mode 100644 index 00000000000..6564949d401 --- /dev/null +++ b/.github/workflows/check-vendor-datadogpy.yml @@ -0,0 +1,77 @@ +name: Check vendored datadogpy version + +# Runs weekly and on demand. Opens (or updates) a GitHub issue when the +# latest `datadog` release on PyPI is ahead of the version pinned in +# ddtrace/vendor/__init__.py, so the team knows to evaluate a vendor bump. + +on: + schedule: + # Every Monday at 09:00 UTC + - cron: "0 9 * * 1" + workflow_dispatch: + +permissions: + contents: read + issues: write + +jobs: + check: + name: Compare vendored vs PyPI version + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check datadogpy vendor version + id: check + run: python .github/scripts/check_datadogpy_vendor.py + + - name: Open or update tracking issue + if: steps.check.outputs.outdated == 'true' + uses: actions/github-script@v7 + with: + script: | + const title = `chore(vendor): bump vendored datadogpy to ${process.env.LATEST_VERSION}`; + const body = [ + `The \`datadog\` package on PyPI has a new release: **${process.env.LATEST_VERSION}**`, + `The version currently vendored in \`ddtrace/vendor/\` is **${process.env.VENDORED_VERSION}**.`, + ``, + `## Next steps`, + `1. Review the [datadogpy changelog](https://github.com/DataDog/datadogpy/blob/master/CHANGELOG.md) for changes in \`datadog/dogstatsd/container.py\` and related files.`, + `2. If there are relevant fixes or improvements, update the vendor copy following the instructions in \`ddtrace/vendor/__init__.py\`.`, + `3. Re-apply any local patches documented in \`ddtrace/vendor/__init__.py\` under the \`dogstatsd\` section.`, + `4. Close this issue once the vendor bump lands.`, + ``, + `_This issue was opened automatically by the [check-vendor-datadogpy](${{ github.server_url }}/${{ github.repository }}/actions/workflows/check-vendor-datadogpy.yml) workflow._`, + ].join('\n'); + + // Check if a tracking issue already exists (avoid duplicates) + const existing = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'vendor-bump', + }); + + const alreadyOpen = existing.data.find(i => i.title.includes('datadogpy')); + if (alreadyOpen) { + console.log(`Issue #${alreadyOpen.number} already open — updating body`); + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: alreadyOpen.number, + title, + body, + }); + } else { + const created = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + labels: ['vendor-bump'], + }); + console.log(`Opened issue #${created.data.number}`); + } + env: + LATEST_VERSION: ${{ steps.check.outputs.latest_version }} + VENDORED_VERSION: ${{ steps.check.outputs.vendored_version }} From 1a01b674bbc622e4b700ce0783dbeeb490879fb5 Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Tue, 2 Jun 2026 16:22:45 -0400 Subject: [PATCH 2/8] chore: fix docstring, type-annotate local vars, scope version regex to dogstatsd section --- .github/scripts/check_datadogpy_vendor.py | 63 +++++++++++++++-------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/.github/scripts/check_datadogpy_vendor.py b/.github/scripts/check_datadogpy_vendor.py index 54afb354c3d..b222e0f7c3f 100644 --- a/.github/scripts/check_datadogpy_vendor.py +++ b/.github/scripts/check_datadogpy_vendor.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 """Compare the vendored datadogpy version with the latest release on PyPI. -Outputs GitHub Actions step outputs: - outdated - "true" if PyPI is ahead of the vendored version, "false" otherwise - latest_version - latest version string from PyPI - vendored_version - version string parsed from ddtrace/vendor/__init__.py +Values written to ``$GITHUB_OUTPUT`` (GitHub Actions inter-step data): + outdated - ``"true"`` when PyPI is ahead of the vendored pin, ``"false"`` otherwise + latest_version - latest version string fetched from PyPI (e.g. ``"0.53.0"``) + vendored_version - version string parsed from ``ddtrace/vendor/__init__.py`` (e.g. ``"0.52.1"``) Exit codes: - 0 - success (regardless of whether outdated) - 1 - unexpected error (e.g. PyPI unreachable, version not parseable) + 0 - completed successfully (regardless of whether the vendored copy is outdated) + 1 - unexpected error (e.g. PyPI unreachable, version string not parseable) """ from __future__ import annotations @@ -22,24 +22,27 @@ import urllib.request -PYPI_URL = "https://pypi.org/pypi/datadog/json" -VENDOR_INIT = Path(__file__).parent.parent.parent / "ddtrace" / "vendor" / "__init__.py" +PYPI_URL: str = "https://pypi.org/pypi/datadog/json" +VENDOR_INIT: Path = Path(__file__).parent.parent.parent / "ddtrace" / "vendor" / "__init__.py" def _set_output(name: str, value: str) -> None: - """Write a GitHub Actions step output.""" - github_output = os.environ.get("GITHUB_OUTPUT") + """Append ``name=value`` to the GitHub Actions step-output file. + + When run locally (``$GITHUB_OUTPUT`` is unset) the value is printed to + stdout instead so the output is still visible. + """ + github_output: str | None = os.environ.get("GITHUB_OUTPUT") if github_output: with open(github_output, "a") as fh: fh.write(f"{name}={value}\n") else: - # Running locally — just print print(f" {name}={value}") def _latest_pypi_version() -> str: try: - req = urllib.request.Request(PYPI_URL) + req: urllib.request.Request = urllib.request.Request(PYPI_URL) with urllib.request.urlopen(req, timeout=10) as resp: # nosec B310 data: dict[str, dict[str, str]] = json.load(resp) version: str = data["info"]["version"] @@ -51,31 +54,47 @@ def _latest_pypi_version() -> str: def _vendored_version() -> str: try: - content = VENDOR_INIT.read_text() + content: str = VENDOR_INIT.read_text() except FileNotFoundError: print(f"ERROR: {VENDOR_INIT} not found", file=sys.stderr) sys.exit(1) - # Match the "Version: X.Y.Z" line inside the dogstatsd section - match = re.search( - r"dogstatsd\b.*?Version:\s*(\d+\.\d+(?:\.\d+)?)", + # Extract just the dogstatsd section (from its header up to the next package header + # or end of file) so we don't accidentally pick up a Version: line from another + # vendored package. Each section starts with "\n---+\n"; the lookahead + # matches that two-line opener to stop before the next section begins. + section_match: re.Match[str] | None = re.search( + r"^dogstatsd\n-+\n(.*?)(?=\n\w[^\n]*\n-+\n|\Z)", content, - re.DOTALL | re.IGNORECASE, + re.DOTALL | re.MULTILINE, + ) + if not section_match: + print(f"ERROR: dogstatsd section not found in {VENDOR_INIT}", file=sys.stderr) + sys.exit(1) + + section: str = section_match.group(1) + + # Accept both formats: + # "Version: 0.52.1" (clean semver, used after the vendor bump) + # "Version: 8e11af2 (0.39.1)" (git-hash + semver in parens, used before) + version_match: re.Match[str] | None = re.search( + r"Version:.*?(\d+\.\d+\.\d+)", + section, ) - if not match: + if not version_match: print(f"ERROR: could not parse vendored datadogpy version from {VENDOR_INIT}", file=sys.stderr) sys.exit(1) - return match.group(1) + return version_match.group(1) def main() -> None: - latest = _latest_pypi_version() - vendored = _vendored_version() + latest: str = _latest_pypi_version() + vendored: str = _vendored_version() print(f"Vendored datadogpy version : {vendored}") print(f"Latest PyPI version : {latest}") - outdated = latest != vendored + outdated: bool = latest != vendored if outdated: print("⚠ Vendored version is behind PyPI — consider a vendor bump.") else: From 4da6b97d70007143796e73568ff99da7e992deb4 Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Tue, 2 Jun 2026 16:25:08 -0400 Subject: [PATCH 3/8] =?UTF-8?q?ci:=20address=20bot=20review=20=E2=80=94=20?= =?UTF-8?q?semver=20comparison,=20fork=20guard,=20pin=20action=20SHAs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/scripts/check_datadogpy_vendor.py | 11 +++++++++-- .github/workflows/check-vendor-datadogpy.yml | 6 ++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/scripts/check_datadogpy_vendor.py b/.github/scripts/check_datadogpy_vendor.py index b222e0f7c3f..29a6e937380 100644 --- a/.github/scripts/check_datadogpy_vendor.py +++ b/.github/scripts/check_datadogpy_vendor.py @@ -2,7 +2,7 @@ """Compare the vendored datadogpy version with the latest release on PyPI. Values written to ``$GITHUB_OUTPUT`` (GitHub Actions inter-step data): - outdated - ``"true"`` when PyPI is ahead of the vendored pin, ``"false"`` otherwise + outdated - ``"true"`` when the PyPI release is strictly newer than the vendored pin, ``"false"`` otherwise latest_version - latest version string fetched from PyPI (e.g. ``"0.53.0"``) vendored_version - version string parsed from ``ddtrace/vendor/__init__.py`` (e.g. ``"0.52.1"``) @@ -87,6 +87,11 @@ def _vendored_version() -> str: return version_match.group(1) +def _version_tuple(v: str) -> tuple[int, ...]: + """Convert a ``"X.Y.Z"`` version string to a comparable integer tuple.""" + return tuple(int(part) for part in v.split(".")) + + def main() -> None: latest: str = _latest_pypi_version() vendored: str = _vendored_version() @@ -94,7 +99,9 @@ def main() -> None: print(f"Vendored datadogpy version : {vendored}") print(f"Latest PyPI version : {latest}") - outdated: bool = latest != vendored + # Flag only when PyPI is strictly ahead; if vendored == latest or vendored + # is somehow newer (e.g. a pre-release pin) we consider ourselves up to date. + outdated: bool = _version_tuple(latest) > _version_tuple(vendored) if outdated: print("⚠ Vendored version is behind PyPI — consider a vendor bump.") else: diff --git a/.github/workflows/check-vendor-datadogpy.yml b/.github/workflows/check-vendor-datadogpy.yml index 6564949d401..fa417cfa05d 100644 --- a/.github/workflows/check-vendor-datadogpy.yml +++ b/.github/workflows/check-vendor-datadogpy.yml @@ -16,10 +16,12 @@ permissions: jobs: check: + # Skip scheduled runs on forks to avoid unintended automation. + if: github.event_name != 'schedule' || github.event.repository.fork == false name: Compare vendored vs PyPI version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check datadogpy vendor version id: check @@ -27,7 +29,7 @@ jobs: - name: Open or update tracking issue if: steps.check.outputs.outdated == 'true' - uses: actions/github-script@v7 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | const title = `chore(vendor): bump vendored datadogpy to ${process.env.LATEST_VERSION}`; From b06c7ed857f73c0cec68d52e75cd8f79b16d290a Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Tue, 2 Jun 2026 16:30:37 -0400 Subject: [PATCH 4/8] ci: handle PEP 440 pre-release versions in _version_tuple, disable credential persistence on checkout --- .github/scripts/check_datadogpy_vendor.py | 21 ++++++++++++++++++-- .github/workflows/check-vendor-datadogpy.yml | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/scripts/check_datadogpy_vendor.py b/.github/scripts/check_datadogpy_vendor.py index 29a6e937380..ca83d5bf1b7 100644 --- a/.github/scripts/check_datadogpy_vendor.py +++ b/.github/scripts/check_datadogpy_vendor.py @@ -88,8 +88,25 @@ def _vendored_version() -> str: def _version_tuple(v: str) -> tuple[int, ...]: - """Convert a ``"X.Y.Z"`` version string to a comparable integer tuple.""" - return tuple(int(part) for part in v.split(".")) + """Convert a version string to a comparable tuple of ints. + + Handles plain ``"X.Y.Z"`` and defensively skips PEP 440 pre-release or + post-release segments so the comparison never raises ``ValueError``:: + + "0.53.0" → (0, 53, 0) + "0.53.0rc1" → (0, 53, 0) # rc treated as the base release + "0.44.1.dev0" → (0, 44, 1) # dev segment dropped + "0.53.0.post1" → (0, 53, 0) # post segment dropped + """ + parts: list[int] = [] + for segment in v.split("."): + numeric: re.Match[str] | None = re.match(r"(\d+)", segment) + if numeric: + parts.append(int(numeric.group(1))) + if not parts: + print(f"ERROR: cannot parse version string {v!r}", file=sys.stderr) + sys.exit(1) + return tuple(parts) def main() -> None: diff --git a/.github/workflows/check-vendor-datadogpy.yml b/.github/workflows/check-vendor-datadogpy.yml index fa417cfa05d..7d57911a2c8 100644 --- a/.github/workflows/check-vendor-datadogpy.yml +++ b/.github/workflows/check-vendor-datadogpy.yml @@ -22,6 +22,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Check datadogpy vendor version id: check From 0b058f2b2b0193a7922acb6f850504ddefed36cf Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Tue, 2 Jun 2026 16:37:49 -0400 Subject: [PATCH 5/8] ci: cc @DataDog/python-guild in vendor-bump issue body --- .github/workflows/check-vendor-datadogpy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/check-vendor-datadogpy.yml b/.github/workflows/check-vendor-datadogpy.yml index 7d57911a2c8..bd3682d1c72 100644 --- a/.github/workflows/check-vendor-datadogpy.yml +++ b/.github/workflows/check-vendor-datadogpy.yml @@ -39,6 +39,8 @@ jobs: `The \`datadog\` package on PyPI has a new release: **${process.env.LATEST_VERSION}**`, `The version currently vendored in \`ddtrace/vendor/\` is **${process.env.VENDORED_VERSION}**.`, ``, + `cc @DataDog/python-guild`, + ``, `## Next steps`, `1. Review the [datadogpy changelog](https://github.com/DataDog/datadogpy/blob/master/CHANGELOG.md) for changes in \`datadog/dogstatsd/container.py\` and related files.`, `2. If there are relevant fixes or improvements, update the vendor copy following the instructions in \`ddtrace/vendor/__init__.py\`.`, From 26a8be832b83a76d336120aebcfd240335cc724e Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Tue, 2 Jun 2026 16:49:05 -0400 Subject: [PATCH 6/8] ci: use packaging.version.Version for correct PEP 440 ordering --- .github/scripts/check_datadogpy_vendor.py | 35 +++++++++++------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/.github/scripts/check_datadogpy_vendor.py b/.github/scripts/check_datadogpy_vendor.py index ca83d5bf1b7..ec0ac81f331 100644 --- a/.github/scripts/check_datadogpy_vendor.py +++ b/.github/scripts/check_datadogpy_vendor.py @@ -21,6 +21,9 @@ import urllib.error import urllib.request +from packaging.version import InvalidVersion +from packaging.version import Version + PYPI_URL: str = "https://pypi.org/pypi/datadog/json" VENDOR_INIT: Path = Path(__file__).parent.parent.parent / "ddtrace" / "vendor" / "__init__.py" @@ -87,26 +90,22 @@ def _vendored_version() -> str: return version_match.group(1) -def _version_tuple(v: str) -> tuple[int, ...]: - """Convert a version string to a comparable tuple of ints. +def _is_outdated(vendored: str, latest: str) -> bool: + """Return True when the PyPI release is strictly newer than the vendored pin. - Handles plain ``"X.Y.Z"`` and defensively skips PEP 440 pre-release or - post-release segments so the comparison never raises ``ValueError``:: + Uses ``packaging.version.Version`` for correct PEP 440 ordering so that + post-releases, pre-releases, and dev releases all compare properly:: - "0.53.0" → (0, 53, 0) - "0.53.0rc1" → (0, 53, 0) # rc treated as the base release - "0.44.1.dev0" → (0, 44, 1) # dev segment dropped - "0.53.0.post1" → (0, 53, 0) # post segment dropped + "0.53.0.post1" > "0.53.0" → True (post-release is newer) + "0.53.0rc1" < "0.53.0" → False (pre-release is older) + "0.44.1.dev0" < "0.44.1" → False (dev release is older) + "0.53.0" == "0.53.0" → False (same) """ - parts: list[int] = [] - for segment in v.split("."): - numeric: re.Match[str] | None = re.match(r"(\d+)", segment) - if numeric: - parts.append(int(numeric.group(1))) - if not parts: - print(f"ERROR: cannot parse version string {v!r}", file=sys.stderr) + try: + return Version(latest) > Version(vendored) + except InvalidVersion as exc: + print(f"ERROR: cannot compare versions {vendored!r} and {latest!r}: {exc}", file=sys.stderr) sys.exit(1) - return tuple(parts) def main() -> None: @@ -116,9 +115,7 @@ def main() -> None: print(f"Vendored datadogpy version : {vendored}") print(f"Latest PyPI version : {latest}") - # Flag only when PyPI is strictly ahead; if vendored == latest or vendored - # is somehow newer (e.g. a pre-release pin) we consider ourselves up to date. - outdated: bool = _version_tuple(latest) > _version_tuple(vendored) + outdated: bool = _is_outdated(vendored, latest) if outdated: print("⚠ Vendored version is behind PyPI — consider a vendor bump.") else: From 7d769f757af23e98eab7526af8a56d534b74dae2 Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Tue, 2 Jun 2026 16:56:44 -0400 Subject: [PATCH 7/8] ci: use vendored packaging, preserve PEP 440 suffix in version regex, pin Python 3.12 --- .github/scripts/check_datadogpy_vendor.py | 21 ++++++++++++++------ .github/workflows/check-vendor-datadogpy.yml | 4 ++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.github/scripts/check_datadogpy_vendor.py b/.github/scripts/check_datadogpy_vendor.py index ec0ac81f331..ab68cabf10c 100644 --- a/.github/scripts/check_datadogpy_vendor.py +++ b/.github/scripts/check_datadogpy_vendor.py @@ -21,8 +21,14 @@ import urllib.error import urllib.request -from packaging.version import InvalidVersion -from packaging.version import Version + +# Use the copy of `packaging` that is already vendored in this repository so +# the workflow step works without a separate `pip install` and the dependency +# version is pinned alongside the rest of the codebase. +sys.path.insert(0, str(Path(__file__).parent.parent.parent / "ddtrace" / "vendor")) + +from packaging.version import InvalidVersion # noqa: E402 +from packaging.version import Version # noqa: E402 PYPI_URL: str = "https://pypi.org/pypi/datadog/json" @@ -77,11 +83,14 @@ def _vendored_version() -> str: section: str = section_match.group(1) - # Accept both formats: - # "Version: 0.52.1" (clean semver, used after the vendor bump) - # "Version: 8e11af2 (0.39.1)" (git-hash + semver in parens, used before) + # Accept both formats, preserving any PEP 440 suffix (rc, post, dev, …): + # "Version: 0.52.1" (clean release after the vendor bump) + # "Version: 0.52.1rc1" (hypothetical pre-release pin) + # "Version: 8e11af2 (0.39.1)" (git-hash + version in parens, legacy) + # The character class [^\s)] stops at whitespace or a closing paren so the + # parenthesised form is handled without a separate branch. version_match: re.Match[str] | None = re.search( - r"Version:.*?(\d+\.\d+\.\d+)", + r"Version:.*?(\d+\.\d+\.\d+[^\s)]*)", section, ) if not version_match: diff --git a/.github/workflows/check-vendor-datadogpy.yml b/.github/workflows/check-vendor-datadogpy.yml index bd3682d1c72..62dc695c341 100644 --- a/.github/workflows/check-vendor-datadogpy.yml +++ b/.github/workflows/check-vendor-datadogpy.yml @@ -25,6 +25,10 @@ jobs: with: persist-credentials: false + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.12" + - name: Check datadogpy vendor version id: check run: python .github/scripts/check_datadogpy_vendor.py From 2440d98cf492ef450adbdd35a95ce3b46e9eec43 Mon Sep 17 00:00:00 2001 From: Vlad Scherbich Date: Wed, 3 Jun 2026 11:18:28 -0400 Subject: [PATCH 8/8] ci: broaden issue template to cover all dogstatsd files, not just container.py --- .github/workflows/check-vendor-datadogpy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-vendor-datadogpy.yml b/.github/workflows/check-vendor-datadogpy.yml index 62dc695c341..fdce002c29e 100644 --- a/.github/workflows/check-vendor-datadogpy.yml +++ b/.github/workflows/check-vendor-datadogpy.yml @@ -46,8 +46,8 @@ jobs: `cc @DataDog/python-guild`, ``, `## Next steps`, - `1. Review the [datadogpy changelog](https://github.com/DataDog/datadogpy/blob/master/CHANGELOG.md) for changes in \`datadog/dogstatsd/container.py\` and related files.`, - `2. If there are relevant fixes or improvements, update the vendor copy following the instructions in \`ddtrace/vendor/__init__.py\`.`, + `1. Review the [datadogpy changelog](https://github.com/DataDog/datadogpy/blob/master/CHANGELOG.md) for changes across the \`datadog/dogstatsd/\` module (any file, not just \`container.py\`).`, + `2. Update the vendored copy of all changed files following the instructions in \`ddtrace/vendor/__init__.py\`.`, `3. Re-apply any local patches documented in \`ddtrace/vendor/__init__.py\` under the \`dogstatsd\` section.`, `4. Close this issue once the vendor bump lands.`, ``,