Skip to content
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d90f9d0
Add cctools CI-tools image + ci-base VM builder
Brian-McM Sep 2, 2026
62b5712
Rename cctools -> scratch-utils; address review feedback
Brian-McM Sep 2, 2026
50457c0
vm-image: source Go + go-build versions from calico-go-build/versions…
Brian-McM Sep 2, 2026
e7601d0
Add VM-image promotions, tests, and the remaining review fixes
Brian-McM Sep 3, 2026
cf65a97
preload-disk: pin the gke-disk-image-builder commit
Brian-McM Sep 3, 2026
ace7e97
Name the VM and disk images off the go-build release tag
Brian-McM Sep 3, 2026
02c2835
Name non-tag image builds after the branch, as go-build does
Brian-McM Sep 3, 2026
7c32cf7
preload-disk: correct the branch-image replacement warning
Brian-McM Sep 3, 2026
7a59bfb
Tighten comments across scratch-utils, vm-image and preload-disk
Brian-McM Sep 3, 2026
6e9da91
createvm: pin an exact VM image; preload-disk: make the network confi…
Brian-McM Sep 3, 2026
befd125
Document that the subcommand is an argument, not the command
Brian-McM Sep 3, 2026
05ec192
createvm: give each zone its own deadline and report every zone's error
Brian-McM Sep 4, 2026
bbf168f
scratch-utils: bump image to v0.3
Brian-McM Sep 4, 2026
a373172
gce: correct the max-run-duration backstop claim
Brian-McM Sep 4, 2026
8f7b1ef
preload-disk: correct the cross-project claim
Brian-McM Sep 4, 2026
4fb9055
preload-disk: fit the GKE 39-character secondary boot disk name cap
Brian-McM Sep 4, 2026
a1ff5f6
preload-disk: build in tigera-cc-dev, where the clusters are
Brian-McM Sep 4, 2026
1412cd9
gce: retry transient control-plane errors, keeping the call in the me…
Brian-McM Sep 9, 2026
95ab59b
Merge remote-tracking branch 'upstream/master' into bm-add-cctools-an…
Brian-McM Sep 9, 2026
40999e1
preload-disk: drop the next-steps log block
Brian-McM Sep 9, 2026
fd4234d
Make the builder trees plural, with the artifact as a subfolder
Brian-McM Sep 9, 2026
217acd5
Tighten comments again: fewer, and shorter
Brian-McM Sep 9, 2026
b1bc61e
ci-base: pre-pull a list of kind node images, not just one
Brian-McM Sep 9, 2026
2981a0c
preload-disks: name it ci-cache, not go-build
Brian-McM Sep 9, 2026
3d1b7ea
Drop the vm-images and preload-disks READMEs
Brian-McM Sep 9, 2026
153649c
Quote remote paths for the shell; validate env names; reject bad disk…
Brian-McM Sep 9, 2026
4387ea8
Fail the image build on a bad download; harden ADC and not-found dete…
Brian-McM Sep 9, 2026
4ea9dd6
scratch-utils: build on scratch rather than distroless
Brian-McM Sep 9, 2026
5ebfe3c
scratch-utils: release by tag, publish moving images from master
Brian-McM Sep 9, 2026
8289024
Chain the VM and preload-disk builds off the go-build publish
Brian-McM Sep 9, 2026
cc112cd
Gate the VM and preload-disk blocks like calico-go-build's
Brian-McM Sep 9, 2026
e2f55b3
Address review feedback on scratch-utils, ci-base and ci-cache
Brian-McM Sep 11, 2026
d8d5d81
gce: never hand a dying VM to a caller that wants to run on one
Brian-McM Sep 11, 2026
e706f7c
gce: treat STOPPED as going away, like TERMINATED
Brian-McM Sep 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
cmd/bin
images/calico-binfmt/bin
images/calico-go-build/bin
images/calico-scratch-utils/bin
31 changes: 31 additions & 0 deletions .semaphore/promotions/calico-scratch-utils.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: v1.0
name: Publish calico/scratch-utils images
agent:
machine:
type: f1-standard-2
os_image: ubuntu2204

execution_time_limit:
minutes: 30

global_job_config:
env_vars:
- name: DEV_REGISTRIES
value: calico
secrets:
- name: docker
prologue:
commands:
- echo $DOCKER_TOKEN | docker login --username "$DOCKER_USER" --password-stdin
- checkout

blocks:
- name: Publish calico/scratch-utils amd64 images
dependencies: []
run:
when: "branch = 'master'"
task:
jobs:
- name: Linux amd64
commands:
- if [ -z "${SEMAPHORE_GIT_PR_NUMBER}" ]; then make -C images calico-scratch-utils-cd CONFIRM=true; fi
47 changes: 47 additions & 0 deletions .semaphore/promotions/ci-base-vm-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
version: v1.0
name: Build ci-base VM image
agent:
machine:
type: f1-standard-2
os_image: ubuntu2204

