From db226ae6e1f588e553fd7c812df5fd89449cc9f0 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Sat, 24 Oct 2026 15:37:57 -0300 Subject: [PATCH 1/3] ci: every workflow step is one task, and Task from go.mod A step that ran its own shell was a second copy of the build that only ever ran on a push. Each of the 37 is now `go tool task `: an existing task where one already did the same thing (boot:roms, boot:compat), a new one beside it otherwise, with what only the workflow knows in the step's env: and its outputs, env and summary written by the task (to stdout outside CI). Task is a go.mod tool at 3.54.0, the version versions.yaml pins for the image, so a workflow needs only setup-go, and the Taskfiles call themselves through TASK_EXE. go-tools moves to spin-stack/go-tools#50 for its two new gates, which task lint runs: taskgate, with no exemption, and sfw, which finds no JavaScript here and holds the first package.json to pnpm through Socket Firewall. attestgate is told which tasks publish (qemu:publish, report:publish) and which attests (release:sign), since the YAML now names them only. lab, report and release run Task with interleaved output: a prefixed line hides the ::error:: commands their tasks print. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 50 +--- .github/workflows/compat.yml | 30 +-- .github/workflows/image.yml | 24 +- .github/workflows/kernel.yml | 21 +- .github/workflows/lab.yml | 113 +-------- .github/workflows/osv.yml | 7 +- .github/workflows/qemu.yml | 45 +--- .github/workflows/release.yml | 116 +-------- .github/workflows/report.yml | 68 +----- README.md | 5 +- Taskfile.yml | 436 +++++++++++++++++++++++++++++++++- boot/Taskfile.yml | 31 +++ go.mod | 137 ++++++++++- go.sum | 259 ++++++++++++++++++++ image/Taskfile.yml | 8 + kernel/Taskfile.yml | 10 + qemu/Taskfile.yml | 38 +++ workflows/workflows_test.go | 27 ++- 18 files changed, 1003 insertions(+), 422 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 256341f..8cc21ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,39 +53,19 @@ jobs: go-version-file: go.mod cache: true - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - # `task lint` and `task test`, and not a list of steps: a second definition of what # the gate is, maintained in a workflow file, goes out of step with the first exactly # when a check is added. - name: Lint - run: task lint + run: go tool task lint - name: Test the machine definition - run: task test + run: go tool task test # always(): a failed suite is when the per-function numbers are wanted. - name: Coverage summary if: always() - run: | - if [ ! -f coverage.out ]; then - echo "coverage.out was not produced; the tests may have failed before coverage ran." >> "$GITHUB_STEP_SUMMARY" - exit 0 - fi - { - echo "## Go coverage" - echo - echo "**$(go tool cover -func=coverage.out | awk '/^total:/ {print $3}')** total" - echo - echo '
Function detail' - echo - echo '```' - go tool cover -func=coverage.out - echo '```' - echo '
' - } >> "$GITHUB_STEP_SUMMARY" - go tool cover -html=coverage.out -o coverage.html + run: go tool task coverage - name: Upload Go coverage HTML if: always() @@ -100,23 +80,13 @@ jobs: # is against what it merges into, on a push against what was there before. - name: What this change broke, and whether a test noticed env: - EVENT: ${{ github.event_name }} - BASE_REF: ${{ github.base_ref }} BEFORE: ${{ github.event.before }} - run: | - set -euo pipefail - if [ "$EVENT" = "pull_request" ]; then - base="origin/$BASE_REF" - else - base="$BEFORE" - fi - git rev-parse --verify "$base^{commit}" >/dev/null 2>&1 || base=HEAD~1 - task mutate BASE="$base" + run: go tool task mutate # The steps below run spin-machine, so it has to exist. `task test` exercises the # machine package; only a build catches what the command around it does with it. - name: Build the tools - run: task tools + run: go tool task tools # `task test` proves the machine package agrees with itself. The steps below ask the # QEMU binary, which is the half that can disagree: the device set is decided in @@ -148,7 +118,7 @@ jobs: - name: Fetch the pinned QEMU id: qemu continue-on-error: true - run: task qemu:fetch + run: go tool task qemu:fetch # vhost-vsock is a kernel module, and the machine's vsock device cannot be created # without /dev/vhost-vsock. The runner has the node and gives the user no access to @@ -158,12 +128,8 @@ jobs: # told what went unchecked instead of being shown a pass. - name: Load vhost_vsock if: steps.qemu.outcome == 'success' - run: | - # The device first: a kernel that builds it in - Spin OS's, which has no modules - has - # it from boot, and modprobe there has nothing to find. - { [ -c /dev/vhost-vsock ] || sudo modprobe vhost_vsock; } && sudo chmod 0666 /dev/vhost-vsock || - echo "no vhost_vsock here; the check will name vhost-vsock-pci as unchecked" + run: go tool task vsock - name: Check QEMU accepts the machine's arguments if: steps.qemu.outcome == 'success' - run: task verify:args + run: go tool task verify:args diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml index 7b04bbf..9b6f12b 100644 --- a/.github/workflows/compat.yml +++ b/.github/workflows/compat.yml @@ -63,37 +63,21 @@ jobs: go-version-file: go.mod cache: false - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - # A builder that can export its cache to the directory above; the runner keeps it. - name: A BuildKit that keeps its cache - run: docker buildx inspect compat > /dev/null 2>&1 && docker buildx use compat || docker buildx create --use --name compat --driver docker-container + run: go tool task boot:buildkit - name: Build this change's QEMU and kernel, and the tools - run: task qemu:build kernel:build tools + run: go tool task qemu:build kernel:build tools # The newest release, checked against its sha256 and its signature, as the machine before; - # this change's machine is the same tree with what was just built in place of its own. + # this change's machine is the same tree with what was just built in place of its own. The + # steps after boot that tree: it is their SPIN_MACHINE_OUTPUT. - name: The machine before, and this one - run: | - set -euo pipefail - task boot:previous - previous=$(cat _output/compat/previous) - here=$PWD/_output/compat/here - rm -rf "$here" && cp -as "$previous" "$here" - rm -rf "$here/bin" "$here/qemu" "$here/kernel" - mkdir -p "$here/bin" "$here/kernel" - cp _output/bin/qemu-system-x86_64 _output/bin/qemu-img _output/bin/spin-machine "$here/bin/" - cp -r _output/qemu "$here/qemu" - cp _output/kernel/vmlinux "$here/kernel/vmlinux" - { - echo "SPIN_COMPAT_PREVIOUS=$previous" - echo "SPIN_MACHINE_OUTPUT=$here" - } >> "$GITHUB_ENV" + run: go tool task boot:here - name: Every ROM the machine maps is the fingerprint's - run: SPIN_ROM_TEST=1 go test ./boot/ -run '^TestEveryROMIsTheFingerprints$' -count=1 -v -timeout 3m + run: go tool task boot:roms - name: A checkpoint of the release before resumes here - run: go test ./boot/ -run '^TestACheckpointOfTheReleaseBeforeResumesHere$' -count=1 -v -timeout 10m + run: go tool task boot:compat diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml index 307d37b..d3d7ca6 100644 --- a/.github/workflows/image.yml +++ b/.github/workflows/image.yml @@ -60,10 +60,7 @@ jobs: id: touches env: BASE: ${{ github.event.pull_request.base.sha || github.event.before }} - run: | - build=$(hack/touches "$BASE" alpine e2fsprogs ubuntu mkosi task git-lfs buildkit -- \ - image e2fsprogs go.mod .github/workflows/image.yml) - echo "build=${build}" | tee -a "$GITHUB_OUTPUT" + run: go tool task touches -- alpine e2fsprogs ubuntu mkosi task git-lfs buildkit -- image e2fsprogs go.mod .github/workflows/image.yml build: needs: changed @@ -81,9 +78,6 @@ jobs: go-version-file: go.mod cache: true - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - # One sticky disk per thing built, and no silent fallback; see the note in qemu.yml. This # job builds e2fsprogs and the image builder, which is one job and so one disk. - name: Setup Blacksmith Builder @@ -100,8 +94,10 @@ jobs: # The image is made and checked with the static e2fsprogs this repository builds, not # the build container's, and image/build.sh stops when it is not there. - name: Build e2fsprogs - run: | - CACHE_EXPORT=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} CACHE_BACKEND=gha task e2fsprogs:build + env: + CACHE_BACKEND: gha + CACHE_EXPORT: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + run: go tool task e2fsprogs:build # image/build.sh asserts what came out on the finished filesystem rather than # trusting the build that made it: that there is an /sbin/init and a /bin/sh, that @@ -114,13 +110,13 @@ jobs: # it would buy minutes of cache traffic in exchange for minutes of archive traffic, # and a cache entry large enough to push others out of the repository's 10 GB. - name: Build the base image - run: | - CACHE_EXPORT=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} CACHE_BACKEND=gha task image:build + env: + CACHE_BACKEND: gha + CACHE_EXPORT: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + run: go tool task image:build - name: What this image is - run: | - ls -la _output/image/rootfs.qcow2 - echo "sha256: $(sha256sum _output/image/rootfs.qcow2 | cut -d' ' -f1)" + run: go tool task image:summary # Not uploaded as an artifact: it is ~860 MB and the release workflow rebuilds it # from the same inputs. What this job is for is finding out that it still builds and diff --git a/.github/workflows/kernel.yml b/.github/workflows/kernel.yml index 2568151..65d1ed9 100644 --- a/.github/workflows/kernel.yml +++ b/.github/workflows/kernel.yml @@ -57,10 +57,7 @@ jobs: id: touches env: BASE: ${{ github.event.pull_request.base.sha || github.event.before }} - run: | - build=$(hack/touches "$BASE" debian debian-snapshot kernel moby-check-config -- \ - kernel go.mod .github/workflows/kernel.yml) - echo "build=${build}" | tee -a "$GITHUB_OUTPUT" + run: go tool task touches -- debian debian-snapshot kernel moby-check-config -- kernel go.mod .github/workflows/kernel.yml build: needs: changed @@ -78,9 +75,6 @@ jobs: go-version-file: go.mod cache: true - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - # One sticky disk per thing built, and no silent fallback; see the note in qemu.yml. - name: Setup Blacksmith Builder uses: useblacksmith/setup-docker-builder@19215110ab936351210feebdfa5b440b4493e184 # v2.2.0 @@ -97,20 +91,17 @@ jobs: # survived the strip. Without them QEMU has no entry point into this kernel and the # failure is a VM that does not start, in whichever lane boots one next. - name: Build the kernel - run: | - CACHE_EXPORT=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} CACHE_BACKEND=gha task kernel:build KERNEL_NPROC=4 + env: + CACHE_BACKEND: gha + CACHE_EXPORT: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + run: go tool task kernel:build KERNEL_NPROC=4 # What it produced, on the run's summary: a pull request that changes the config, or # bumps the Debian toolchain the kernel is compiled with, changes every guest's next # boot, and the change that does it need not look like much. Checkpoints are not # affected: the kernel is not in the fingerprint (machine.Spec.Fingerprint). - name: What this kernel is - run: | - set -euo pipefail - { - echo "kernel sha256: $(sha256sum _output/kernel/vmlinux | cut -d' ' -f1)" - echo "config sha256: $(sha256sum _output/kernel/kernel-config | cut -d' ' -f1)" - } | tee -a "$GITHUB_STEP_SUMMARY" + run: go tool task kernel:summary - name: Upload the kernel uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 diff --git a/.github/workflows/lab.yml b/.github/workflows/lab.yml index 5287d25..05cbaa6 100644 --- a/.github/workflows/lab.yml +++ b/.github/workflows/lab.yml @@ -89,6 +89,9 @@ jobs: KERNEL_RUN_C: ${{ inputs.kernel_run_c }} QEMU_RUN: ${{ inputs.qemu_run }} VARS: ${{ inputs.vars }} + # GitHub reads a workflow command (::error::) only at the start of a line, where Task's + # prefixed output puts the task's name. + TASK_OUTPUT: interleaved steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -101,39 +104,14 @@ jobs: go-version-file: go.mod cache: false - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - - name: Unpack the release - run: | - set -euo pipefail - if [ -z "$RELEASE" ]; then - RELEASE=$(gh release list -R "$GITHUB_REPOSITORY" --exclude-drafts --exclude-pre-releases --limit 1 --json tagName -q '.[0].tagName') - fi - rm -rf _output/lab - mkdir -p _output/lab/tmp - gh release download "$RELEASE" -R "$GITHUB_REPOSITORY" -p '*.tar.gz' -D _output/lab - tar -xzf _output/lab/*.tar.gz -C _output/lab - { - echo "RELEASE=$RELEASE" - echo "SPIN_MACHINE_OUTPUT=$PWD/_output/lab/spin-machine-${RELEASE}-linux-x86_64/usr/share/spin-stack" - # On disk: the overlays and memory files go here, gigabytes a tmpfs /tmp holds in RAM. - echo "TMPDIR=$PWD/_output/lab/tmp" - } >> "$GITHUB_ENV" + run: go tool task lab:unpack # Another build to compare: a Kernel run's vmlinux (B, and C beside it) or a QEMU run's # QEMU and firmware. qemu.yml and kernel.yml build any branch on dispatch. - name: Fetch the builds to compare if: inputs.kernel_run != '' || inputs.kernel_run_c != '' || inputs.qemu_run != '' - run: | - set -euo pipefail - fetch() { # run, artifact pattern, directory - [[ "$1" =~ ^[0-9]+$ ]] || { echo "::error::a run id is a number, got: $1"; exit 1; } - gh run download "$1" -R "$GITHUB_REPOSITORY" -p "$2" -D "$3" - } - if [ -n "$KERNEL_RUN" ]; then fetch "$KERNEL_RUN" 'vmlinux-*' _output/lab/kernel-b; fi - if [ -n "$KERNEL_RUN_C" ]; then fetch "$KERNEL_RUN_C" 'vmlinux-*' _output/lab/kernel-c; fi - if [ -n "$QEMU_RUN" ]; then fetch "$QEMU_RUN" 'qemu-*-linux-amd64' _output/lab/qemu-b; fi + run: go tool task lab:fetch # beside: the build is booted interleaved with the release's own - SPIN_KERNEL_B and # SPIN_KERNEL_C for a kernel, and for QEMU a second release tree, SPIN_MACHINE_OUTPUT_B, @@ -145,94 +123,23 @@ jobs: if: inputs.kernel_run != '' || inputs.kernel_run_c != '' || inputs.qemu_run != '' env: VARIANT: ${{ inputs.variant }} - run: | - set -euo pipefail - one() { # the one file under $1 whose path matches $2 - f=$(find "$1" -path "$2" -type f | head -1) - [ -n "$f" ] || { echo "::error::$1 has no $2"; exit 1; } - echo "$PWD/$f" - } - b=$PWD/_output/lab/release-b - tree_b() { [ -d "$b" ] || cp -as "$SPIN_MACHINE_OUTPUT" "$b"; } - if [ -n "$KERNEL_RUN" ]; then - k=$(one _output/lab/kernel-b '*/vmlinux') - if [ "$VARIANT" = instead ]; then - tree_b; rm -f "$b/kernel/vmlinux"; install -m 0644 "$k" "$b/kernel/vmlinux" - else - echo "SPIN_KERNEL_B=$k" >> "$GITHUB_ENV" - fi - fi - if [ -n "$KERNEL_RUN_C" ]; then - [ "$VARIANT" = beside ] || { echo "::error::kernel_run_c is a third kernel beside the release, not one to boot instead"; exit 1; } - echo "SPIN_KERNEL_C=$(one _output/lab/kernel-c '*/vmlinux')" >> "$GITHUB_ENV" - fi - if [ -n "$QEMU_RUN" ]; then - q=$(one _output/lab/qemu-b '*/bin/qemu-system-x86_64') - tree_b; rm -rf "$b/bin/qemu-system-x86_64" "$b/qemu" - install -m 0755 "$q" "$b/bin/qemu-system-x86_64" - cp -r "$(dirname "$(dirname "$q")")/qemu" "$b/qemu" - [ "$VARIANT" = instead ] || echo "SPIN_MACHINE_OUTPUT_B=$b" >> "$GITHUB_ENV" - fi - if [ "$VARIANT" = instead ]; then echo "SPIN_MACHINE_OUTPUT=$b" >> "$GITHUB_ENV"; fi + run: go tool task lab:place - name: Take the variables - run: | - set -euo pipefail - IFS=';' read -ra pairs <<< "$VARS" - for pair in "${pairs[@]}"; do - pair="${pair#"${pair%%[![:space:]]*}"}" - pair="${pair%"${pair##*[![:space:]]}"}" - [ -z "$pair" ] && continue - key="${pair%%=*}" - [[ "$pair" == *=* && "$key" =~ ^(REPS|TOP|GAP|ONLY|FLAGS|CPUS|MEMORY_MIB|DEBUG|FILE_MB|CACHE_TIMEOUT_S|GRAPH_[A-Z_]+|SHARE_[A-Z_]+|SPIN_[A-Z0-9_]+)$ ]] || - { echo "::error::not a variable this workflow passes on: $pair"; exit 1; } - case "$key" in - SPIN_MACHINE_OUTPUT|SPIN_MACHINE_OUTPUT_B|SPIN_KERNEL_B|SPIN_KERNEL_C) echo "::error::$key is set by this workflow"; exit 1 ;; - esac - echo "$pair" >> "$GITHUB_ENV" - done + run: go tool task lab:vars - name: What this run is env: VARIANT: ${{ inputs.variant }} - run: | - { - echo "### $EXPERIMENT on $RUNNER_NAME" - echo - echo "- release: $RELEASE" - echo "- kernel B: ${KERNEL_RUN:+run }${KERNEL_RUN:-none}" - echo "- kernel C: ${KERNEL_RUN_C:+run }${KERNEL_RUN_C:-none}" - echo "- QEMU B: ${QEMU_RUN:+run }${QEMU_RUN:-none}" - if [ -n "$KERNEL_RUN$KERNEL_RUN_C$QEMU_RUN" ]; then echo "- booted: $VARIANT the release"; fi - echo "- vars: ${VARS:-none}" - echo "- CPU: $(sed -n 's/^model name\s*: //p' /proc/cpuinfo | head -1), $(nproc) CPUs" - echo "- load: $(cut -d' ' -f1-3 /proc/loadavg)" - if sudo -n true 2>/dev/null; then echo "- sudo -n: yes"; else echo "- sudo -n: **no** (targets that edit an overlay skip)"; fi - } | tee -a "$GITHUB_STEP_SUMMARY" - [ -r /dev/kvm ] && [ -w /dev/kvm ] || { echo "::error::no usable /dev/kvm"; exit 1; } + run: go tool task lab:about # report writes its JSON where OUT says; the others print their tables through t.Log. - # A skipped test exits 0, and a green run that measured nothing reads as a result, so a - # skip fails the run with the test's reason. - name: Run the experiment - run: | - set -o pipefail - task "$EXPERIMENT" OUTPUT_DIR="$SPIN_MACHINE_OUTPUT" OUT="$PWD/_output/lab/report.json" 2>&1 | tee _output/lab/lab.log - if grep -q -- '--- SKIP' _output/lab/lab.log; then - echo "::error::the experiment skipped: $(grep -B1 -- '--- SKIP' _output/lab/lab.log | head -1 | sed 's/^.*_test.go:[0-9]*: //')" - exit 1 - fi + run: go tool task lab:run - name: What it found if: always() - run: | - [ -f _output/lab/lab.log ] || exit 0 - { - echo - echo '```' - grep -E '^\s{4}\S' _output/lab/lab.log | sed 's/^ //' | tail -300 - echo '```' - } >> "$GITHUB_STEP_SUMMARY" + run: go tool task lab:found - name: Keep the log if: always() diff --git a/.github/workflows/osv.yml b/.github/workflows/osv.yml index 49051e3..af43128 100644 --- a/.github/workflows/osv.yml +++ b/.github/workflows/osv.yml @@ -31,20 +31,17 @@ jobs: go-version-file: go.mod cache: true - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - - name: Install cosign uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Scan the newest release env: GH_TOKEN: ${{ github.token }} - run: task osv + run: go tool task osv # One issue a package, which a release closes once it has no finding in it; hack/osvissues # says why a package and not a finding. - name: Bring the issues to the findings env: GH_TOKEN: ${{ github.token }} - run: go run ./hack/osvissues -release "$(gh release view --json tagName -q .tagName)" -findings _output/osv.tsv + run: go tool task osv:issues diff --git a/.github/workflows/qemu.yml b/.github/workflows/qemu.yml index b089983..b6327ce 100644 --- a/.github/workflows/qemu.yml +++ b/.github/workflows/qemu.yml @@ -67,10 +67,7 @@ jobs: id: touches env: BASE: ${{ github.event.pull_request.base.sha || github.event.before }} - run: | - build=$(hack/touches "$BASE" alpine qemu debian debian-snapshot qboot -- \ - qemu go.mod .github/workflows/qemu.yml) - echo "build=${build}" | tee -a "$GITHUB_OUTPUT" + run: go tool task touches -- alpine qemu debian debian-snapshot qboot -- qemu go.mod .github/workflows/qemu.yml build: needs: changed @@ -85,9 +82,6 @@ jobs: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - # For the acceptance check at the end, which is a Go test. The runner's own Go is # whatever the image happens to carry, and go.mod names the one this builds with. - name: Set up Go @@ -135,11 +129,13 @@ jobs: # to bump is how CI and production end up on different QEMUs. - name: Read the pinned QEMU version id: qemu - run: echo "version=$(go tool versions version qemu)" >> "$GITHUB_OUTPUT" + run: go tool task qemu:version - name: Build QEMU and verify what came out - run: | - CACHE_EXPORT=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} CACHE_BACKEND=gha task qemu:build QEMU_JOBS=4 + env: + CACHE_BACKEND: gha + CACHE_EXPORT: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + run: go tool task qemu:build QEMU_JOBS=4 # vhost-vsock is a kernel module, and the machine's vsock device cannot be created # without /dev/vhost-vsock. The runner has the node and gives the user no access to @@ -148,11 +144,7 @@ jobs: # keeps the device line and drops the requirement, and a runner without it is told # what went unchecked instead of being shown a pass. - name: Load vhost_vsock - run: | - # The device first: a kernel that builds it in - Spin OS's, which has no modules - has - # it from boot, and modprobe there has nothing to find. - { [ -c /dev/vhost-vsock ] || sudo modprobe vhost_vsock; } && sudo chmod 0666 /dev/vhost-vsock || - echo "no vhost_vsock here; the check will name vhost-vsock-pci as unchecked" + run: go tool task vsock # The other half of what a device allowlist decides. `task qemu:build` ends in # qemu:verify, which asks this binary which accelerators and firmware files it has; @@ -164,7 +156,7 @@ jobs: # lane that catches a change made on *this* side, before the binary it would break is # published at all. - name: Check the built QEMU accepts the machine's arguments - run: task verify:args + run: go tool task verify:args # What it produced, and whether it still offers the machine type every checkpoint is # saved on, on the run's summary. A changed QEMU binary is a new emulator of the same @@ -172,13 +164,7 @@ jobs: # checkpoint the released QEMU saved resumes on it is boot:compat's to say, on the KVM # runner (compat.yml). - name: What this QEMU is - run: | - set -euo pipefail - { - echo "qemu sha256: $(sha256sum _output/bin/qemu-system-x86_64 | cut -d' ' -f1)" - echo "qboot.bin: $(stat -c%s _output/qemu/qboot.bin) bytes" - go run ./hack/machinetype check -qemu _output/bin/qemu-system-x86_64 - } | tee -a "$GITHUB_STEP_SUMMARY" + run: go tool task qemu:summary - name: Upload the extracted binaries uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 @@ -208,15 +194,4 @@ jobs: # runner's sticky disk already holds these layers. - name: Publish the runtime image if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - run: | - docker buildx build \ - --file qemu/Dockerfile \ - --target runtime \ - --platform linux/amd64 \ - --cache-from type=gha,scope=qemu \ - $(go tool versions args alpine qemu debian debian-snapshot qboot) \ - --build-arg JOBS=4 \ - --label org.opencontainers.image.source=https://github.com/${{ github.repository }} \ - --tag ghcr.io/${{ github.repository }}/qemu:${{ steps.qemu.outputs.version }} \ - --push \ - . + run: go tool task qemu:publish diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8e451f4..6a48f93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,6 +56,10 @@ jobs: timeout-minutes: 180 outputs: version: ${{ steps.version.outputs.version }} + env: + # GitHub reads a workflow command (::error::) only at the start of a line, where Task's + # prefixed output puts the task's name. + TASK_OUTPUT: interleaved steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -70,9 +74,6 @@ jobs: go-version-file: go.mod cache: true - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 - # Its own sticky disk, and not one of the lanes'. This job builds all four artefacts, so # it would want every lane's disk at once and can only have one — and a release can # overlap a lane, which sharing a key would make them contend for. The BuildKit scopes it @@ -103,28 +104,7 @@ jobs: id: version env: INPUT_VERSION: ${{ inputs.version }} - run: | - set -euo pipefail - if [ -n "${INPUT_VERSION:-}" ]; then - version="$INPUT_VERSION" - origin="given by the caller" - else - day=$(date -u +%Y%m%d) - # Count what today already has. `git tag -l` on a fetch-depth:0 checkout sees - # every tag; the sequence is two digits so that v20260909.02 sorts after .01 - # and both sort before v20260910.01, as strings, everywhere. - taken=$(git tag -l "v${day}.*" | wc -l) - version=$(printf 'v%s.%02d' "$day" "$((taken + 1))") - origin="generated for today (${taken} already taken)" - fi - - case "$version" in - v[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].[0-9][0-9]) ;; - *) echo "::error::'$version' is not vYYYYMMDD.NN" >&2; exit 1 ;; - esac - - echo "version=$version" >> "$GITHUB_OUTPUT" - echo "Releasing $version — $origin" + run: go tool task release:version # `task release` builds all four artefacts and packs them, ending in hack/release, # which refuses to produce a tarball with anything missing. A release that installs @@ -140,7 +120,7 @@ jobs: # Reads what main's lanes exported and writes nothing back: a release is built once, and # the next one reads main's newer cache, not this. See CACHE_EXPORT in Taskfile.yml. CACHE_EXPORT: "false" - run: task release QEMU_JOBS=4 KERNEL_NPROC=4 + run: go tool task release QEMU_JOBS=4 KERNEL_NPROC=4 # The machine's identity, and what it costs whoever holds checkpoints. # @@ -158,50 +138,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} VERSION: ${{ steps.version.outputs.version }} - run: | - set -euo pipefail - name="spin-machine-${VERSION}-linux-x86_64" - manifest="_output/release/${name}/usr/share/spin-stack/machine.env" - cat "$manifest" - - # The release before this one, for both the verdict and the notes: the newest published - # one that is not this version, so a re-run of a version that already published compares - # against its predecessor rather than against itself. A listing that fails fails the - # step - read as "no releases", it would announce a first release that is not one. - releases=$(gh release list -R "$GITHUB_REPOSITORY" --limit 30 --json tagName -q '.[].tagName') - previous=$(printf '%s\n' "$releases" | grep -vFx -- "$VERSION" | head -1 || true) - - if [ -n "$previous" ]; then - # machine.env's lines are the script's key=value arguments, as they are. - # shellcheck disable=SC2046 - REFERENCE="$previous" hack/fingerprint-diff $(grep '_sha256=' "$manifest") > /tmp/verdict.md - # What reached the machine since: the commits by the part they changed, the pins - # that moved, the kernel options and the patches, read from git. - go run ./hack/releasenotes -from "$previous" -to HEAD > /tmp/changes.md - else - echo "Nothing to compare against: this is the first published release." > /tmp/verdict.md - echo "The first release: nothing before it to say what changed against." > /tmp/changes.md - fi - # Whether the QEMU shipped offers a machine type newer than the one every checkpoint is - # saved on: said, never acted on (machine.MachineType). - offer=$(go run ./hack/machinetype check -qemu "_output/release/${name}/usr/share/spin-stack/bin/qemu-system-x86_64") - if [ -n "$offer" ]; then printf '\n%s\n' "$offer" >> /tmp/verdict.md; fi - cat /tmp/verdict.md - cat /tmp/changes.md - - { - echo 'notes<> "$GITHUB_OUTPUT" + run: go tool task release:notes # v4 is the one that installs cosign v3. Dependabot moves this pin like every other `uses:`. - name: Install cosign @@ -213,51 +150,22 @@ jobs: - name: Write the provenance env: VERSION: ${{ steps.version.outputs.version }} - run: go tool provenance -version "${VERSION}" -out _output/provenance.json + run: go tool task release:provenance # Each file is signed and attested, then each bundle checked against the identity that made # it, file by file: a bundle nothing verifies is a step that can quietly stop working. - # - # An attestation is checked by the file's digest, not the file: verify-blob-attestation reads - # a blob whole and refuses one over COSIGN_MAX_ATTACHMENT_SIZE (128 MiB), and the tarball is - # 338 MB (v20261013.01's run failed there). The digest is what the in-toto subject names. - name: Sign and attest what the release offers env: IDENTITY: ${{ github.server_url }}/${{ github.repository }}/.github/workflows/release.yml@${{ github.ref }} - run: | - set -euo pipefail - attested() { - cosign verify-blob-attestation --type "$1" --bundle "$2" \ - --digest "$(sha256sum "$3" | cut -d' ' -f1)" --digestAlg sha256 \ - --certificate-identity "${IDENTITY}" \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com - } - for f in _output/release/*.tar.gz _output/release/*.tar.gz.sha256 _output/release/machine.env _output/release/*.cdx.json; do - cosign sign-blob --yes --bundle "${f}.sigstore.json" "${f}" > /dev/null - cosign attest-blob --yes --type slsaprovenance1 --predicate _output/provenance.json \ - --bundle "${f}.provenance.sigstore.json" "${f}" > /dev/null - cosign verify-blob --bundle "${f}.sigstore.json" --certificate-identity "${IDENTITY}" \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com "${f}" - attested slsaprovenance1 "${f}.provenance.sigstore.json" "${f}" - done - # The tarball's SBOM (hack/release), attested over it: what it is made of, by the - # workflow that built it. The same SBOM is inside it, at usr/share/spin-stack/sbom. - for f in _output/release/*.tar.gz; do - cosign attest-blob --yes --type cyclonedx --predicate "${f%.tar.gz}.cdx.json" \ - --bundle "${f}.cdx.sigstore.json" "${f}" > /dev/null - attested cyclonedx "${f}.cdx.sigstore.json" "${f}" - done - go tool attestgate files -require provenance _output/release - go tool attestgate files -require cdx -except '*.sha256,machine.env,*.cdx.json' _output/release + run: go tool task release:sign # Tagged here, after the files are signed and before they are published, so that the next # run's count of "tags already taken today" is right and the tarball has a commit behind it. # A version tagged already is refused here: git push does not move a tag. - name: Tag the commit - run: | - set -euo pipefail - git tag "${{ steps.version.outputs.version }}" - git push origin "${{ steps.version.outputs.version }}" + env: + VERSION: ${{ steps.version.outputs.version }} + run: go tool task release:tag - name: Publish uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 diff --git a/.github/workflows/report.yml b/.github/workflows/report.yml index e4fc574..3c7e59e 100644 --- a/.github/workflows/report.yml +++ b/.github/workflows/report.yml @@ -41,6 +41,9 @@ jobs: env: GH_TOKEN: ${{ github.token }} VERSION: ${{ inputs.version }} + # GitHub reads a workflow command (::error::) only at the start of a line, where Task's + # prefixed output puts the task's name. + TASK_OUTPUT: interleaved steps: # The harness from the ref asked for - the release's own tag when release.yml calls - and, # run by hand, from where the run was started: a release older than the report has none. @@ -49,29 +52,6 @@ jobs: with: ref: ${{ inputs.ref || github.sha }} - # What this runner can do, said before anything is measured: a row the report skips is one - # this host lacks the device for, and the summary says which before the report does. - - name: What this runner has - run: | - { - echo "### Runner $RUNNER_NAME" - echo - for dev in /dev/kvm /dev/vhost-vsock; do - if [ -r "$dev" ] && [ -w "$dev" ]; then echo "- $dev: usable"; else echo "- $dev: **not usable** ($(ls -l "$dev" 2>&1))"; fi - done - if sudo -n true 2>/dev/null; then - echo "- sudo -n: yes" - sudo -n modprobe nbd max_part=8 2>/dev/null || true - for _ in $(seq 50); do [ -e /dev/nbd0 ] && break; sleep 0.02; done - if [ -e /dev/nbd0 ]; then echo "- /dev/nbd0: present (image variants and the echo login run)"; else echo "- /dev/nbd0: **missing** (image variants are skipped, the login is agetty's)"; fi - else - echo "- sudo -n: **no** (image variants are skipped, the login is agetty's)" - fi - echo "- gh: $(command -v gh || echo '**missing**')" - echo "- CPU: $(sed -n 's/^model name\s*: //p' /proc/cpuinfo | head -1), $(nproc) CPUs" - } | tee -a "$GITHUB_STEP_SUMMARY" - [ -r /dev/kvm ] && [ -w /dev/kvm ] || { echo "::error::no usable /dev/kvm: nothing here can be measured"; exit 1; } - # No Actions cache: this runner keeps Go's module and build caches on its own disk, and # the cache service only stored another copy per branch, against the repository's limit. - name: Set up Go @@ -80,43 +60,23 @@ jobs: go-version-file: go.mod cache: false - - name: Set up Task - uses: go-task/setup-task@a00fbb05ce67b35648be3c78cbc9fd85354c757e # v2.2.0 + # What this runner can do, said before anything is measured: a row the report skips is one + # this host lacks the device for, and the summary says which before the report does. + - name: What this runner has + run: go tool task report:runner # The tarball as a consumer gets it, and not a tree a build left: what is measured is what # was published. - name: Unpack the release - run: | - set -euo pipefail - rm -rf _output/report - mkdir -p _output/report - gh release download "$VERSION" -R "$GITHUB_REPOSITORY" -p '*.tar.gz' -D _output/report - tar -xzf _output/report/*.tar.gz -C _output/report - echo "RELEASE_TREE=$PWD/_output/report/spin-machine-${VERSION}-linux-x86_64/usr/share/spin-stack" >> "$GITHUB_ENV" + run: go tool task report:unpack - name: Measure the feature matrix - run: task report OUTPUT_DIR="$RELEASE_TREE" OUT="$PWD/_output/report/report.json" + run: go tool task report OUTPUT_DIR="$RELEASE_TREE" OUT="$PWD/_output/report/report.json" # Against the newest release before this one that has a report. The first release with # a report has nothing to compare with, and says so. - name: Compare with the release before it - run: | - set -euo pipefail - cd _output/report - previous="" - for tag in $(gh release list -R "$GITHUB_REPOSITORY" --limit 30 --json tagName -q '.[].tagName'); do - [ "$tag" = "$VERSION" ] && continue - if gh release download "$tag" -R "$GITHUB_REPOSITORY" -p report.json -O previous.json 2>/dev/null; then - previous="$tag" - break - fi - done - if [ -n "$previous" ]; then - "$RELEASE_TREE/bin/spin-machine" compare --old previous.json --new report.json > compare.md - else - echo "No earlier release published a report.json to compare the feature matrix with." > compare.md - fi - cat compare.md >> "$GITHUB_STEP_SUMMARY" + run: go tool task report:compare - name: Keep the report uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 @@ -129,10 +89,4 @@ jobs: - name: Publish the report, and what moved if: inputs.publish - run: | - set -euo pipefail - cd _output/report - gh release upload "$VERSION" -R "$GITHUB_REPOSITORY" report.json --clobber - gh release view "$VERSION" -R "$GITHUB_REPOSITORY" --json body -q .body > notes.md - { echo; cat compare.md; } >> notes.md - gh release edit "$VERSION" -R "$GITHUB_REPOSITORY" --notes-file notes.md + run: go tool task report:publish diff --git a/README.md b/README.md index f065b78..e02e8b8 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,9 @@ task fingerprint # this machine's identity task release # one tarball, one version ``` -`task` is [taskfile.dev](https://taskfile.dev), not GNU task. The part builds run in -containers (`qemu/Dockerfile`, `kernel/Dockerfile`, `e2fsprogs/Dockerfile`, +`task` is [taskfile.dev](https://taskfile.dev), not GNU task, at the version go.mod pins: +`go tool task build` runs it with nothing installed, and is what CI runs. The part builds +run in containers (`qemu/Dockerfile`, `kernel/Dockerfile`, `e2fsprogs/Dockerfile`, `image/Dockerfile`), so a container engine is needed to build; a boot is not, and neither is `task build` — a consumer points `--release` at an unpacked release tree instead. A boot needs `/dev/kvm` readable and writable by whoever runs it, the same requirement diff --git a/Taskfile.yml b/Taskfile.yml index 7ae56b0..0c176fb 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -123,7 +123,7 @@ tasks: default: cmds: - - task --list + - '{{.TASK_EXE}} --list' # ========================================================================== # Build @@ -209,7 +209,7 @@ tasks: - cmd: 'echo "OK: go vet"' # `task --list` parses every included Taskfile, so a syntax error or a name defined # twice fails here rather than in whichever lane first called it. - - task --list > /dev/null + - '{{.TASK_EXE}} --list > /dev/null' - cmd: 'echo "OK: the Taskfiles parse"' - | set -euo pipefail @@ -219,12 +219,15 @@ tasks: done echo "OK: the shell scripts parse" # go-tools' gates, at the version go.mod pins: every goroutine held to a context, no test - # that cannot fail, every path and task AGENTS.md and CLAUDE.md name resolves, and every - # mutate-exempt reason covers an edit mutate makes. + # that cannot fail, every path and task AGENTS.md and CLAUDE.md name resolves, every + # mutate-exempt reason covers an edit mutate makes, every workflow step is one task, and + # pnpm is the one package manager, installing through Socket Firewall. - go tool ctxlife - go tool testquality ./... - go tool refs - go tool mutate -stale-exempts + - go tool taskgate + - go tool sfw check - task: lint:workflows lint:workflows: @@ -246,11 +249,70 @@ tasks: mutate: desc: >- Break what the change against BASE touched and fail on an edit no test refuses - (task mutate BASE=origin/main). - vars: - BASE: '{{.BASE | default "origin/main"}}' + (task mutate BASE=origin/main, the default). In CI the base is what the change is to: a + pull request's target branch, or on a push what the push replaced (BEFORE). + cmds: + - | + set -euo pipefail + base='{{.BASE}}' + if [ -z "$base" ] && [ "${GITHUB_ACTIONS:-}" = true ]; then + if [ "$GITHUB_EVENT_NAME" = pull_request ]; then + base="origin/$GITHUB_BASE_REF" + else + base="${BEFORE:-}" + fi + # A push that created its branch has no commit before it. + git rev-parse --verify "$base^{commit}" >/dev/null 2>&1 || base=HEAD~1 + fi + go tool mutate -base "${base:-origin/main}" -max 2000 + + coverage: + desc: >- + What `task test` covered, function by function: on the run's summary in CI, on stdout + here, and as coverage.html. + cmds: + - | + set -e + summary=${GITHUB_STEP_SUMMARY:-/dev/stdout} + if [ ! -f coverage.out ]; then + echo "coverage.out was not produced; the tests may have failed before coverage ran." >> "$summary" + exit 0 + fi + { + echo "## Go coverage" + echo + echo "**$(go tool cover -func=coverage.out | awk '/^total:/ {print $3}')** total" + echo + echo '
Function detail' + echo + echo '```' + go tool cover -func=coverage.out + echo '```' + echo '
' + } >> "$summary" + go tool cover -html=coverage.out -o coverage.html + + touches: + desc: >- + Whether the commits since BASE can change what one part builds, as build=true or + build=false, on the step's outputs in CI (task touches BASE= -- ... -- + ...; hack/touches says how it decides). + cmds: + - | + set -e + build=$(hack/touches "${BASE:-}" {{.CLI_ARGS}}) + echo "build=${build}" | tee -a "${GITHUB_OUTPUT:-/dev/null}" + + vsock: + desc: >- + Make /dev/vhost-vsock usable by this user, so verify:args can create the machine's vsock + device. Without it, says so rather than failing: verify:args names the device unchecked. cmds: - - go tool mutate -base {{.BASE}} -max 2000 + # The device first: a kernel that builds it in - Spin OS's, which has no modules - has it + # from boot, and modprobe there has nothing to find. + - | + { [ -c /dev/vhost-vsock ] || sudo modprobe vhost_vsock; } && sudo chmod 0666 /dev/vhost-vsock || + echo "no vhost_vsock here; the check will name vhost-vsock-pci as unchecked" verify:args: desc: >- @@ -316,6 +378,14 @@ tasks: "$dir/osv.json" | sort -u > _output/osv.tsv echo "$tag: $(wc -l < _output/osv.tsv) finding(s), in _output/osv.tsv" + osv:issues: + desc: >- + Bring the issues to what task osv found: one open for each package with findings, closed + once the newest release has none (hack/osvissues says why a package and not a finding). + Needs gh. + cmds: + - go run ./hack/osvissues -release "$(gh release view --json tagName -q .tagName)" -findings _output/osv.tsv + release: desc: Build everything and pack one versioned tarball. cmds: @@ -325,6 +395,137 @@ tasks: # that could disagree with what was built. - OUTPUT_DIR="{{.OUTPUT_ABS}}" hack/release + # What release.yml does around `task release`, in its order. The version and the identity a file + # is signed as are the workflow's to know, and come in its environment. + + release:version: + desc: >- + The version a release is: INPUT_VERSION, or a new one for today, counted from the tags + today already has. On the step's outputs in CI. + cmds: + - | + set -euo pipefail + if [ -n "${INPUT_VERSION:-}" ]; then + version="$INPUT_VERSION" + origin="given by the caller" + else + day=$(date -u +%Y%m%d) + # Count what today already has. `git tag -l` on a fetch-depth:0 checkout sees + # every tag; the sequence is two digits so that v20260909.02 sorts after .01 + # and both sort before v20260910.01, as strings, everywhere. + taken=$(git tag -l "v${day}.*" | wc -l) + version=$(printf 'v%s.%02d' "$day" "$((taken + 1))") + origin="generated for today (${taken} already taken)" + fi + + case "$version" in + v[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].[0-9][0-9]) ;; + *) echo "::error::'$version' is not vYYYYMMDD.NN" >&2; exit 1 ;; + esac + + echo "version=$version" >> "${GITHUB_OUTPUT:-/dev/stdout}" + echo "Releasing $version — $origin" + + release:notes: + desc: >- + The notes of the release VERSION built in _output/release: what changed since the release + before it, whether its machine is that one's (hack/fingerprint-diff), and its machine.env. + On the step's outputs in CI. Needs gh. + cmds: + - | + set -euo pipefail + name="spin-machine-${VERSION}-linux-x86_64" + manifest="_output/release/${name}/usr/share/spin-stack/machine.env" + cat "$manifest" + + # The release before this one, for both the verdict and the notes: the newest published + # one that is not this version, so a re-run of a version that already published compares + # against its predecessor rather than against itself. A listing that fails fails the + # step - read as "no releases", it would announce a first release that is not one. + releases=$(gh release list -R "$GITHUB_REPOSITORY" --limit 30 --json tagName -q '.[].tagName') + previous=$(printf '%s\n' "$releases" | grep -vFx -- "$VERSION" | head -1 || true) + + if [ -n "$previous" ]; then + # machine.env's lines are the script's key=value arguments, as they are. + # shellcheck disable=SC2046 + REFERENCE="$previous" hack/fingerprint-diff $(grep '_sha256=' "$manifest") > /tmp/verdict.md + # What reached the machine since: the commits by the part they changed, the pins + # that moved, the kernel options and the patches, read from git. + go run ./hack/releasenotes -from "$previous" -to HEAD > /tmp/changes.md + else + echo "Nothing to compare against: this is the first published release." > /tmp/verdict.md + echo "The first release: nothing before it to say what changed against." > /tmp/changes.md + fi + # Whether the QEMU shipped offers a machine type newer than the one every checkpoint is + # saved on: said, never acted on (machine.MachineType). + offer=$(go run ./hack/machinetype check -qemu "_output/release/${name}/usr/share/spin-stack/bin/qemu-system-x86_64") + if [ -n "$offer" ]; then printf '\n%s\n' "$offer" >> /tmp/verdict.md; fi + cat /tmp/verdict.md + cat /tmp/changes.md + + { + echo 'notes<> "${GITHUB_OUTPUT:-/dev/stdout}" + + release:provenance: + desc: >- + Who built the release VERSION and from what - this commit, every pin in versions.yaml - as + SLSA provenance, in _output/provenance.json. + cmds: + - go tool provenance -version "${VERSION}" -out _output/provenance.json + + release:sign: + desc: >- + Sign and attest every file of _output/release as IDENTITY, the workflow at its ref, and + check each bundle against it. Needs cosign and an OIDC token, so it is release.yml's. + # An attestation is checked by the file's digest, not the file: verify-blob-attestation reads + # a blob whole and refuses one over COSIGN_MAX_ATTACHMENT_SIZE (128 MiB), and the tarball is + # 338 MB (v20261013.01's run failed there). The digest is what the in-toto subject names. + cmds: + - | + set -euo pipefail + attested() { + cosign verify-blob-attestation --type "$1" --bundle "$2" \ + --digest "$(sha256sum "$3" | cut -d' ' -f1)" --digestAlg sha256 \ + --certificate-identity "${IDENTITY}" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com + } + for f in _output/release/*.tar.gz _output/release/*.tar.gz.sha256 _output/release/machine.env _output/release/*.cdx.json; do + cosign sign-blob --yes --bundle "${f}.sigstore.json" "${f}" > /dev/null + cosign attest-blob --yes --type slsaprovenance1 --predicate _output/provenance.json \ + --bundle "${f}.provenance.sigstore.json" "${f}" > /dev/null + cosign verify-blob --bundle "${f}.sigstore.json" --certificate-identity "${IDENTITY}" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com "${f}" + attested slsaprovenance1 "${f}.provenance.sigstore.json" "${f}" + done + # The tarball's SBOM (hack/release), attested over it: what it is made of, by the + # workflow that built it. The same SBOM is inside it, at usr/share/spin-stack/sbom. + for f in _output/release/*.tar.gz; do + cosign attest-blob --yes --type cyclonedx --predicate "${f%.tar.gz}.cdx.json" \ + --bundle "${f}.cdx.sigstore.json" "${f}" > /dev/null + attested cyclonedx "${f}.cdx.sigstore.json" "${f}" + done + go tool attestgate files -require provenance _output/release + go tool attestgate files -require cdx -except '*.sha256,machine.env,*.cdx.json' _output/release + + release:tag: + desc: Tag this commit VERSION and push the tag. A version tagged already is refused, since git push does not move a tag. + cmds: + - | + set -euo pipefail + git tag "$VERSION" + git push origin "$VERSION" + # ========================================================================== # Trying the machine # ========================================================================== @@ -426,6 +627,223 @@ tasks: SPIN_REPORT_ONLY='{{.ONLY}}' SPIN_REPORT_FLAGS='{{.FLAGS}}' REPS={{.REPS}} go test ./boot/ -run '^TestReport$' -count=1 -v -timeout 6h + # ========================================================================== + # The KVM runner: what lab.yml and report.yml do around a target + # ========================================================================== + # + # In their order. What the dispatch asked for comes in the job's environment (RELEASE, + # EXPERIMENT, KERNEL_RUN, KERNEL_RUN_C, QEMU_RUN, VARIANT, VARS; VERSION for a report), and what + # one step finds reaches the next through $GITHUB_ENV. + + lab:unpack: + desc: The release RELEASE, or the newest, unpacked into _output/lab as the tree the experiment boots. Needs gh. + cmds: + - | + set -euo pipefail + if [ -z "$RELEASE" ]; then + RELEASE=$(gh release list -R "$GITHUB_REPOSITORY" --exclude-drafts --exclude-pre-releases --limit 1 --json tagName -q '.[0].tagName') + fi + rm -rf _output/lab + mkdir -p _output/lab/tmp + gh release download "$RELEASE" -R "$GITHUB_REPOSITORY" -p '*.tar.gz' -D _output/lab + tar -xzf _output/lab/*.tar.gz -C _output/lab + { + echo "RELEASE=$RELEASE" + echo "SPIN_MACHINE_OUTPUT=$PWD/_output/lab/spin-machine-${RELEASE}-linux-x86_64/usr/share/spin-stack" + # On disk: the overlays and memory files go here, gigabytes a tmpfs /tmp holds in RAM. + echo "TMPDIR=$PWD/_output/lab/tmp" + } >> "${GITHUB_ENV:-/dev/stdout}" + + lab:fetch: + desc: The builds to compare, from the runs KERNEL_RUN, KERNEL_RUN_C and QEMU_RUN name, into _output/lab. Needs gh. + cmds: + - | + set -euo pipefail + fetch() { # run, artifact pattern, directory + [[ "$1" =~ ^[0-9]+$ ]] || { echo "::error::a run id is a number, got: $1"; exit 1; } + gh run download "$1" -R "$GITHUB_REPOSITORY" -p "$2" -D "$3" + } + if [ -n "$KERNEL_RUN" ]; then fetch "$KERNEL_RUN" 'vmlinux-*' _output/lab/kernel-b; fi + if [ -n "$KERNEL_RUN_C" ]; then fetch "$KERNEL_RUN_C" 'vmlinux-*' _output/lab/kernel-c; fi + if [ -n "$QEMU_RUN" ]; then fetch "$QEMU_RUN" 'qemu-*-linux-amd64' _output/lab/qemu-b; fi + + lab:place: + desc: >- + Put the fetched builds where the experiment boots them: beside the release's (VARIANT=beside) + or in place of it (VARIANT=instead). + cmds: + - | + set -euo pipefail + env=${GITHUB_ENV:-/dev/stdout} + one() { # the one file under $1 whose path matches $2 + f=$(find "$1" -path "$2" -type f | head -1) + [ -n "$f" ] || { echo "::error::$1 has no $2"; exit 1; } + echo "$PWD/$f" + } + b=$PWD/_output/lab/release-b + tree_b() { [ -d "$b" ] || cp -as "$SPIN_MACHINE_OUTPUT" "$b"; } + if [ -n "$KERNEL_RUN" ]; then + k=$(one _output/lab/kernel-b '*/vmlinux') + if [ "$VARIANT" = instead ]; then + tree_b; rm -f "$b/kernel/vmlinux"; install -m 0644 "$k" "$b/kernel/vmlinux" + else + echo "SPIN_KERNEL_B=$k" >> "$env" + fi + fi + if [ -n "$KERNEL_RUN_C" ]; then + [ "$VARIANT" = beside ] || { echo "::error::kernel_run_c is a third kernel beside the release, not one to boot instead"; exit 1; } + echo "SPIN_KERNEL_C=$(one _output/lab/kernel-c '*/vmlinux')" >> "$env" + fi + if [ -n "$QEMU_RUN" ]; then + q=$(one _output/lab/qemu-b '*/bin/qemu-system-x86_64') + tree_b; rm -rf "$b/bin/qemu-system-x86_64" "$b/qemu" + install -m 0755 "$q" "$b/bin/qemu-system-x86_64" + cp -r "$(dirname "$(dirname "$q")")/qemu" "$b/qemu" + [ "$VARIANT" = instead ] || echo "SPIN_MACHINE_OUTPUT_B=$b" >> "$env" + fi + if [ "$VARIANT" = instead ]; then echo "SPIN_MACHINE_OUTPUT=$b" >> "$env"; fi + + lab:vars: + desc: >- + VARS, `KEY=VALUE; KEY=VALUE`, for the experiment: only the names a target reads, so a typo + fails here rather than being ignored, and none of the ones lab:unpack and lab:place set. + cmds: + - | + set -euo pipefail + IFS=';' read -ra pairs <<< "$VARS" + for pair in "${pairs[@]}"; do + pair="${pair#"${pair%%[![:space:]]*}"}" + pair="${pair%"${pair##*[![:space:]]}"}" + [ -z "$pair" ] && continue + key="${pair%%=*}" + [[ "$pair" == *=* && "$key" =~ ^(REPS|TOP|GAP|ONLY|FLAGS|CPUS|MEMORY_MIB|DEBUG|FILE_MB|CACHE_TIMEOUT_S|GRAPH_[A-Z_]+|SHARE_[A-Z_]+|SPIN_[A-Z0-9_]+)$ ]] || + { echo "::error::not a variable this workflow passes on: $pair"; exit 1; } + case "$key" in + SPIN_MACHINE_OUTPUT|SPIN_MACHINE_OUTPUT_B|SPIN_KERNEL_B|SPIN_KERNEL_C) echo "::error::$key is set by this workflow"; exit 1 ;; + esac + echo "$pair" >> "${GITHUB_ENV:-/dev/stdout}" + done + + lab:about: + desc: What this lab run is and the host it runs on, on the run's summary in CI; fails without a usable /dev/kvm. + cmds: + - | + set -e + { + echo "### $EXPERIMENT on ${RUNNER_NAME:-$(hostname)}" + echo + echo "- release: $RELEASE" + echo "- kernel B: ${KERNEL_RUN:+run }${KERNEL_RUN:-none}" + echo "- kernel C: ${KERNEL_RUN_C:+run }${KERNEL_RUN_C:-none}" + echo "- QEMU B: ${QEMU_RUN:+run }${QEMU_RUN:-none}" + if [ -n "$KERNEL_RUN$KERNEL_RUN_C$QEMU_RUN" ]; then echo "- booted: $VARIANT the release"; fi + echo "- vars: ${VARS:-none}" + echo "- CPU: $(sed -n 's/^model name\s*: //p' /proc/cpuinfo | head -1), $(nproc) CPUs" + echo "- load: $(cut -d' ' -f1-3 /proc/loadavg)" + if sudo -n true 2>/dev/null; then echo "- sudo -n: yes"; else echo "- sudo -n: **no** (targets that edit an overlay skip)"; fi + } | tee -a "${GITHUB_STEP_SUMMARY:-/dev/null}" + [ -r /dev/kvm ] && [ -w /dev/kvm ] || { echo "::error::no usable /dev/kvm"; exit 1; } + + lab:run: + desc: >- + The experiment EXPERIMENT, on the tree SPIN_MACHINE_OUTPUT, logged to _output/lab/lab.log; + report writes its JSON to _output/lab/report.json. + # A skipped test exits 0, and a green run that measured nothing reads as a result, so a skip + # fails the run with the test's reason. + cmds: + - | + set -o pipefail + {{.TASK_EXE}} "$EXPERIMENT" OUTPUT_DIR="$SPIN_MACHINE_OUTPUT" OUT="$PWD/_output/lab/report.json" 2>&1 | tee _output/lab/lab.log + if grep -q -- '--- SKIP' _output/lab/lab.log; then + echo "::error::the experiment skipped: $(grep -B1 -- '--- SKIP' _output/lab/lab.log | head -1 | sed 's/^.*_test.go:[0-9]*: //')" + exit 1 + fi + + lab:found: + desc: What the experiment printed, from _output/lab/lab.log, on the run's summary in CI. + cmds: + - | + set -e + [ -f _output/lab/lab.log ] || exit 0 + { + echo + echo '```' + grep -E '^\s{4}\S' _output/lab/lab.log | sed 's/^ //' | tail -300 + echo '```' + } >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}" + + report:runner: + desc: What this host can measure, said before anything is, on the run's summary in CI; fails without a usable /dev/kvm. + # A row the report skips is one this host lacks the device for, and this says which first. + cmds: + - | + set -e + { + echo "### Runner ${RUNNER_NAME:-$(hostname)}" + echo + for dev in /dev/kvm /dev/vhost-vsock; do + if [ -r "$dev" ] && [ -w "$dev" ]; then echo "- $dev: usable"; else echo "- $dev: **not usable** ($(ls -l "$dev" 2>&1))"; fi + done + if sudo -n true 2>/dev/null; then + echo "- sudo -n: yes" + sudo -n modprobe nbd max_part=8 2>/dev/null || true + for _ in $(seq 50); do [ -e /dev/nbd0 ] && break; sleep 0.02; done + if [ -e /dev/nbd0 ]; then echo "- /dev/nbd0: present (image variants and the echo login run)"; else echo "- /dev/nbd0: **missing** (image variants are skipped, the login is agetty's)"; fi + else + echo "- sudo -n: **no** (image variants are skipped, the login is agetty's)" + fi + echo "- gh: $(command -v gh || echo '**missing**')" + echo "- CPU: $(sed -n 's/^model name\s*: //p' /proc/cpuinfo | head -1), $(nproc) CPUs" + } | tee -a "${GITHUB_STEP_SUMMARY:-/dev/null}" + [ -r /dev/kvm ] && [ -w /dev/kvm ] || { echo "::error::no usable /dev/kvm: nothing here can be measured"; exit 1; } + + report:unpack: + desc: >- + The release VERSION's tarball, as a consumer gets it, unpacked into _output/report: what is + measured is what was published. Needs gh. + cmds: + - | + set -euo pipefail + rm -rf _output/report + mkdir -p _output/report + gh release download "$VERSION" -R "$GITHUB_REPOSITORY" -p '*.tar.gz' -D _output/report + tar -xzf _output/report/*.tar.gz -C _output/report + echo "RELEASE_TREE=$PWD/_output/report/spin-machine-${VERSION}-linux-x86_64/usr/share/spin-stack" >> "${GITHUB_ENV:-/dev/stdout}" + + report:compare: + desc: >- + _output/report/report.json against the newest release before VERSION that published one, + in compare.md beside it and on the run's summary in CI. Needs gh. + cmds: + - | + set -euo pipefail + cd _output/report + previous="" + for tag in $(gh release list -R "$GITHUB_REPOSITORY" --limit 30 --json tagName -q '.[].tagName'); do + [ "$tag" = "$VERSION" ] && continue + if gh release download "$tag" -R "$GITHUB_REPOSITORY" -p report.json -O previous.json 2>/dev/null; then + previous="$tag" + break + fi + done + if [ -n "$previous" ]; then + "$RELEASE_TREE/bin/spin-machine" compare --old previous.json --new report.json > compare.md + else + echo "No earlier release published a report.json to compare the feature matrix with." > compare.md + fi + cat compare.md >> "${GITHUB_STEP_SUMMARY:-/dev/stdout}" + + report:publish: + desc: Upload _output/report/report.json to the release VERSION and append compare.md to its notes. Needs gh. + cmds: + - | + set -euo pipefail + cd _output/report + gh release upload "$VERSION" -R "$GITHUB_REPOSITORY" report.json --clobber + gh release view "$VERSION" -R "$GITHUB_REPOSITORY" --json body -q .body > notes.md + { echo; cat compare.md; } >> notes.md + gh release edit "$VERSION" -R "$GITHUB_REPOSITORY" --notes-file notes.md + # ========================================================================== # Keeping the pins and the tree # ========================================================================== @@ -448,7 +866,7 @@ tasks: - '{{.VERSIONS}} bump {{.NAME}} {{.TO}}' # A QEMU bump keeps the machine type (machine.MachineType), and the bump's pull request # shows what the newer types change against it, from the source just pinned. - - cmd: task qemu:compat + - cmd: '{{.TASK_EXE}} qemu:compat' if: '[ "{{.NAME}}" = qemu ]' clean: diff --git a/boot/Taskfile.yml b/boot/Taskfile.yml index 810f172..378a249 100644 --- a/boot/Taskfile.yml +++ b/boot/Taskfile.yml @@ -52,6 +52,37 @@ tasks: fi echo "$dir/$name/usr/share/spin-stack" > {{.OUTPUT_ABS}}/compat/previous + buildkit: + desc: >- + Use the BuildKit builder named compat, made the first time: a docker-container builder, + which keeps its cache in .cache/buildkit for the KVM runner's next run. + cmds: + - docker buildx inspect compat > /dev/null 2>&1 && docker buildx use compat || docker buildx create --use --name compat --driver docker-container + + here: + desc: >- + The machine before (boot:previous) and this one: the newest release with this tree's QEMU, + kernel and spin-machine in place of its own, in _output/compat/here. Both are exported to + the steps after in CI (SPIN_COMPAT_PREVIOUS, SPIN_MACHINE_OUTPUT). Needs a built QEMU, + kernel and tools. + # The base image is the release's: a checkpoint resumes with the disks it was saved with. + cmds: + - task: previous + - | + set -euo pipefail + previous=$(cat {{.OUTPUT_ABS}}/compat/previous) + here={{.OUTPUT_ABS}}/compat/here + rm -rf "$here" && cp -as "$previous" "$here" + rm -rf "$here/bin" "$here/qemu" "$here/kernel" + mkdir -p "$here/bin" "$here/kernel" + cp {{.OUTPUT_ABS}}/bin/qemu-system-x86_64 {{.OUTPUT_ABS}}/bin/qemu-img {{.OUTPUT_ABS}}/bin/spin-machine "$here/bin/" + cp -r {{.OUTPUT_ABS}}/qemu "$here/qemu" + cp {{.OUTPUT_ABS}}/kernel/vmlinux "$here/kernel/vmlinux" + { + echo "SPIN_COMPAT_PREVIOUS=$previous" + echo "SPIN_MACHINE_OUTPUT=$here" + } >> "${GITHUB_ENV:-/dev/stdout}" + compat: desc: >- A checkpoint the newest published release saves resumes on this tree's build, when the two diff --git a/go.mod b/go.mod index d5c6181..b33c0ae 100644 --- a/go.mod +++ b/go.mod @@ -5,25 +5,154 @@ go 1.27 toolchain go1.27.3 tool ( + github.com/go-task/task/v3/cmd/task github.com/spin-stack/go-tools/cmd/attestgate github.com/spin-stack/go-tools/cmd/ctxlife github.com/spin-stack/go-tools/cmd/mutate github.com/spin-stack/go-tools/cmd/provenance github.com/spin-stack/go-tools/cmd/refs github.com/spin-stack/go-tools/cmd/sbom + github.com/spin-stack/go-tools/cmd/sfw + github.com/spin-stack/go-tools/cmd/taskgate github.com/spin-stack/go-tools/cmd/testquality github.com/spin-stack/go-tools/cmd/versions ) require ( - github.com/spin-stack/go-tools v0.0.0-20261013164036-99d744796066 + github.com/spin-stack/go-tools v0.0.0-20261024182514-8cf54b031efe golang.org/x/sys v0.49.0 ) require ( + cel.dev/expr v0.25.2 // indirect + charm.land/bubbles/v2 v2.1.1 // indirect + charm.land/bubbletea/v2 v2.0.10 // indirect + charm.land/lipgloss/v2 v2.0.6 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.24.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.10.0 // indirect + cloud.google.com/go/iam v1.14.0 // indirect + cloud.google.com/go/monitoring v1.31.0 // indirect + cloud.google.com/go/storage v1.65.1 // indirect github.com/CycloneDX/cyclonedx-go v0.12.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.38.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.62.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.62.0 // indirect + github.com/Ladicle/tabwriter v1.0.0 // indirect + github.com/Masterminds/semver/v3 v3.5.0 // indirect + github.com/alecthomas/chroma/v2 v2.27.0 // indirect + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aws/aws-sdk-go-v2 v1.44.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.20 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.40 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.39 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.40 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.40 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.41 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.10.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.40 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.41 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.108.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.6.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.34.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.39.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.46.0 // indirect + github.com/aws/smithy-go v1.28.1 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chainguard-dev/git-urls v1.0.2 // indirect + github.com/charmbracelet/colorprofile v0.4.3 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 // indirect + github.com/charmbracelet/x/ansi v0.11.8 // indirect + github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/charmbracelet/x/termios v0.1.1 // indirect + github.com/charmbracelet/x/windows v0.2.2 // indirect + github.com/clipperhouse/displaywidth v0.11.0 // indirect + github.com/clipperhouse/uax29/v2 v2.7.0 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dlclark/regexp2/v2 v2.7.1 // indirect + github.com/docker/cli v29.7.2+incompatible // indirect + github.com/docker/docker-credential-helpers v0.9.3 // indirect + github.com/dominikbraun/graph v0.23.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/elliotchance/orderedmap/v3 v3.1.1 // indirect + github.com/envoyproxy/go-control-plane/envoy v1.39.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect + github.com/fatih/color v1.19.0 // indirect + github.com/felixge/httpsnoop v1.1.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/go-logr/logr v1.4.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-task/task/v3 v3.54.0 // indirect + github.com/go-task/template v0.2.0 // indirect + github.com/google/go-containerregistry v0.22.1 // indirect + github.com/google/s2a-go v0.1.10 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.22 // indirect + github.com/googleapis/gax-go/v2 v2.26.2 // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.74 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.8.9 // indirect + github.com/hashicorp/go-version v1.9.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/klauspost/compress v1.19.2 // indirect + github.com/klauspost/cpuid/v2 v2.4.0 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect + github.com/lucasb-eyer/go-colorful v1.4.1 // indirect + github.com/mattn/go-colorable v0.1.15 // indirect + github.com/mattn/go-isatty v0.0.24 // indirect + github.com/mattn/go-runewidth v0.0.27 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/pierrec/lz4/v4 v4.1.27 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/puzpuzpuz/xsync/v4 v4.5.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/sajari/fuzzy v1.0.0 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/spiffe/go-spiffe/v2 v2.8.1 // indirect + github.com/stretchr/objx v0.5.3 // indirect + github.com/stretchr/testify v1.12.1 // indirect + github.com/u-root/u-root v0.16.0 // indirect + github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect + github.com/ulikunitz/xz v0.5.16 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/zeebo/xxh3 v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.45.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.70.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0 // indirect + go.opentelemetry.io/otel v1.45.0 // indirect + go.opentelemetry.io/otel/metric v1.45.0 // indirect + go.opentelemetry.io/otel/sdk v1.45.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.45.0 // indirect + go.opentelemetry.io/otel/trace v1.45.0 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect - golang.org/x/mod v0.41.0 // indirect - golang.org/x/sync v0.23.0 // indirect - golang.org/x/tools v0.51.0 // indirect + golang.org/x/crypto v0.58.0 // indirect + golang.org/x/mod v0.42.0 // indirect + golang.org/x/net v0.61.0 // indirect + golang.org/x/oauth2 v0.37.0 // indirect + golang.org/x/sync v0.24.0 // indirect + golang.org/x/term v0.47.0 // indirect + golang.org/x/text v0.43.0 // indirect + golang.org/x/time v0.16.0 // indirect + golang.org/x/tools v0.52.0 // indirect + google.golang.org/api v0.299.0 // indirect + google.golang.org/genproto v0.0.0-20260724162435-b2f20204f0df // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260724162435-b2f20204f0df // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260921155816-b14227669459 // indirect + google.golang.org/grpc v1.84.0 // indirect + google.golang.org/protobuf v1.36.12 // indirect + mvdan.cc/sh/v3 v3.14.1 // indirect + mvdan.cc/sh/x v0.0.0-20260922090537-aebdf2b86f56 // indirect ) diff --git a/go.sum b/go.sum index 70e4f9b..0e31661 100644 --- a/go.sum +++ b/go.sum @@ -1,36 +1,295 @@ +cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs= +cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +charm.land/bubbles/v2 v2.1.1 h1:7r55WzBxpo/R3z98hGmY7KKPd3ET6vsf0Fb9sDHOV60= +charm.land/bubbles/v2 v2.1.1/go.mod h1:GE6M31gaWZVXzGw73OeuTTgy4lX+OtkH0E5ymnNsHxo= +charm.land/bubbletea/v2 v2.0.10 h1:oolvo20VBpI0PfqE7iFjkZ1bx0WpmXGfnKz5Yldjq5o= +charm.land/bubbletea/v2 v2.0.10/go.mod h1:QOatcnhOjYIfxzUSTz6raF7Ex4R/rIuHa3SnBdCCpMc= +charm.land/lipgloss/v2 v2.0.6 h1:EaGKeuA8FvF+v2BT5VmZd2LoYLaMZJXA5n34th8nCIQ= +charm.land/lipgloss/v2 v2.0.6/go.mod h1:ipDDJNSGa1hlwDtSfW1s2/xR8Vdhbut4PXh2zEKZd0Q= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.24.0 h1:UYMbF8otPZnLAkNJ5/LYQYOq0ARcJS1P4JqTeMKbCYU= +cloud.google.com/go/auth v0.24.0/go.mod h1:IFG/AMA1VWfuTrdbieEsB2GcpJyJV/phGAvogkOoPR4= +cloud.google.com/go/auth/oauth2adapt v0.3.0 h1:FY8oSZpCYoUNv6QxVODuMjQz4IlSOVeiQtZ08vLPz88= +cloud.google.com/go/auth/oauth2adapt v0.3.0/go.mod h1:7+2uCm7++XFO+/lN06c2HXpDXb/NMNn2/UwyBPbTnkk= +cloud.google.com/go/compute/metadata v0.10.0 h1:pyKMUQSwchgkIBBJGdILqQbs/BNJXqwSA7Ej6LAvvtY= +cloud.google.com/go/compute/metadata v0.10.0/go.mod h1:rGFHRrIif570kSibjFTMbt6/4/tzgJWFGI/HVol4GIk= +cloud.google.com/go/iam v1.14.0 h1:YRIB1/4xxwJ+NfI6RQr1WaOoHHeV0MizJEj940nBXJA= +cloud.google.com/go/iam v1.14.0/go.mod h1:JTPZfbHdGXJrOYREtkRoFzCDGaBdbA7ILLKO/DDuav0= +cloud.google.com/go/monitoring v1.31.0 h1:LCuAoYiq8snyL/eDAG/VC73uWFXeax8+YEfmoNGJUrY= +cloud.google.com/go/monitoring v1.31.0/go.mod h1:7uk2dIJIf7ra64dI1VuQ0ttoFqvtKjdzq46u6zNP1hU= +cloud.google.com/go/storage v1.65.1 h1:LRRpBJUTf+OXDPX9jZUKZ3mSLIsz3htG+qUpeNZovyA= +cloud.google.com/go/storage v1.65.1/go.mod h1:UsS9OgFg/XHOSYakQ8ZtLWWeyGkk1WnmD/GsGfN0BHM= github.com/CycloneDX/cyclonedx-go v0.12.0 h1:/7Jum36UA6V043tQZ/fE3jf+Nf9gn/qxUFfd7QReMy8= github.com/CycloneDX/cyclonedx-go v0.12.0/go.mod h1:V2577HhxDDCDLYfkm55WJrz16nHTfyQZwcWUBSG7Z28= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.38.0 h1:rmzbFS2CkHq0y2L5LkMVWm+QXjjNEXxjmhrJqga/QGk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.38.0/go.mod h1:iIyrdhveU5Ow84ipRlxtjCOQnIM0DiqSMxuxm50xwZY= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.62.0 h1:5y2LR2pripbccOte6BpZ+guv5O5W0OQIfKvUYZrGaAQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.62.0/go.mod h1:b3f7EifFRqkVt142USoGIP62uUeZm7ALCPrs1ZjWXYo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.62.0 h1:aPMa5qZU9dp4fU34o+jQgVIPFIOi20oxYg8TLigmZLg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.62.0/go.mod h1:sg6Wqbl0BKKZ5zKnQj2q0qic/3ziF894SCx1LpbX37Y= +github.com/Ladicle/tabwriter v1.0.0 h1:DZQqPvMumBDwVNElso13afjYLNp0Z7pHqHnu0r4t9Dg= +github.com/Ladicle/tabwriter v1.0.0/go.mod h1:c4MdCjxQyTbGuQO/gvqJ+IA/89UEwrsD6hUCW98dyp4= +github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE= +github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs= +github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aws/aws-sdk-go-v2 v1.44.0 h1:4IbaHhtzy+4h37z4JQyO9a2QsiCml3CNYHtq5hIHigo= +github.com/aws/aws-sdk-go-v2 v1.44.0/go.mod h1:bttEH6JqnUL8LepvDVfdrds/fZ5bCIxzpe3abyUrhDU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.20 h1:GPRlPwz40I2B2VrBEASOA3Bi77NyeqejNLkifosX0rs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.20/go.mod h1:g7PNzKcsOKWb4fkSRBA7BZVAS6Y8IcxzN+nRohhQ1Q8= +github.com/aws/aws-sdk-go-v2/config v1.32.40 h1:lAVC9gMmKusmqDRe32dPtgKl/BWvJmMJoWELKHCAObw= +github.com/aws/aws-sdk-go-v2/config v1.32.40/go.mod h1:8xOJLbe/hOj1g4PVsfJYV7O2byq+UGET1onDdUgbwqc= +github.com/aws/aws-sdk-go-v2/credentials v1.19.39 h1:XOg8LC3Kgnsa3WiPQjc7Bi8k5IBN92cPYfIV9XMFss0= +github.com/aws/aws-sdk-go-v2/credentials v1.19.39/go.mod h1:GonTDBQ+mTpCVNwaHjj0PagspfrYYMEqOx7FehoEP/I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.40 h1:r5aGipEVgI9aT/tAGjdrPbDQvIAKdTrS3rUPQtG4Rmo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.40/go.mod h1:vOD3CnPxAdkL6MWZeROkZsTlskklMFfgVFkHzx/oZpY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.40 h1:UIXlbijuB2XK1Kr57fo8iIxCuaSHJzwZ1uo+2tbEYIk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.40/go.mod h1:wcEsL6jscjZjVUinb0Q5qD/GXOG1yT3GNfmT9HuDwzU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40 h1:xLQVRDs2NddDmK9BEyh5KSlJ1Gpy5/GIJXrV6WcVGAE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40/go.mod h1:XRXnpFVFGLaEVK+olDdFIM1vNa04ETW452oFGEPUxAo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.41 h1:nv/ILuCY0yXACzMQwvtt/HbqDDjemZiI0AeDbxGQlnU= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.41/go.mod h1:dzvOSpxaPqQ3j0xS6Lc1vyVuWW0RBj7s/QqYpzu3Q/0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19 h1:bAdDl/HkGCcGPoe25ToSHEw23VIxt6CT5fLcg111BKg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19/go.mod h1:KaUzbLxv4CeSxh6ZCl9B4m7CuFenS8kUEaDs+f/DQr4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.10.0 h1:U8/A0RRBaEspzH1uul3JHLbypXwEGUkRkvoT9f0ATcM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.10.0/go.mod h1:UELStX5KwtJNtQxa+UuF8dc3z4UYc40e8yHYJSozNwY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.40 h1:gr3Fw1cxZXNCdeo/lQ7isHEHzvHVM7z75qb2zW9aMjw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.40/go.mod h1:8z/9CmfnQhiuXD7Ykbcg4a/whSWsniE0ODSx9uwVzfk= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.41 h1:Q9DIKDuJix/oJnQxFpQ26L0EwVa/YNo4k2kbktrjQjE= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.41/go.mod h1:x+TuqkOIG1SZS0+yN54sExGA9ZpjhPO6vPdYnpTFX1M= +github.com/aws/aws-sdk-go-v2/service/s3 v1.108.0 h1:Yp+x5PKXEmoqHsgP/pAkBy5Tyq1UlXAzM0OInh0vxWw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.108.0/go.mod h1:locV6DtXyp7Xzr2BG6jtsbeBi3YAWJ/CY4xUThYmIwQ= +github.com/aws/aws-sdk-go-v2/service/signin v1.6.0 h1:agcr0j8YeFEzdXNo17Rg9MbbjLRjrimabwNtji4e+lU= +github.com/aws/aws-sdk-go-v2/service/signin v1.6.0/go.mod h1:qU5PxgQ4JiUOOMotzfO3+5oUda5W+8JDVKyLQqlrJik= +github.com/aws/aws-sdk-go-v2/service/sso v1.34.0 h1:FxaN8/sn61DTXNI6Gt678tFJUY8iUsCchm6Y/F/RjaA= +github.com/aws/aws-sdk-go-v2/service/sso v1.34.0/go.mod h1:vu4OY6s8LJtT8BtYG2LD6BGSZMptkYn3o5hvCPB22jc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.39.0 h1:crWKPeGYTBTuBxQ3p73kjfJvt4brUIsr+Fuypko8FxY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.39.0/go.mod h1:HjjZVhaBz0JBR/kbWKThmNDhFKS7y6EURuk493tJk9Y= +github.com/aws/aws-sdk-go-v2/service/sts v1.46.0 h1:IZ63JdogSNNjex/jsODNv7jGDcO/xJYd9FsgyfCsp1g= +github.com/aws/aws-sdk-go-v2/service/sts v1.46.0/go.mod h1:I+rwAf3spG5dITBaAo3xXRowk8kiOhtU1kYxfvCTC44= +github.com/aws/smithy-go v1.28.1 h1:R/nXH00c8qcfCzQVELtRw+eLQWtzv+VAIEFJ1/xxXlQ= +github.com/aws/smithy-go v1.28.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= +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/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ= +github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o= +github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q= +github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q= +github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 h1:rdnVWKgJpTVXKuKuJyxDJ+NFJdUaUqGvyGy61OcvlbA= +github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886/go.mod h1:nAw0d9PhFp1qdzi2xhQU5YOu5sVpDIHWlaW2Uz/bCro= +github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ= +github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= +github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= +github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= +github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM= +github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k= +github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8= +github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0= +github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= +github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2/v2 v2.7.1 h1:yqDtwI1ptXXvEUNpYTk2lad4jLtAcKqkzepn4savSk4= +github.com/dlclark/regexp2/v2 v2.7.1/go.mod h1:avUrQvPaLz2DrFNHJF0taWAFFX2C1GMSSoeiqFjcBmU= +github.com/docker/cli v29.7.2+incompatible h1:dlkwallR8XqfeVnA2ELEhdwvb4lsSwuB4IgsG8Q9cLY= +github.com/docker/cli v29.7.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= +github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= +github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= +github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/elliotchance/orderedmap/v3 v3.1.1 h1:eV7lfZ5fVL8d36b8Wogqi/eqm7R/kZcftA9Yiyj+63M= +github.com/elliotchance/orderedmap/v3 v3.1.1/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= +github.com/envoyproxy/go-control-plane/envoy v1.39.0 h1:1uwRDYPYG8BIBU9Mj1sUAebNmlM6beu/ZKKweSLDxk8= +github.com/envoyproxy/go-control-plane/envoy v1.39.0/go.mod h1:5e4ylfTZO723MEEFsCpSW4ZEBWR8mwkEyXfwJBTCZ9c= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= +github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= +github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc= +github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +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/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-task/task/v3 v3.54.0 h1:xDgD9BNHIDnHhemB3gumYb+ozUoa6oCFMIz44GGosj8= +github.com/go-task/task/v3 v3.54.0/go.mod h1:oOHzpL1r0bga9Xq1dC/8kucE1Y4fxSMTlKKFpNi6mFc= +github.com/go-task/template v0.2.0 h1:xW7ek0o65FUSTbKcSNeg2Vyf/I7wYXFgLUznptvviBE= +github.com/go-task/template v0.2.0/go.mod h1:dbdoUb6qKnHQi1y6o+IdIrs0J4o/SEhSTA6bbzZmdtc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-containerregistry v0.22.1 h1:RZuuSYhTvlDvtsK+NkutoCZ//C0X2ebLK8X8l3ULs84= +github.com/google/go-containerregistry v0.22.1/go.mod h1:bJR35SK8XgisYmhg/FMQ/5RK0S/XrOAqLBV5/LR2XE0= +github.com/google/s2a-go v0.1.10 h1:EMp+aOuXN6l8cE/gjF5Bt+vyZxsUuyCWe9chDWR/+uU= +github.com/google/s2a-go v0.1.10/go.mod h1:pz4tyvwXvJLLbyrkh6FW1eS2zPUXMaTmyNhYtyP2tNw= +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.22 h1:NU4XpII6jD+Dxcot94fqjE+AfJoE/lQP9q3faYGzC/c= +github.com/googleapis/enterprise-certificate-proxy v0.3.22/go.mod h1:L3D/IQExI6LqEjBdXcZQ1WluSgigQmSwBboFstVPM4w= +github.com/googleapis/gax-go/v2 v2.26.2 h1:ydkmNXxj7bEmmeK5AihkKnWxyOyBR9TDebvp5L5izk8= +github.com/googleapis/gax-go/v2 v2.26.2/go.mod h1:sMKqnMesnKH+3wiRJROcttA+cJoZoGbZl1vDQ8XYtGk= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.74 h1:mymLUKThnV9wFvogOK8NnsMP9/vlhnjXY98gr2QIGW8= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.74/go.mod h1:Bh9qYL8ehmDxSg14Tk8oxFCP90XHfs6NxV1D84884xA= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.8.9 h1:1AOTMUmz/S/GuqOTE6+bg6nwPXTEbKr3Tc/T/lVS7is= +github.com/hashicorp/go-getter v1.8.9/go.mod h1:qI7vH/m552bXutKe4UkWptOJl4bo2KeO/CSOoh4s0ps= +github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= +github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/in-toto/attestation v1.2.0 h1:aPRUZ3azbqD7yEBD5fP3TD8Dszf+YHo284SOcpahjQk= github.com/in-toto/attestation v1.2.0/go.mod h1:r79G45gOmzPismgObLSL+rZTFxUgZLOQJI6LofTZgXk= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8= +github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= +github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= +github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= +github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/lucasb-eyer/go-colorful v1.4.1 h1:1EO+WB73+EH8EVbzlrG3KLAfEypQWVHIBqlTf+2hNss= +github.com/lucasb-eyer/go-colorful v1.4.1/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= +github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= +github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= +github.com/mattn/go-runewidth v0.0.27 h1:Feg/Oou5zI/wnpgDF6omIU0OokC9GxLC/WRknhVlIR0= +github.com/mattn/go-runewidth v0.0.27/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/pierrec/lz4/v4 v4.1.27 h1:+PhzhWDrjRj89TH2sw43nE3+4+W8lSxIuQadEHZyjUk= +github.com/pierrec/lz4/v4 v4.1.27/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/puzpuzpuz/xsync/v4 v4.5.0 h1:vOSWu6b57/emh+L/Cw0BeQfvxa/cogFywXHeGUxQxAg= +github.com/puzpuzpuz/xsync/v4 v4.5.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= +github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spiffe/go-spiffe/v2 v2.8.1 h1:eXZMLsu+3MLEPJyGJkolqtVrteZfQdUpOWj6LTiDl/E= +github.com/spiffe/go-spiffe/v2 v2.8.1/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= github.com/spin-stack/go-tools v0.0.0-20261013164036-99d744796066 h1:T4uAeYrQ9e9Fml3PcZGzgji5sIAoebXK9zy94u5IBwg= github.com/spin-stack/go-tools v0.0.0-20261013164036-99d744796066/go.mod h1:cy1ojfIbEjrfZi0lGzE+wjueaWw1jrotHQ+vyFz9pZQ= +github.com/spin-stack/go-tools v0.0.0-20261024182514-8cf54b031efe h1:rJz8V82biVU+07n5vjQUl9xeWES43Xs8awFmXVEwyBc= +github.com/spin-stack/go-tools v0.0.0-20261024182514-8cf54b031efe/go.mod h1:AjnMnKNXxvNt1n0zTkHpABmBd+NnNBqdRMSwmYu885Y= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/terminalstatic/go-xsd-validate v0.1.8 h1:UVrTCy1j3DhwaYTTUF+QYO/Nan13S0tf+Jwi+p45Bf0= github.com/terminalstatic/go-xsd-validate v0.1.8/go.mod h1:1kb47fi2c6onlf+B7UrrQ9VYraOhcYwFm3iG+J6F4Zo= +github.com/u-root/u-root v0.16.0 h1:wY40O83MBVks97+Is0WlFlOPSwKQMIrWP9R1IsrExg8= +github.com/u-root/u-root v0.16.0/go.mod h1:yL/XdSSW27PdGLgUh4MNRBy54mKM+TBLzpwiB4nwj90= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= +github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= +github.com/ulikunitz/xz v0.5.16 h1:ld6NyySjx5lowVKwJvMRLnW5nxKX/xnpSiFYZ/Lxur0= +github.com/ulikunitz/xz v0.5.16/go.mod h1:H9Rt/W6/Qj27PGauhQc6nfCDy7vHpzsOThBSaYDoEhw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= +github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= +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/detectors/gcp v1.45.0 h1:9jR0ZPRok9ryaOQ2Wx8rg5F7Aon59mxrqbVI60/vlBk= +go.opentelemetry.io/contrib/detectors/gcp v1.45.0/go.mod h1:VSme3o2fvSg5bVg0dRzyHaj4Z5EVhG+g2Fde6LKzmQA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.70.0 h1:oECp5f+hN7nkwjU/8BxQ/q23bGPb8FIrD839owX222E= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.70.0/go.mod h1:DqEFwLumhzMBDQv9PcWbyoDxHI/4lAk6CM4nJBH39sc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0 h1:LMuyCAyfalSjDyjdC65nK6N0zoTT63+E/u95X0JovZI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0/go.mod h1:085m8qbm4hgc8rZWGDEa4vmyyo2c3nPxUslYUKUIU04= +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.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +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= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= +golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54= +golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w= golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= +golang.org/x/mod v0.42.0 h1:ICeL3t2L30ljSPHHxDnR4fqVcBt/zR2zJAb9juavmQg= +golang.org/x/mod v0.42.0/go.mod h1:u5fzIrRInkL8MaO1cbRkUHT64v303YIT5KEqpNr7jRs= +golang.org/x/net v0.61.0 h1:RR+6j/BTBCrggOLugxa+66R8FvoN6MHlzDlZIbN9YFw= +golang.org/x/net v0.61.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= +golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= +golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= +golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA= +golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/term v0.47.0 h1:cpyOwQkr2Nzxe2p6KnrTG7Ei2wtzjsuSjhpXXepZ/BM= +golang.org/x/term v0.47.0/go.mod h1:efAfAuG6RKABvg1ArGebRkvX6LXul14SM67o2e4mUCY= +golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc= +golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s= +golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE= +golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s= golang.org/x/tools v0.51.0 h1:k4Xc/1Om9jwkBJBo4NVLMSARBoWtK10mx+W5BnXCeAI= golang.org/x/tools v0.51.0/go.mod h1:9eEncMayCV6zRMGhR5eZEC2iBx98qWcF1HZ9Z7wJOoA= +golang.org/x/tools v0.52.0 h1:ryxg4U63oaUYk7uOLTF37n43f4qgtGvqV4Ioit1BaEs= +golang.org/x/tools v0.52.0/go.mod h1:ItcP5UNaVGG+Yc4eIYmaFLNJ4soEopkx5Y2d4lcEurs= +google.golang.org/api v0.299.0 h1:b3K+ydSMd0kh6TQI6bJyApRQfqQX2MfSOaVkpM59mJw= +google.golang.org/api v0.299.0/go.mod h1:zlR3GVA8b2R5nv5Ij9UWe37StVB3cxDD7DBFi4ZFsHw= +google.golang.org/genproto v0.0.0-20260724162435-b2f20204f0df h1:A7u56ilVtWR3CySHErsWAsimNwD4FoX9KWd8SUCn6vc= +google.golang.org/genproto v0.0.0-20260724162435-b2f20204f0df/go.mod h1:4RPHZcXMGptb7aRZb+M43xI7ixmjEtASEf2VtOOBZbU= +google.golang.org/genproto/googleapis/api v0.0.0-20260724162435-b2f20204f0df h1:NsJx+hCSwIBI6+C4BuJIkb8xOG1M+nfQDsqIrQHT92k= +google.golang.org/genproto/googleapis/api v0.0.0-20260724162435-b2f20204f0df/go.mod h1:1brfde68Npq6+WA75c1EHWPijZEG1kMus61ygPZfn4A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260921155816-b14227669459 h1:b0xCahf3FK2m2Cv0p4vTozGPWncCvLfwV86UNg8xWU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260921155816-b14227669459/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc= +google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= +google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +mvdan.cc/sh/v3 v3.14.1 h1:bXkhQWNHCs0KZEChF8hYS6FC+T2N9mUZLbQv9blditI= +mvdan.cc/sh/v3 v3.14.1/go.mod h1:syYCoFET8w9tvevxiXUtY8/ICrU+l26jHmhJDra3Vwo= +mvdan.cc/sh/x v0.0.0-20260922090537-aebdf2b86f56 h1:deNO1TejgB0Dmp3IjB2vkIiHVG81yvLModUSzLjI98A= +mvdan.cc/sh/x v0.0.0-20260922090537-aebdf2b86f56/go.mod h1:j4gEzJjKcncRAMCu/GVaXCR8/b63sHi/ty4+pG+FuPU= diff --git a/image/Taskfile.yml b/image/Taskfile.yml index 4e3f242..c8f8acb 100644 --- a/image/Taskfile.yml +++ b/image/Taskfile.yml @@ -23,6 +23,14 @@ tasks: -v {{.MKOSI_CACHE_DIR}}:/cache \ {{.IMAGE_BUILDER_TAG}} + summary: + desc: What the built base image is, by size and sha256. + cmds: + - | + set -e + ls -la {{.OUTPUT_ABS}}/image/rootfs.qcow2 + echo "sha256: $(sha256sum {{.OUTPUT_ABS}}/image/rootfs.qcow2 | cut -d' ' -f1)" + builder: desc: Build the container that builds the base image (mkosi, qemu-utils). # A step of build, not a thing to run on its own. diff --git a/kernel/Taskfile.yml b/kernel/Taskfile.yml index f73e1b5..26c1eab 100644 --- a/kernel/Taskfile.yml +++ b/kernel/Taskfile.yml @@ -48,6 +48,16 @@ tasks: echo "$k carries no Xen PVH notes — QEMU has no entry point into it" >&2; exit 1; } echo "OK: $k, PVH notes present, sha256 $(sha256sum "$k" | cut -c1-16)…" + summary: + desc: What the built kernel and its config are, by sha256, on the run's summary in CI. + cmds: + - | + set -euo pipefail + { + echo "kernel sha256: $(sha256sum {{.OUTPUT_ABS}}/kernel/vmlinux | cut -d' ' -f1)" + echo "config sha256: $(sha256sum {{.OUTPUT_ABS}}/kernel/kernel-config | cut -d' ' -f1)" + } | tee -a "${GITHUB_STEP_SUMMARY:-/dev/null}" + menuconfig: desc: "Edit the kernel config. Writes back to kernel/config--." interactive: true diff --git a/qemu/Taskfile.yml b/qemu/Taskfile.yml index f760d62..efc4c4e 100644 --- a/qemu/Taskfile.yml +++ b/qemu/Taskfile.yml @@ -90,6 +90,44 @@ tasks: - for: [qemu-system-x86_64, qemu-system-x86_64-tcg] cmd: go run ./hack/machinetype check -qemu {{.OUTPUT_ABS}}/bin/{{.ITEM}} + version: + desc: The pinned QEMU version, as version=, on the step's outputs in CI. + cmds: + - echo "version={{.QEMU_VERSION}}" >> "${GITHUB_OUTPUT:-/dev/stdout}" + + summary: + desc: >- + What the built QEMU is, and whether it still offers the machine type every checkpoint is + saved on: on the run's summary in CI. + cmds: + - | + set -euo pipefail + { + echo "qemu sha256: $(sha256sum {{.OUTPUT_ABS}}/bin/qemu-system-x86_64 | cut -d' ' -f1)" + echo "qboot.bin: $(stat -c%s {{.OUTPUT_ABS}}/qemu/qboot.bin) bytes" + go run ./hack/machinetype check -qemu {{.OUTPUT_ABS}}/bin/qemu-system-x86_64 + } | tee -a "${GITHUB_STEP_SUMMARY:-/dev/null}" + + publish: + desc: >- + Build and push the runtime image, tagged with the pinned version, to GitHub's registry + under GITHUB_REPOSITORY: what `fetch` pulls. Needs a docker login that can write packages. + cmds: + - | + set -euo pipefail + repo=${GITHUB_REPOSITORY:-spin-stack/spin-machine} + docker buildx build \ + --file qemu/Dockerfile \ + --target runtime \ + --platform linux/amd64 \ + --cache-from type=gha,scope=qemu \ + $({{.VERSIONS}} args alpine qemu debian debian-snapshot qboot) \ + --build-arg JOBS=4 \ + --label org.opencontainers.image.source=https://github.com/${repo} \ + --tag ghcr.io/${repo}/qemu:{{.QEMU_VERSION}} \ + --push \ + . + compat: desc: >- Print what QEMU's newer machine types change against the pinned one (machine.MachineType): diff --git a/workflows/workflows_test.go b/workflows/workflows_test.go index a1084a7..b9da264 100644 --- a/workflows/workflows_test.go +++ b/workflows/workflows_test.go @@ -12,16 +12,25 @@ import ( // Every step that publishes runs after an unconditional provenance attestation in its job; the // ones that look like an upload and ship nothing anyone installs are named here, each with why. +// A step runs a task, so the tasks that upload and the one that attests are named too: the YAML +// says only their names. func TestEveryUploadIsAttested(t *testing.T) { - g := attestgate.Gate{Root: "..", RequireSBOM: true, MainOnly: []string{"release.yml"}, NotPublished: map[string]string{ - "ci.yml/gate/Upload Go coverage HTML": "a coverage page for a person, kept seven days", - "kernel.yml/build/Upload the kernel": "a lane's kernel for a person to fetch; a release builds its own", - "lab.yml/lab/Keep the log": "a measurement's log, for a person", - "qemu.yml/build/Upload the extracted binaries": "a lane's QEMU for a person to fetch; a release builds its own", - "qemu.yml/build/Publish the runtime image": "what ci.yml's argument check pulls (task qemu:fetch); a release compiles QEMU, it never takes this", - "report.yml/report/Keep the report": "the run's copy of report.json, for a person", - "report.yml/report/Publish the report, and what moved": "report.json is measurement data: nothing installs or verifies it", - }} + g := attestgate.Gate{ + Root: "..", + RequireSBOM: true, + MainOnly: []string{"release.yml"}, + UploadTasks: []string{"qemu:publish", "report:publish"}, + AttestTasks: []string{"release:sign"}, + NotPublished: map[string]string{ + "ci.yml/gate/Upload Go coverage HTML": "a coverage page for a person, kept seven days", + "kernel.yml/build/Upload the kernel": "a lane's kernel for a person to fetch; a release builds its own", + "lab.yml/lab/Keep the log": "a measurement's log, for a person", + "qemu.yml/build/Upload the extracted binaries": "a lane's QEMU for a person to fetch; a release builds its own", + "qemu.yml/build/Publish the runtime image": "what ci.yml's argument check pulls (task qemu:fetch); a release compiles QEMU, it never takes this", + "report.yml/report/Keep the report": "the run's copy of report.json, for a person", + "report.yml/report/Publish the report, and what moved": "report.json is measurement data: nothing installs or verifies it", + }, + } if err := g.Check(); err != nil { t.Error(err) } From eb2241fd9be4cfcd1f35e14888219b0a14a05a54 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Sat, 24 Oct 2026 15:59:56 -0300 Subject: [PATCH 2/3] go-tools at main (dfcf2c1): sfw and taskgate as merged spin-stack/go-tools#50 and #51 are on main: the pin moves from the PR's commit to main's, which also finds the Task go.mod pins for refs and holds pnpm run to installing nothing on its own. Co-Authored-By: Claude Opus 5.5 --- go.mod | 2 +- go.sum | 72 +++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index b33c0ae..47f34a1 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ tool ( ) require ( - github.com/spin-stack/go-tools v0.0.0-20261024182514-8cf54b031efe + github.com/spin-stack/go-tools v0.0.0-20261024185510-dfcf2c10f30b golang.org/x/sys v0.49.0 ) diff --git a/go.sum b/go.sum index 0e31661..a9f3c65 100644 --- a/go.sum +++ b/go.sum @@ -16,24 +16,36 @@ cloud.google.com/go/compute/metadata v0.10.0 h1:pyKMUQSwchgkIBBJGdILqQbs/BNJXqwS cloud.google.com/go/compute/metadata v0.10.0/go.mod h1:rGFHRrIif570kSibjFTMbt6/4/tzgJWFGI/HVol4GIk= cloud.google.com/go/iam v1.14.0 h1:YRIB1/4xxwJ+NfI6RQr1WaOoHHeV0MizJEj940nBXJA= cloud.google.com/go/iam v1.14.0/go.mod h1:JTPZfbHdGXJrOYREtkRoFzCDGaBdbA7ILLKO/DDuav0= +cloud.google.com/go/logging v1.19.0 h1:NCqhdVUg3wQ8Cobdf16FDSuTGi3+6+hdSBHrY5TsR6Q= +cloud.google.com/go/logging v1.19.0/go.mod h1:i40NZCHC9Gqvod4yE+yQfDWwlgwW/SrshkkGibCHxcA= +cloud.google.com/go/longrunning v1.2.0 h1:WjYH3YHBGCxGJP9M4dWGHBfXr/cFIjMkNgWcJj7/iMM= +cloud.google.com/go/longrunning v1.2.0/go.mod h1:5KMQALFGOCtFoi2xSOA1u3H7WKlhmckgiyFw7+LGQp0= cloud.google.com/go/monitoring v1.31.0 h1:LCuAoYiq8snyL/eDAG/VC73uWFXeax8+YEfmoNGJUrY= cloud.google.com/go/monitoring v1.31.0/go.mod h1:7uk2dIJIf7ra64dI1VuQ0ttoFqvtKjdzq46u6zNP1hU= cloud.google.com/go/storage v1.65.1 h1:LRRpBJUTf+OXDPX9jZUKZ3mSLIsz3htG+qUpeNZovyA= cloud.google.com/go/storage v1.65.1/go.mod h1:UsS9OgFg/XHOSYakQ8ZtLWWeyGkk1WnmD/GsGfN0BHM= +cloud.google.com/go/trace v1.16.0 h1:GmQovzFc5F0CNfl0VLgL64aoTtu7xsM0YajW2GlG9+E= +cloud.google.com/go/trace v1.16.0/go.mod h1:r+bdAn16dKLSV1G2D5v3e58IlQlizfxWrUfjx7kM7X0= github.com/CycloneDX/cyclonedx-go v0.12.0 h1:/7Jum36UA6V043tQZ/fE3jf+Nf9gn/qxUFfd7QReMy8= github.com/CycloneDX/cyclonedx-go v0.12.0/go.mod h1:V2577HhxDDCDLYfkm55WJrz16nHTfyQZwcWUBSG7Z28= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.38.0 h1:rmzbFS2CkHq0y2L5LkMVWm+QXjjNEXxjmhrJqga/QGk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.38.0/go.mod h1:iIyrdhveU5Ow84ipRlxtjCOQnIM0DiqSMxuxm50xwZY= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.62.0 h1:5y2LR2pripbccOte6BpZ+guv5O5W0OQIfKvUYZrGaAQ= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.62.0/go.mod h1:b3f7EifFRqkVt142USoGIP62uUeZm7ALCPrs1ZjWXYo= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.62.0 h1:tRsXhJnn0w0TNwJpVrB94wsrimzjWKFzdQlUhRdNUzc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.62.0/go.mod h1:ifhe5teRNcbxg9p353DhOkOgczzL/IBLYFqT1cm1zpM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.62.0 h1:aPMa5qZU9dp4fU34o+jQgVIPFIOi20oxYg8TLigmZLg= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.62.0/go.mod h1:sg6Wqbl0BKKZ5zKnQj2q0qic/3ziF894SCx1LpbX37Y= github.com/Ladicle/tabwriter v1.0.0 h1:DZQqPvMumBDwVNElso13afjYLNp0Z7pHqHnu0r4t9Dg= github.com/Ladicle/tabwriter v1.0.0/go.mod h1:c4MdCjxQyTbGuQO/gvqJ+IA/89UEwrsD6hUCW98dyp4= github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE= github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.27.0 h1:FodwmyOBgJULFYmDqibcp9pvfDLWdtPRh9v/r5BXYZs= github.com/alecthomas/chroma/v2 v2.27.0/go.mod h1:NjJ3ciIgrqBNeIkWZ4e46nseoLDslxU1LmfCoL+wcY8= +github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= +github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aws/aws-sdk-go-v2 v1.44.0 h1:4IbaHhtzy+4h37z4JQyO9a2QsiCml3CNYHtq5hIHigo= @@ -72,6 +84,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.46.0 h1:IZ63JdogSNNjex/jsODNv7jGDcO/ github.com/aws/aws-sdk-go-v2/service/sts v1.46.0/go.mod h1:I+rwAf3spG5dITBaAo3xXRowk8kiOhtU1kYxfvCTC44= github.com/aws/smithy-go v1.28.1 h1:R/nXH00c8qcfCzQVELtRw+eLQWtzv+VAIEFJ1/xxXlQ= github.com/aws/smithy-go v1.28.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= +github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= @@ -86,6 +100,8 @@ github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886 h1:rdnVW github.com/charmbracelet/ultraviolet v0.0.0-20260811164956-006e29f97886/go.mod h1:nAw0d9PhFp1qdzi2xhQU5YOu5sVpDIHWlaW2Uz/bCro= github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ= github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0= +github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA= +github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= @@ -98,8 +114,8 @@ github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJ github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2/v2 v2.7.1 h1:yqDtwI1ptXXvEUNpYTk2lad4jLtAcKqkzepn4savSk4= @@ -114,8 +130,12 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elliotchance/orderedmap/v3 v3.1.1 h1:eV7lfZ5fVL8d36b8Wogqi/eqm7R/kZcftA9Yiyj+63M= github.com/elliotchance/orderedmap/v3 v3.1.1/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= +github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.39.0 h1:1uwRDYPYG8BIBU9Mj1sUAebNmlM6beu/ZKKweSLDxk8= github.com/envoyproxy/go-control-plane/envoy v1.39.0/go.mod h1:5e4ylfTZO723MEEFsCpSW4ZEBWR8mwkEyXfwJBTCZ9c= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= @@ -131,17 +151,22 @@ 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/go-quicktest/qt v1.102.0 h1:HSQxCeh5YZH3EL3W39ixjtyaEhcWSXQHtHnMBzSs474= +github.com/go-quicktest/qt v1.102.0/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/task/v3 v3.54.0 h1:xDgD9BNHIDnHhemB3gumYb+ozUoa6oCFMIz44GGosj8= github.com/go-task/task/v3 v3.54.0/go.mod h1:oOHzpL1r0bga9Xq1dC/8kucE1Y4fxSMTlKKFpNi6mFc= github.com/go-task/template v0.2.0 h1:xW7ek0o65FUSTbKcSNeg2Vyf/I7wYXFgLUznptvviBE= github.com/go-task/template v0.2.0/go.mod h1:dbdoUb6qKnHQi1y6o+IdIrs0J4o/SEhSTA6bbzZmdtc= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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/go-containerregistry v0.22.1 h1:RZuuSYhTvlDvtsK+NkutoCZ//C0X2ebLK8X8l3ULs84= github.com/google/go-containerregistry v0.22.1/go.mod h1:bJR35SK8XgisYmhg/FMQ/5RK0S/XrOAqLBV5/LR2XE0= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/s2a-go v0.1.10 h1:EMp+aOuXN6l8cE/gjF5Bt+vyZxsUuyCWe9chDWR/+uU= github.com/google/s2a-go v0.1.10/go.mod h1:pz4tyvwXvJLLbyrkh6FW1eS2zPUXMaTmyNhYtyP2tNw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -158,6 +183,8 @@ github.com/hashicorp/go-getter v1.8.9 h1:1AOTMUmz/S/GuqOTE6+bg6nwPXTEbKr3Tc/T/lV github.com/hashicorp/go-getter v1.8.9/go.mod h1:qI7vH/m552bXutKe4UkWptOJl4bo2KeO/CSOoh4s0ps= github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/in-toto/attestation v1.2.0 h1:aPRUZ3azbqD7yEBD5fP3TD8Dszf+YHo284SOcpahjQk= github.com/in-toto/attestation v1.2.0/go.mod h1:r79G45gOmzPismgObLSL+rZTFxUgZLOQJI6LofTZgXk= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -168,6 +195,10 @@ github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV91 github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lucasb-eyer/go-colorful v1.4.1 h1:1EO+WB73+EH8EVbzlrG3KLAfEypQWVHIBqlTf+2hNss= github.com/lucasb-eyer/go-colorful v1.4.1/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= @@ -190,25 +221,28 @@ github.com/pierrec/lz4/v4 v4.1.27 h1:+PhzhWDrjRj89TH2sw43nE3+4+W8lSxIuQadEHZyjUk github.com/pierrec/lz4/v4 v4.1.27/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/puzpuzpuz/xsync/v4 v4.5.0 h1:vOSWu6b57/emh+L/Cw0BeQfvxa/cogFywXHeGUxQxAg= github.com/puzpuzpuz/xsync/v4 v4.5.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.15.0 h1:D0RCU5rMAp+SpgkiNdrjfJ+LX4J1M32V2NeCY7EJ6hc= +github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= +github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= +github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spiffe/go-spiffe/v2 v2.8.1 h1:eXZMLsu+3MLEPJyGJkolqtVrteZfQdUpOWj6LTiDl/E= github.com/spiffe/go-spiffe/v2 v2.8.1/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= -github.com/spin-stack/go-tools v0.0.0-20261013164036-99d744796066 h1:T4uAeYrQ9e9Fml3PcZGzgji5sIAoebXK9zy94u5IBwg= -github.com/spin-stack/go-tools v0.0.0-20261013164036-99d744796066/go.mod h1:cy1ojfIbEjrfZi0lGzE+wjueaWw1jrotHQ+vyFz9pZQ= -github.com/spin-stack/go-tools v0.0.0-20261024182514-8cf54b031efe h1:rJz8V82biVU+07n5vjQUl9xeWES43Xs8awFmXVEwyBc= -github.com/spin-stack/go-tools v0.0.0-20261024182514-8cf54b031efe/go.mod h1:AjnMnKNXxvNt1n0zTkHpABmBd+NnNBqdRMSwmYu885Y= +github.com/spin-stack/go-tools v0.0.0-20261024185510-dfcf2c10f30b h1:NecYdTb3idSPRsLeC0ZlfkCUehR3N0mIvnD4IklltYc= +github.com/spin-stack/go-tools v0.0.0-20261024185510-dfcf2c10f30b/go.mod h1:AjnMnKNXxvNt1n0zTkHpABmBd+NnNBqdRMSwmYu885Y= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= @@ -229,6 +263,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= @@ -241,8 +277,12 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0 h1:LMuyCAy go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0/go.mod h1:085m8qbm4hgc8rZWGDEa4vmyyo2c3nPxUslYUKUIU04= 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/exporters/stdout/stdoutmetric v1.44.0 h1:hqxVTu/GtBF+vJ8d1fzW7fRxZFvgoDjWcxwwCaFDYpU= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0/go.mod h1:z5fVEF4X5v0ESvlJqBrrFlBVoj5EQuefZpzsu7R+x5Q= 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/metric/x v0.67.0 h1:PcicCNZFkZ4bXfSooXdo3WN7RBOVOtjVdo1wD358Uns= +go.opentelemetry.io/otel/metric/x v0.67.0/go.mod h1:FBjCWZe6wgcqxcMtjdGiClDKXb2YxxXii0CXftE4QtI= go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= @@ -253,16 +293,14 @@ go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54= golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w= -golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= -golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= +golang.org/x/exp v0.0.0-20260718201538-764159d718ef h1:LkZ48HFgy/TvhTI0bcWkjgFkgLyKUwcTbDjS0DUjw+A= +golang.org/x/exp v0.0.0-20260718201538-764159d718ef/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q= golang.org/x/mod v0.42.0 h1:ICeL3t2L30ljSPHHxDnR4fqVcBt/zR2zJAb9juavmQg= golang.org/x/mod v0.42.0/go.mod h1:u5fzIrRInkL8MaO1cbRkUHT64v303YIT5KEqpNr7jRs= golang.org/x/net v0.61.0 h1:RR+6j/BTBCrggOLugxa+66R8FvoN6MHlzDlZIbN9YFw= golang.org/x/net v0.61.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= -golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= -golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA= golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= @@ -273,10 +311,10 @@ golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc= golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s= golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE= golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s= -golang.org/x/tools v0.51.0 h1:k4Xc/1Om9jwkBJBo4NVLMSARBoWtK10mx+W5BnXCeAI= -golang.org/x/tools v0.51.0/go.mod h1:9eEncMayCV6zRMGhR5eZEC2iBx98qWcF1HZ9Z7wJOoA= golang.org/x/tools v0.52.0 h1:ryxg4U63oaUYk7uOLTF37n43f4qgtGvqV4Ioit1BaEs= golang.org/x/tools v0.52.0/go.mod h1:ItcP5UNaVGG+Yc4eIYmaFLNJ4soEopkx5Y2d4lcEurs= +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.299.0 h1:b3K+ydSMd0kh6TQI6bJyApRQfqQX2MfSOaVkpM59mJw= google.golang.org/api v0.299.0/go.mod h1:zlR3GVA8b2R5nv5Ij9UWe37StVB3cxDD7DBFi4ZFsHw= google.golang.org/genproto v0.0.0-20260724162435-b2f20204f0df h1:A7u56ilVtWR3CySHErsWAsimNwD4FoX9KWd8SUCn6vc= @@ -289,6 +327,8 @@ google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= mvdan.cc/sh/v3 v3.14.1 h1:bXkhQWNHCs0KZEChF8hYS6FC+T2N9mUZLbQv9blditI= mvdan.cc/sh/v3 v3.14.1/go.mod h1:syYCoFET8w9tvevxiXUtY8/ICrU+l26jHmhJDra3Vwo= mvdan.cc/sh/x v0.0.0-20260922090537-aebdf2b86f56 h1:deNO1TejgB0Dmp3IjB2vkIiHVG81yvLModUSzLjI98A= From 44d02eea1abfc6ae090e31b123037c2dc2083214 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Sat, 24 Oct 2026 16:21:16 -0300 Subject: [PATCH 3/3] go-tools at main (5824d9a): refs runs the Task go.mod pins as go tool task Through spin-stack/go-tools#52: refs ran the path `go tool -n task` printed, a build directory that in CI was gone once go returned, and lint failed on it. Co-Authored-By: Claude Opus 5.5 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 47f34a1..ec93e61 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ tool ( ) require ( - github.com/spin-stack/go-tools v0.0.0-20261024185510-dfcf2c10f30b + github.com/spin-stack/go-tools v0.0.0-20261024191920-5824d9a153be golang.org/x/sys v0.49.0 ) diff --git a/go.sum b/go.sum index a9f3c65..e6064d2 100644 --- a/go.sum +++ b/go.sum @@ -241,8 +241,8 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spiffe/go-spiffe/v2 v2.8.1 h1:eXZMLsu+3MLEPJyGJkolqtVrteZfQdUpOWj6LTiDl/E= github.com/spiffe/go-spiffe/v2 v2.8.1/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= -github.com/spin-stack/go-tools v0.0.0-20261024185510-dfcf2c10f30b h1:NecYdTb3idSPRsLeC0ZlfkCUehR3N0mIvnD4IklltYc= -github.com/spin-stack/go-tools v0.0.0-20261024185510-dfcf2c10f30b/go.mod h1:AjnMnKNXxvNt1n0zTkHpABmBd+NnNBqdRMSwmYu885Y= +github.com/spin-stack/go-tools v0.0.0-20261024191920-5824d9a153be h1:NzmdrDxCGDUvuXDP4TLz7FVJlB71bLI1fFue8MuqL44= +github.com/spin-stack/go-tools v0.0.0-20261024191920-5824d9a153be/go.mod h1:AjnMnKNXxvNt1n0zTkHpABmBd+NnNBqdRMSwmYu885Y= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=