Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 14 additions & 5 deletions .ko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.

defaultBaseImage: gcr.io/distroless/static-debian13
# Every base image is pinned by digest so that two builds of the same commit

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.

I don't think we need the comments to justify pinning by SHA

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.

+1, we pin by sha for most images in the repo without any comment.

Also, are we sure these digests point at the tag we specified, if an agent generated this?

This is the sort of PR I would 100% hand generate. You can use crane digest on the intended image for TOFU.

# produce the same images regardless of when or where they run. The tag is
# kept next to the digest for readability and so a bump can re-resolve it:
# the digest is what ko uses. hack/verify/ko-base-images.sh fails a ref
# without a digest. Bump by re-resolving each tag (`crane digest <ref:tag>`)
# and replacing the digest; a change of tag (a new major) is a deliberate
# edit, not a bump.

defaultBaseImage: gcr.io/distroless/static-debian13:latest@sha256:f2ea2709ac8db56323cbd7d014277f32cb572d9ea124b0076f7aafe5980678fe

defaultPlatforms:
- linux/amd64
- linux/arm64

baseImageOverrides:
github.com/agent-substrate/substrate/demos/sandbox: alpine
github.com/agent-substrate/substrate/demos/sandbox: alpine:3.24@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b
# ateom-microvm needs glibc (for the fetched cloud-hypervisor binary) and mount/umount
# (to bind the image into the virtiofsd shared dir) — both in debian:stable-slim but
# not in the distroless static default.
github.com/agent-substrate/substrate/cmd/ateom-microvm: debian:stable-slim
# (to bind the image into the virtiofsd shared dir) — both in debian slim but
# not in the distroless static default. Pinned to an explicit Debian major
# rather than stable-slim, which silently moves when Debian's stable does.
github.com/agent-substrate/substrate/cmd/ateom-microvm: debian:13-slim@sha256:d7e12182ce18b85b93007c1dedf31f2d29e01ccf3182cc4017c709b6259bc132
53 changes: 53 additions & 0 deletions hack/verify/ko-base-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bash

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.

I don't think we need a defensive script for this. PR review should be sufficient. These cost time on every PR and we're already tight on CI resources.


# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Fails if any base image in .ko.yaml is not pinned by digest. A tag-only base
# makes the build depend on when it runs: the same commit built a week apart
# would produce different images. See the header comment in .ko.yaml.

set -o errexit -o nounset -o pipefail

ROOT="$(git rev-parse --show-toplevel)"
cd "${ROOT}"

# Image refs are the values of defaultBaseImage and of every entry under
# baseImageOverrides. Both are `key: value` lines; comments and blank lines
# are dropped. defaultPlatforms entries are list items and never match.
refs="$(sed -e 's/#.*$//' .ko.yaml \
| awk '
/^defaultBaseImage:/ { print $2; next }
/^baseImageOverrides:/ { in_overrides = 1; next }
/^[^[:space:]]/ { in_overrides = 0 }
in_overrides && NF >= 2 { print $NF }
')"

if [[ -z "${refs}" ]]; then
echo "error: no base image refs found in .ko.yaml" >&2
exit 1
fi

rc=0
while IFS= read -r ref; do
if [[ ! "${ref}" =~ @sha256:[0-9a-f]{64}$ ]]; then
echo "error: .ko.yaml base image is not pinned by digest: ${ref}" >&2
rc=1
fi
done <<< "${refs}"

if [[ "${rc}" -ne 0 ]]; then
echo "Pin every base image as <image>:<tag>@sha256:<digest> (see .ko.yaml)." >&2
fi
exit "${rc}"
Loading