Skip to content

Commit 7e78fe5

Browse files
chore: use static versions instead of setuptools-scm (#15245)
## Description APMLP-587 Remove `setuptools-scm` and rely on statically defined versions in `pyproject.toml` and `ddtrace/version.py`. A lot of the changes are moving components away from using `ddtrace.version.get_version()` to compute the version vs using the statically defined `ddtrace.__version__`/`ddtrace.version.__version__` ## Testing <!-- Describe your testing strategy or note what tests are included --> ## Risks <!-- Note any risks associated with this change, or "None" if no risks --> ## Additional Notes We are dropping the version specific public s3 folders. This is because the static versions mean we are likely to easily overwrite the contents of a bucket on PRs/feature branches/new runs on main or release branches/etc. Removing them and only relying on the pipeline id is the safest way to not have any conflicts between versions and files uploaded. This PR also adds a helper script `scripts/verify-package-version`: ``` Verify and update static versions in pyproject.toml and ddtrace/version.py. Performs the following validations: - Ensures version in pyproject.toml is PEP 440 compliant (e.g., "4.1.0.dev0" not "4.1.0.dev") - Verifies __version__ in ddtrace/version.py matches __version_tuple__ when parsed - Checks that versions in both files are consistent Usage: scripts/verify-package-version # Check versions match (exit 0 if OK, 1 if mismatch) scripts/verify-package-version --fix # Update version.py from pyproject.toml ``` --------- Co-authored-by: Christophe Papazian <114495376+christophe-papazian@users.noreply.github.com>
1 parent a82e9b1 commit 7e78fe5

File tree

42 files changed

+605
-183
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+605
-183
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,6 @@ CLAUDE.local.md
152152
.riot/venv*
153153
.riot/requirements/*.in
154154

155-
# Auto-generated version file
156-
ddtrace/_version.py
157-
158155
# Benchmarks
159156
artifacts/
160157

.gitlab/package.yml

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,3 @@
1-
compute_library_version:
2-
image: registry.ddbuild.io/images/dd-octo-sts-ci-base:2025.06-1
3-
tags: [ "arch:amd64" ]
4-
stage: package
5-
id_tokens:
6-
DDOCTOSTS_ID_TOKEN:
7-
aud: dd-octo-sts
8-
script: |
9-
set -eo pipefail
10-
11-
if [ -z ${GH_TOKEN} ]
12-
then
13-
# Use dd-octo-sts to get GitHub token
14-
dd-octo-sts token --scope DataDog/dd-trace-py --policy gitlab.github-access.read > token
15-
gh auth login --with-token < token
16-
rm token
17-
fi
18-
# Prevent git operation errors:
19-
# failed to determine base repo: failed to run git: fatal: detected dubious ownership in repository at ...
20-
git config --global --add safe.directory "${CI_PROJECT_DIR}"
21-
.gitlab/download-library-version-from-gh-actions.sh
22-
23-
echo "SETUPTOOLS_SCM_PRETEND_VERSION_FOR_DDTRACE=$(cat library-version/version.txt)" | tee library_version.env
24-
echo "DDTRACE_VERSION=$(cat library-version/version.txt)" | tee -a library_version.env
25-
artifacts:
26-
reports:
27-
dotenv: library_version.env
28-
paths:
29-
- "library-version/version.txt"
30-
311
download_ddtrace_artifacts:
322
image: registry.ddbuild.io/images/dd-octo-sts-ci-base:2025.06-1
333
tags: [ "arch:amd64" ]
@@ -90,8 +60,6 @@ publish-wheels-to-s3:
9060
needs:
9161
- job: download_ddtrace_artifacts
9262
artifacts: true
93-
- job: compute_library_version
94-
artifacts: true
9563
variables:
9664
BUCKET: dd-trace-py-builds
9765
script:
@@ -107,24 +75,20 @@ publish-wheels-to-s3:
10775
- printf ' - %s\n' "${WHEELS[@]}"
10876

10977
- |
110-
if [ -f library-version/version.txt ]; then
111-
VERSION="$(tr -d '\r\n' < library-version/version.txt)"
112-
fi
78+
VERSION=$(grep '^version = ' pyproject.toml | head -1 | sed -E 's/version = "(.+)"/\1/')
11379
11480
if [ -z "${VERSION:-}" ]; then
115-
echo "ERROR: VERSION is not defined or library-version/version.txt missing!"
81+
echo "ERROR: VERSION is not defined in pyproject.toml!"
11682
exit 1
11783
fi
11884
11985
- printf 'Detected version %s\n' ${VERSION}
12086

121-
# Upload all wheels to versioned prefix and pipeline-id prefix
122-
- aws s3 cp --recursive --exclude "*" --include "*.whl" pywheels "s3://${BUCKET}/${VERSION}/"
87+
# Upload all wheels to pipeline-id prefix
12388
- aws s3 cp --recursive --exclude "*" --include "*.whl" pywheels "s3://${BUCKET}/${CI_PIPELINE_ID}/"
12489

12590
- |
12691
VERSION_ENC="${VERSION//+/%2B}"
127-
S3_BASE_VER="https://${BUCKET}.s3.amazonaws.com/${VERSION_ENC}"
12892
S3_BASE_PIPE="https://${BUCKET}.s3.amazonaws.com/${CI_PIPELINE_ID}"
12993
13094
generate_index_html() {
@@ -141,15 +105,27 @@ publish-wheels-to-s3:
141105
}
142106
143107
# Generate both minimal indexes
144-
generate_index_html "index.version.html"
145108
generate_index_html "index.pipeline.html"
146109
147110
# Upload to each S3 prefix
148-
aws s3 cp "index.version.html" "s3://${BUCKET}/${VERSION}/index.html" --content-type text/html
149111
aws s3 cp "index.pipeline.html" "s3://${BUCKET}/${CI_PIPELINE_ID}/index.html" --content-type text/html
150112
151113
# Print the clickable URLs
152-
VER_INDEX_URL="${S3_BASE_VER}/index.html"
153114
PIPE_INDEX_URL="${S3_BASE_PIPE}/index.html"
154-
echo "S3 index (version): ${VER_INDEX_URL}"
155115
echo "S3 index (pipeline): ${PIPE_INDEX_URL}"
116+
117+
118+
# Fail if the downloaded package versions do not match the git tag version
119+
verify_package_version:
120+
image: registry.ddbuild.io/images/mirror/python:3.14.0
121+
tags: [ "arch:amd64" ]
122+
stage: package
123+
needs: [ download_ddtrace_artifacts ]
124+
only:
125+
# v2.10.0
126+
# v2.10.1
127+
# v2.10.0rc0
128+
# v2.10.0rc5
129+
- /^v[0-9]+\.[0-9]+\.[0-9]+(rc[0-9]+)?$/
130+
script:
131+
- .gitlab/verify-package-versions.sh

.gitlab/verify-package-versions.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
WHEEL_FILES=(pywheels/*.whl)
5+
if [ ${#WHEEL_FILES[@]} -eq 0 ]; then
6+
echo "No wheels found in pywheels/"; exit 1
7+
fi
8+
9+
VERSION_TAG="${CI_COMMIT_TAG#v}"
10+
echo "Verifying package version ${VERSION_TAG}"
11+
12+
for wf in "${WHEEL_FILES[@]}"; do
13+
echo "Checking wheel file: ${wf}"
14+
WHEEL_VERSION=$(basename "${wf}" | awk -F '-' '{print $2}')
15+
if [ "${WHEEL_VERSION}" != "${VERSION_TAG}" ]; then
16+
echo "ERROR: Wheel version ${WHEEL_VERSION} does not match tag version ${VERSION_TAG}"
17+
exit 1
18+
fi
19+
done
20+
21+
SDIST_FILES=(pywheels/*.tar.gz)
22+
if [ ${#SDIST_FILES[@]} -eq 0 ]; then
23+
echo "No sdist files found in pywheels/"; exit 1
24+
fi
25+
for sf in "${SDIST_FILES[@]}"; do
26+
echo "Checking sdist file: ${sf}"
27+
SDIST_VERSION=$(basename "${sf}" | awk -F '-' '{print $2}' | sed 's/\.tar\.gz$//')
28+
if [ "${SDIST_VERSION}" != "${VERSION_TAG}" ]; then
29+
echo "ERROR: Sdist version ${SDIST_VERSION} does not match tag version ${VERSION_TAG}"
30+
exit 1
31+
fi
32+
done
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
id: ddtrace-version-import
2+
message: Import `__version__` from `ddtrace.version` instead of `ddtrace`
3+
severity: error
4+
language: python
5+
ignores:
6+
- "tests/**"
7+
- "benchmarks/**"
8+
rule:
9+
any:
10+
# Match: from ddtrace import __version__ (using variable with constraint)
11+
- pattern: from $MOD import __version__
12+
# Match: from ddtrace import __version__ as $ALIAS
13+
- pattern: from $MOD import __version__ as $ALIAS
14+
# Match: from ddtrace import $$$IMPORTS, __version__
15+
- pattern: from $MOD import $$$IMPORTS, __version__
16+
# Match: from ddtrace import $$$IMPORTS, __version__ as $ALIAS
17+
- pattern: from $MOD import $$$IMPORTS, __version__ as $ALIAS
18+
# Match: from ddtrace import __version__, $$$IMPORTS
19+
- pattern: from $MOD import __version__, $$$IMPORTS
20+
# Match: from ddtrace import __version__ as $ALIAS, $$$IMPORTS
21+
- pattern: from $MOD import __version__ as $ALIAS, $$$IMPORTS
22+
# Match: from ddtrace import $$$IMPORTS, __version__, $$$IMPORTS (middle case)
23+
- pattern: from $MOD import $$$IMPORTS, __version__, $$$IMPORTS
24+
# Match: from ddtrace import $$$IMPORTS, __version__ as $ALIAS, $$$IMPORTS (middle case with alias)
25+
- pattern: from $MOD import $$$IMPORTS, __version__ as $ALIAS, $$$IMPORTS
26+
# Match: ddtrace.__version__ usage
27+
- pattern: ddtrace.__version__
28+
constraints:
29+
MOD:
30+
regex: "^ddtrace$"
31+
ALIAS:
32+
regex: ".*"
33+
note: |
34+
The `__version__` attribute should be imported from `ddtrace.version` to avoid circular dependencies and ensure proper version management.
35+
36+
Change your imports as follows:
37+
38+
**Before:**
39+
```python
40+
from ddtrace import __version__
41+
import ddtrace
42+
version = ddtrace.__version__
43+
```
44+
45+
**After:**
46+
```python
47+
from ddtrace.version import __version__
48+
```
49+
50+
This ensures that `__version__` is accessed from the dedicated version module, preventing circular import issues and making version management more explicit.

0 commit comments

Comments
 (0)