Skip to content

Commit 75bf47a

Browse files
authored
ci: validate TAG_NAME and force the version used for pypi upload (#79)
This change sets an explicit version to be used based on the TAG_NAME env var in `cloudbuild.yaml`, which is needed when the tag differs from the tip of main. Also sets the fallback version to a local version to ensure it gets rejected by PyPi in case it ever accidentally is used for uploading. Also adds a validation check to cloudbuild.yaml to fail fast if it looks like it might be building the fallback version.
1 parent 6aa148a commit 75bf47a

File tree

2 files changed

+51
-12
lines changed

2 files changed

+51
-12
lines changed

cloudbuild.yaml

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,53 @@
1313
# limitations under the License.
1414

1515
steps:
16-
# 1. Build the source distribution (sdist).
17-
- name: 'python:3.10'
18-
id: 'build-sdist'
19-
entrypoint: 'bash'
16+
# 1. Validate the tag and normalize the version.
17+
# This ensures the build only proceeds for properly formatted release tags (vX.Y.Z).
18+
# The normalized version (without 'v') is saved to a file for subsequent steps.
19+
- name: 'bash'
20+
id: 'validate-tag'
2021
args:
2122
- '-c'
2223
- |
2324
if [ -z "$TAG_NAME" ]; then
2425
echo "Error: TAG_NAME is not set. This pipeline is only for tag-based releases."
2526
exit 1
2627
fi
28+
29+
# Regex for vX.Y.Z (plus optional suffixes starting with '-')
30+
if [[ ! "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-.*)?$ ]]; then
31+
echo "Error: Invalid tag format '$TAG_NAME'. Expected vX.Y.Z or vX.Y.Z-suffix"
32+
exit 1
33+
fi
34+
35+
36+
if [[ "$TAG_NAME" == "v0.0.0"* ]]; then
37+
echo "Error: Cannot publish fallback version '$TAG_NAME'."
38+
exit 1
39+
fi
40+
41+
# Strip the 'v' prefix and save for subsequent steps
42+
VERSION=${TAG_NAME#v}
43+
echo "$VERSION" > _PYPI_VERSION.txt
44+
echo "Validated version: $VERSION"
45+
46+
# 2. Build the source distribution (sdist).
47+
- name: 'python:3.10'
48+
id: 'build-sdist'
49+
entrypoint: 'bash'
50+
args:
51+
- '-c'
52+
- |
53+
# Explicitly setting the version to use, so that it doesn't use local versions derived from Git
54+
# when running for a tag that is behind the latest commit on main.
55+
export SETUPTOOLS_SCM_PRETEND_VERSION=$(cat _PYPI_VERSION.txt)
56+
echo "Building sdist for version: $${SETUPTOOLS_SCM_PRETEND_VERSION}"
57+
2758
pip install build
2859
python -m build --sdist
60+
waitFor: ['validate-tag']
2961

30-
# 2. Build the manylinux wheels.
62+
# 3. Build the manylinux wheels.
3163
# We use the manylinux image directly to avoid the "reserved" docker.sock issue.
3264
# This image is pre-loaded with Python versions and build tools.
3365
- name: '$_MANYLINUX_IMAGE'
@@ -38,9 +70,17 @@ steps:
3870
- |
3971
# Use Python 3.10 as the build controller (it will produce the abi3 wheel)
4072
PYBIN="/opt/python/cp310-cp310/bin"
73+
export SETUPTOOLS_SCM_PRETEND_VERSION=$(cat _PYPI_VERSION.txt)
4174
4275
# Install build dependencies
43-
$$PYBIN/pip install build
76+
$$PYBIN/pip install build setuptools-scm
77+
78+
# Validation: Ensure scikit-build-core is actually using our pretend version
79+
DETECTED_VERSION=$$($$PYBIN/python -c "import setuptools_scm; print(setuptools_scm.get_version())")
80+
if [ "$$DETECTED_VERSION" != "$$SETUPTOOLS_SCM_PRETEND_VERSION" ]; then
81+
echo "Error: Version mismatch! Expected $$SETUPTOOLS_SCM_PRETEND_VERSION but detected $$DETECTED_VERSION."
82+
exit 1
83+
fi
4484
4585
echo "Building wheel (scikit-build-core will handle abi3 and C++ extension compilation)..."
4686
SKBUILD_CMAKE_ARGS="-DBUILD_TESTING=OFF" $$PYBIN/python -m build --wheel
@@ -54,8 +94,7 @@ steps:
5494
rm dist/*-linux_*.whl
5595
waitFor: ['build-sdist']
5696

57-
58-
# 3. Upload to internal Artifact Registry (AR) for OSS Exit Gate.
97+
# 4. Upload to internal Artifact Registry (AR) for OSS Exit Gate.
5998
- name: 'python:3.10'
6099
id: 'upload-to-ar'
61100
entrypoint: 'bash'
@@ -66,7 +105,7 @@ steps:
66105
twine upload --repository-url https://us-python.pkg.dev/oss-exit-gate-prod/${_PROJECT_NAME}--pypi dist/*
67106
waitFor: ['build-wheels']
68107

69-
# 4. Create and upload the manifest to GCS to trigger the Exit Gate publication.
108+
# 5. Create and upload the manifest to GCS to trigger the Exit Gate publication.
70109
# The presence of this file in the specific GCS bucket triggers the verification and publishing process.
71110
- name: 'gcr.io/cloud-builders/gcloud'
72111
id: 'trigger-exit-gate'

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,9 @@ cmake.source-dir = "."
160160
# Tool-specific Configuration for setuptools-scm
161161
# ===================================================================
162162
[tool.setuptools_scm]
163-
# Fallback version to use if git is not available or the directory is not a git repo.
164-
# This prevents build failures in environments like some CI runners or /tmp clones.
165-
fallback_version = "0.0.0"
163+
# Fallback version for local development in non-git environments.
164+
# The '+' ensures PyPI will reject this version if it's accidentally uploaded.
165+
fallback_version = "0.0.0+dev.local"
166166

167167
# ===================================================================
168168
# Tool-specific Configuration for Ruff

0 commit comments

Comments
 (0)