execution_time_limit:
minutes: 30

# Manual-only (no auto_promote in semaphore.yml): trigger from the Semaphore UI to
# (re)build the ci-base GCE VM image. The work runs on a throwaway builder VM (see
# vm-images/ci-base/build-image.sh); this agent just drives gcloud. The image lives in a
# family, so createvm always gets the newest.
#
# The baked toolchain is pinned: Go and calico/go-build from
# images/calico-go-build/versions.yaml, kind/gh from vm-images/ci-base/versions.yaml. Re-run
# after bumping either.
global_job_config:
env_vars:
- name: PROJECT
value: unique-caldron-775
- name: ZONE
value: us-central1-a
- name: FAMILY
value: ci-base
# Same secret the projectcalico/calico GCE jobs use. Needs compute instance +
# image create/delete in PROJECT.
secrets:
- name: google-service-account-for-gce
prologue:
commands:
- export GOOGLE_APPLICATION_CREDENTIALS=$HOME/secrets/secret.google-service-account-key.json
- gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS
- gcloud config set project $PROJECT
- checkout
# build-image.sh reads the versions.yaml files with yq.
- which yq || (sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 && sudo chmod +x /usr/local/bin/yq)

blocks:
- name: Build ci-base VM image
dependencies: []
task:
jobs:
- name: build-image
commands:
- bash vm-images/ci-base/build-image.sh
54 changes: 54 additions & 0 deletions .semaphore/promotions/preload-disk-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
version: v1.0
name: Build go-build preload disk image
agent:
machine:
type: f1-standard-2
os_image: ubuntu2204

execution_time_limit:
minutes: 30

# Manual-only (no auto_promote in semaphore.yml): trigger from the Semaphore UI to
# (re)build the GKE secondary-boot-disk image preloading calico/go-build. The work
# runs on a throwaway builder VM via Google's gke-disk-image-builder (see
# preload-disks/ci-cache/build-preload-disk.sh); this agent drives gcloud + `go run`.
global_job_config:
env_vars:
# The project holding the GKE clusters that consume the disk. Building it here
# keeps the image with its consumer and needs no cross-project IAM; a pool CAN
# reference an image elsewhere, but then both the cluster's compute SA and its
# GKE service agent need compute.imageUser -- see the build script's header.
- name: PROJECT
value: tigera-cc-dev
- name: ZONE
value: us-central1-a
# Daisy scratch/staging bucket the builder requires (uploads its workflow
# sources + streams the builder VM's serial log here); the SA needs write access.
# Must live in PROJECT: the builder VM writes its serial log, so a bucket
# elsewhere reintroduces the cross-project IAM that building here avoids.
- name: GCS_PATH
value: gs://gke-argo-disk-images-cc-dev
# Same secret the projectcalico/calico GCE jobs use; also feeds ADC, which
# gke-disk-image-builder reads. Needs compute instance/disk/image create+delete
# and log-bucket write in PROJECT.
secrets:
- name: google-service-account-for-gce
prologue:
commands:
- export GOOGLE_APPLICATION_CREDENTIALS=$HOME/secrets/secret.google-service-account-key.json
- gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS
- gcloud config set project $PROJECT
# gke-disk-image-builder is `go run ./cli`; pick the Go the tool's go.mod needs.
- sem-version go 1.24
- checkout
# build-preload-disk.sh resolves the go-build tag from versions.yaml with yq.
- which yq || (sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 && sudo chmod +x /usr/local/bin/yq)

blocks:
- name: Build preload disk image
dependencies: []
task:
jobs:
- name: build-preload-disk
commands:
- bash preload-disks/ci-cache/build-preload-disk.sh
32 changes: 32 additions & 0 deletions .semaphore/semaphore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ promotions:
pipeline_file: promotions/calico-tinygo.yml
auto_promote:
when: "branch = 'master' AND change_in('/images/calico-tinygo/')"
# Publish scratch-utils images for master when the binary or image changed.
- name: Publish calico/scratch-utils images
pipeline_file: promotions/calico-scratch-utils.yml
auto_promote:
when: "branch = 'master' AND change_in(['/images/calico-scratch-utils/', '/cmd/scratch-utils/', '/scratch-utils/'])"
# Manual only (no auto_promote): trigger from the Semaphore UI to (re)build the
# ci-base GCE VM image. See promotions/ci-base-vm-image.yml and vm-images/ci-base/.
- name: Build ci-base VM image
pipeline_file: promotions/ci-base-vm-image.yml
# Manual only (no auto_promote): trigger from the Semaphore UI to (re)build the
# go-build preload disk image. See promotions/preload-disk-image.yml and preload-disks/ci-cache/.
- name: Build go-build preload disk image
pipeline_file: promotions/preload-disk-image.yml

