build: Add Cloud Build pipeline for tag-triggered AR uploads (#18)

* Add Cloud Build pipeline for tag-triggered AR uploads Builds sdist + wheel via 'uv build' against the tagged commit and publishes both to the colab-cli Python repo in Artifact Registry (us-central1-python.pkg.dev/colab-cli-external/colab-cli). Hatch-vcs derives the version from the tag, so the build unshallows the GitHub checkout to make 'git describe' return the clean tag name. * Fix Cloud Build pipeline: use git-equipped uv image, trim shell flags The uv:python3.13-bookworm-slim image lacks a git binary, which causes hatch-vcs to fail with 'not a git repository' during 'uv build'. Switch to the non-slim bookworm variant so git is available for the version derivation. Also simplify the shell prologue in each step to 'set -e' (the existing 'set -euo pipefail' was overkill: no pipelines are used, and Cloud Build expands substitutions before bash sees them so '-u' adds no coverage).

Tyler committed May 18, 2026 at 16:53 UTC bc29f732e6bfd3e9bb35075de489d01b7cbd0c99
1 file changed +73
cloudbuild.yaml new
+73
@@ -0,0 +1,73 @@
1 +# Cloud Build pipeline triggered on git tag push.
2 +#
3 +# Builds an sdist + wheel for colab-cli using `uv build`, then publishes both
4 +# to the Artifact Registry Python repository at
5 +# us-central1-python.pkg.dev/colab-cli-external/colab-cli/
6 +#
7 +# The build runs against the tagged commit (TAG_NAME is set by the trigger).
8 +# Version is derived from the git tag by hatch-vcs, so the checkout must have
9 +# tags available (Cloud Build's default GitHub checkout includes them).
10 +#
11 +# Trigger: GitHub push to refs/tags/v* on googlecolab/google-colab-cli (main).
12 +substitutions:
13 + _AR_LOCATION: us-central1
14 + _AR_REPOSITORY: colab-cli
15 + _AR_PROJECT: colab-cli-external
16 +
17 +steps:
18 + # 1. Ensure hatch-vcs sees the tag. Cloud Build's default GitHub checkout
19 + # is shallow and may omit tag refs; unshallow + force-fetch tags so
20 + # `git describe` returns the clean tag (e.g. v0.4.0 -> 0.4.0) rather
21 + # than a dev-suffixed pseudo-version.
22 + - id: show-version
23 + name: gcr.io/cloud-builders/git
24 + entrypoint: bash
25 + args:
26 + - -c
27 + - |
28 + set -e
29 + git fetch --tags --force --unshallow 2>/dev/null || git fetch --tags --force
30 + echo "TAG_NAME=${TAG_NAME}"
31 + echo "git describe: $(git describe --tags --always)"
32 +
33 + # 2. Build sdist + wheel into dist/ using uv.
34 + # Use the non-slim bookworm variant: hatch-vcs derives the version
35 + # by shelling out to `git describe`, which requires a git binary
36 + # in the build container. The -slim variant omits git and breaks
37 + # the build with a setuptools-scm "not a git repository" error.
38 + - id: build
39 + name: ghcr.io/astral-sh/uv:python3.13-bookworm
40 + entrypoint: bash
41 + args:
42 + - -c
43 + - |
44 + set -e
45 + uv build
46 + ls -la dist/
47 +
48 + # 3. Publish artifacts to Artifact Registry via twine + the
49 + # google-artifactregistry-auth keyring plugin (uses ADC from the
50 + # Cloud Build service account).
51 + - id: publish
52 + name: python:3.13-slim
53 + entrypoint: bash
54 + args:
55 + - -c
56 + - |
57 + set -e
58 + pip install --quiet --root-user-action=ignore \
59 + twine keyrings.google-artifactregistry-auth
60 + twine upload \
61 + --repository-url "https://${_AR_LOCATION}-python.pkg.dev/${_AR_PROJECT}/${_AR_REPOSITORY}/" \
62 + --verbose \
63 + dist/*
64 +
65 +# Surface the built artifacts in the Cloud Build UI / logs.
66 +artifacts:
67 + objects:
68 + location: gs://${PROJECT_ID}_cloudbuild/colab-cli/${TAG_NAME}
69 + paths:
70 + - dist/*
71 +
72 +options:
73 + logging: CLOUD_LOGGING_ONLY