blocks:
- name: calico/go-build image
Expand Down Expand Up @@ -186,3 +199,22 @@ blocks:
matrix:
- env_var: ARCH
values: ["amd64", "arm64"]

- name: calico/scratch-utils image
dependencies: []
task:
jobs:
- name: Build calico/scratch-utils amd64 image
commands:
- make -C images calico-scratch-utils-image ARCH=amd64

# Run in the golang image at the version versions.yaml pins, so the tests see the
# same Go the go-build image ships and the agent needs none of its own.
- name: Go unit tests
dependencies: []
task:
jobs:
- name: go test
commands:
- GO_VERSION=$(hack/generate-version-tag-name.sh -f images/calico-go-build/versions.yaml -g)
- docker run --rm -v "$PWD:/src" -w /src golang:${GO_VERSION} go test ./scratch-utils/... ./cmd/...
10 changes: 9 additions & 1 deletion cmd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ BINFMT_VERSION = $(shell yq -r '.tonistiigi-binfmt.version' ../images/calico-bin
QEMU_VERSION = $(shell yq -r '.qemu.version' ../images/calico-binfmt/versions.yaml)

.PHONY: build
build: bin/binfmt-$(ARCH) bin/semvalidator-$(ARCH)
build: bin/binfmt-$(ARCH) bin/semvalidator-$(ARCH) bin/scratch-utils-$(ARCH)

bin/binfmt-$(ARCH): binfmt/main.go
CGO_ENABLED=0 GOOS=linux GOARCH=$(ARCH) \
Expand All @@ -17,6 +17,14 @@ bin/semvalidator-$(ARCH): semvalidator/main.go
CGO_ENABLED=0 GOOS=linux GOARCH=$(ARCH) \
go build -o bin/semvalidator-$(ARCH) -v -buildvcs=false -ldflags "-s -w" semvalidator/main.go

# Unlike the single-file binaries above, this one spans ../scratch-utils/, so list
# every .go file it compiles -- otherwise an incremental build ships a stale binary.
SCRATCH_UTILS_SRCS = $(shell find scratch-utils ../scratch-utils -name '*.go')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things here:

= is recursive, so this find re-runs every time make expands the prerequisite list. := runs it once.

Bigger: build: now depends on bin/scratch-utils-$(ARCH), and build is a prerequisite of calico-go-build-image (images/Makefile:67) and calico-binfmt-image (:100). Every arch of the go-build image matrix now downloads and compiles google.golang.org/api, gRPC and the OTel stack — roughly 20 modules those images never contain — before it can start its own Dockerfile.

Give bin/scratch-utils-$(ARCH) its own target that only calico-scratch-utils-image depends on.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


bin/scratch-utils-$(ARCH): $(SCRATCH_UTILS_SRCS)
CGO_ENABLED=0 GOOS=linux GOARCH=$(ARCH) \
go build -o bin/scratch-utils-$(ARCH) -v -buildvcs=false -ldflags "-s -w" ./scratch-utils

.PHONY: clean
clean:
rm -fr bin/
53 changes: 53 additions & 0 deletions cmd/scratch-utils/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) 2026 Tigera, Inc. All rights reserved.

// Command scratch-utils bundles the CI VM helpers into one binary dispatched by
// subcommand -- one image, different args, not four binaries:
//
// scratch-utils createvm create the CI GCE VM (config from env)
// scratch-utils deletevm delete it by name, best-effort
// scratch-utils secret <ENV_VAR> <DEST_PATH> env var -> file
// scratch-utils runonvm [flags] <script> run a script on the VM over SSH
//
// No gcloud or bash dependency, so it runs from a distroless image. The ENTRYPOINT
// is this binary, so a pod passes the subcommand as an ARGUMENT -- `args:
// [createvm]`; a bare `command: [createvm]` replaces the entrypoint and fails.
package main

import (
"fmt"
"os"

"github.com/projectcalico/go-build/scratch-utils/subcmd/createvm"
"github.com/projectcalico/go-build/scratch-utils/subcmd/deletevm"
"github.com/projectcalico/go-build/scratch-utils/subcmd/runonvm"
"github.com/projectcalico/go-build/scratch-utils/subcmd/secret"
)

func main() {
if len(os.Args) < 2 {
usage()
os.Exit(2)
}
sub := os.Args[1]
// Each subcommand then sees its own args as os.Args[1:].
os.Args = append([]string{os.Args[0] + " " + sub}, os.Args[2:]...)

switch sub {
case "createvm":
os.Exit(createvm.Run())
case "deletevm":
os.Exit(deletevm.Run())
case "secret":
os.Exit(secret.Run())
case "runonvm":
os.Exit(runonvm.Run())
default:
fmt.Fprintf(os.Stderr, "scratch-utils: unknown subcommand %q\n", sub)
usage()
os.Exit(2)
}
}

func usage() {
fmt.Fprintln(os.Stderr, "usage: scratch-utils <createvm|deletevm|secret|runonvm> [args]")
}
21 changes: 21 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,35 @@ require (
github.com/opencontainers/image-spec v1.1.1
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.10.1
golang.org/x/crypto v0.55.0
google.golang.org/api v0.296.0
)

require (
cloud.google.com/go/auth v0.23.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.20 // indirect
github.com/googleapis/gax-go/v2 v2.24.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/tonistiigi/go-archvariant v1.0.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect
go.opentelemetry.io/otel v1.45.0 // indirect
go.opentelemetry.io/otel/metric v1.45.0 // indirect
go.opentelemetry.io/otel/trace v1.45.0 // indirect
golang.org/x/net v0.58.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/text v0.41.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 // indirect
google.golang.org/grpc v1.83.2 // indirect
google.golang.org/protobuf v1.36.12 // indirect
)
59 changes: 59 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
cloud.google.com/go/auth v0.23.2 h1:pxSCpfiji41hpzpPdMCftEUCezpgpqmmDdYiAjCKXxo=
cloud.google.com/go/auth v0.23.2/go.mod h1:4DhBRcqvtljQN3dJ57qtqbib5ZGCYE5f2crfiiC2EM0=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v1.0.0-rc.5 h1:vXd569rDrz8LeMXzAnBsy6LADV5YtsD8oyaRarxdmSU=
github.com/containerd/platforms v1.0.0-rc.5/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.20 h1:t/xL64VUoN69MuMRQuJETqYGOw4Z9mSRJK9epIEtwFk=
github.com/googleapis/enterprise-certificate-proxy v0.3.20/go.mod h1:L3D/IQExI6LqEjBdXcZQ1WluSgigQmSwBboFstVPM4w=
github.com/googleapis/gax-go/v2 v2.24.0 h1:myMaPYyF9MecEmvQqMqomIwn9t/4KCZN9qnwsS76wlg=
github.com/googleapis/gax-go/v2 v2.24.0/go.mod h1:IaTHBDd7NHxSCiu0vEs8pQZu4dGZrWwuSoxCnk16OFM=
github.com/moby/buildkit v0.32.2 h1:Sfy7+u6dUv/2yuBc9KCoK70Re8atuV8aPZ5UOC068Vc=
github.com/moby/buildkit v0.32.2/go.mod h1:0GB/EJ1d+4VIVqIAgy3asaoGkVXy7IrDfVy7mPhOvg8=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
Expand All @@ -20,11 +43,47 @@ github.com/stretchr/testify v1.12.0 h1:K6Mr6jO9JICuend/5xzTM03ydSV3vdNRYAdPSukj8
github.com/stretchr/testify v1.12.0/go.mod h1:bOYBZb5qJ00vPzWfIqBUZPaxK8jWiXc6d3ErP4Ca9Gw=
github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0=
github.com/tonistiigi/go-archvariant v1.0.0/go.mod h1:TxFmO5VS6vMq2kvs3ht04iPXtu2rUT/erOnGFYfk5Ho=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU=
go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ=
go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M=
go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s=
go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag=
go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc=
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
google.golang.org/api v0.296.0 h1:Nn5EHeKdGx70MFClaV/II0gsWUm6xhEjb0xYLylVvaA=
google.golang.org/api v0.296.0/go.mod h1:02qB8+Ox1ZFzcaKFMguy1nQLJmSIyvV6Ff4txJEXtl4=
google.golang.org/genproto v0.0.0-20260715232425-e75dac1f907d h1:C9v1o0/4quuhOAfmRXA2j+we0PqZIp8traLdeogF3Ms=
google.golang.org/genproto v0.0.0-20260715232425-e75dac1f907d/go.mod h1:Wz2wFJntZFmLGo7pLDXZ3wYk5hyc0Mb+SkHhDDXT+lU=
google.golang.org/genproto/googleapis/api v0.0.0-20260715232425-e75dac1f907d h1:QwnJwPte4XXAkhPu26LTDIahnsMSUV0kK8HkxbC+Pc4=
google.golang.org/genproto/googleapis/api v0.0.0-20260715232425-e75dac1f907d/go.mod h1:WRrQ7/7N19PypuT0fxLOL5Lq0waoiRri4FbtHDEKrGE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 h1:cYNAzI2sUwhmCcoj9TxvihSrqsxt6uIkj3rDRhSDmW4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU=
google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading