diff --git a/.github/actions/setup-aqua/action.yaml b/.github/actions/setup-aqua/action.yaml index d818972..112008d 100644 --- a/.github/actions/setup-aqua/action.yaml +++ b/.github/actions/setup-aqua/action.yaml @@ -1,6 +1,12 @@ name: Setup aqua description: > Install aqua (pinned, checksum-verified), put its bin directory on PATH, and authorize the repository's committed policy. aqua itself is the one tool aqua cannot pin. Same pins as limen-install: the installer script is fetched at an exact tag and checksum-verified, and it installs an exact aqua version. +inputs: + github-token: + description: > + Token aqua authenticates its GitHub API calls with (exported as AQUA_GITHUB_TOKEN for the rest of the job). aqua resolves every github_release package through the API — the release by tag, its assets, the checksum file — and unauthenticated calls are limited to 60/hour PER IP, an IP the hosted runners share with every other tenant: "403 API rate limit exceeded" on the first tool a lint leg touches is that limit, not this repository's usage. The job's own token lifts it to a per-token budget. Default: the job's token, whose permissions the job declares (contents: read on every canonical read-only job). Pass "" to opt out — the write-capable checksum workflow does, by doctrine. + required: false + default: ${{ github.token }} runs: using: composite steps: @@ -44,7 +50,41 @@ runs: echo "${AQUA_INSTALLER_SHA256} ${tmp}/aqua-installer" | shasum -a 256 -c - fi chmod +x "${tmp}/aqua-installer" - "${tmp}/aqua-installer" -v "${AQUA_VERSION}" + # The installer picks aqua's build from `uname -m`. On the windows + # arm64 runners that answer is WRONG: Git for Windows' arm64 build + # ships an x86_64 Git Bash (git.exe is native; bash, coreutils and + # uname are not — its release notes say so), so under this shell + # `uname -m` is x86_64, the installer fetches aqua_windows_amd64, and + # that aqua then resolves EVERY package for windows/amd64: go, just, + # gotestsum, the race runtime — the whole leg emulated, and no arm64 + # coverage at all. The runner knows what it is (RUNNER_ARCH); tell the + # installer through the one input it reads. A shim on PATH, for the + # installer's process only, answering `uname -m` with aarch64: the + # installer's own checksum table already covers aqua_windows_arm64 + # and its bootstrap aqua then installs the pinned version natively — + # every byte still verified the same way, only the choice corrected. + # Self-retiring: skipped once the shell's uname is honest. + if [ "${RUNNER_OS:-}" = "Windows" ] && [ "${RUNNER_ARCH:-}" = "ARM64" ] && [ "$(uname -m)" != "aarch64" ]; then + echo "windows/arm64 runner under an emulated shell (uname -m: $(uname -m)); steering the installer to arm64" + mkdir -p "${tmp}/shim" + real_uname="$(command -v uname)" + printf '#!/usr/bin/env bash\nif [ "${1:-}" = "-m" ]; then echo aarch64; else exec "%s" "$@"; fi\n' "${real_uname}" >"${tmp}/shim/uname" + chmod +x "${tmp}/shim/uname" + PATH="${tmp}/shim:${PATH}" "${tmp}/aqua-installer" -v "${AQUA_VERSION}" + # Assert, do not assume: read the PE machine field of the installed + # binary (0xAA64 = ARM64, 0x8664 = AMD64). If this ever fails, the + # leg is silently emulated again — better red than slow and false. + exe="${AQUA_ROOT_DIR}/bin/aqua.exe" + pe_offset="$(od -An -tu4 -j 60 -N 4 "${exe}" | tr -d ' ')" + machine="$(od -An -tx2 -j "$((pe_offset + 4))" -N 2 "${exe}" | tr -d ' ')" + if [ "${machine}" != "aa64" ]; then + echo "installed aqua is not an arm64 binary (PE machine 0x${machine}); the windows/arm64 leg would run emulated amd64 tooling" >&2 + exit 1 + fi + echo "aqua: native windows/arm64 (PE machine 0x${machine})" + else + "${tmp}/aqua-installer" -v "${AQUA_VERSION}" + fi rm -rf "${tmp}" echo "${AQUA_ROOT_DIR}/bin" >>"$GITHUB_PATH" - name: Authorize the committed aqua policy @@ -52,3 +92,14 @@ runs: # must be allowed — every caller needs this, whatever it runs next. shell: bash run: aqua policy allow aqua-policy.yaml + - name: Authenticate aqua's GitHub API calls + # See the github-token input. Via env, never interpolated into the + # script; GITHUB_ENV so every later step's aqua (and the shims it links) + # sees it — that is where the downloads actually happen, lazily, on + # first use. AQUA_GITHUB_TOKEN rather than GITHUB_TOKEN: only aqua reads + # it, nothing else in the job inherits a credential it did not ask for. + if: inputs.github-token != '' + shell: bash + env: + TOKEN: ${{ inputs.github-token }} + run: echo "AQUA_GITHUB_TOKEN=${TOKEN}" >>"$GITHUB_ENV" diff --git a/.github/workflows/update-aqua-checksum.yaml b/.github/workflows/update-aqua-checksum.yaml index 15a0aa5..4da45ef 100644 --- a/.github/workflows/update-aqua-checksum.yaml +++ b/.github/workflows/update-aqua-checksum.yaml @@ -89,6 +89,14 @@ jobs: - name: Install aqua (pinned, checksum-verified) uses: ./.github/actions/setup-aqua + with: + # No token for aqua here, by doctrine: this job's token carries + # contents:write, and the update steps below run a branch-declared + # binary (the branch's limen pin). Unauthenticated API calls are + # rate-limited per runner IP; this is one job per Renovate branch, + # and a 403 here fails loudly and is rerun — a write token in the + # environment of branch-controlled code would not fail loudly. + github-token: "" - name: Regenerate aqua-checksums.json # No tool install: update-checksum only reads the manifest and hashes diff --git a/.limen/just/test-go.just b/.limen/just/test-go.just index 9631be9..64e9a24 100644 --- a/.limen/just/test-go.just +++ b/.limen/just/test-go.just @@ -47,8 +47,36 @@ unit: (_banner "test go" "unit") # ("relocation target stderr not defined") — see golang/go#52690, #54313, # #58619. On macOS with Xcode 15+, ld emits "has malformed LC_DYSYMTAB" # warnings for race builds; cosmetic, the binaries are correct (golang/go#61229). +# +# The detector does not exist everywhere. It is a prebuilt LLVM +# ThreadSanitizer runtime that Go vendors per platform (runtime/race/*.syso), +# and LLVM ships none for windows/arm64 among others — so on those hosts +# `-race` is not a slow option but a missing one, and `go build -race` +# refuses before compiling a line ("-race is not supported on GOOS/GOARCH"). +# That refusal is the probe: ask the toolchain, rather than keep a platform +# list that drifts as Go and LLVM add targets. The check is host-level, made +# before any package is looked at, so probing `unsafe` — a package with no +# source to compile — costs milliseconds and answers exactly the same as +# probing the module would. On such a host the recipe +# says so, loudly, and passes: a red leg would re-report a Go limitation on +# every push, and a silent green would hide a coverage gap that is real — +# this leg's race coverage is absent (the other legs' is not: the linux and +# macos arm64 legs run the detector natively). The skip is keyed to that +# exact message: any other failure of the probe build is a real one and +# fails the recipe as before. race: (_banner "test go" "race") - CGO_ENABLED=1 gotestsum -- -count=1 -timeout "${TEST_GO_TIMEOUT:-10m}" -ldflags=-linkmode=external -race ./... + #!/usr/bin/env bash + set -euo pipefail + export CGO_ENABLED=1 + if ! probe="$(go build -race -o /dev/null unsafe 2>&1)"; then + if printf '%s\n' "$probe" | grep -q -- '-race is not supported'; then + echo "race: SKIPPED — no race detector for $(go env GOOS)/$(go env GOARCH); ${probe}" >&2 + exit 0 + fi + printf '%s\n' "$probe" >&2 + exit 1 + fi + gotestsum -- -count=1 -timeout "${TEST_GO_TIMEOUT:-10m}" -ldflags=-linkmode=external -race ./... # Benchmarks, with allocation stats. -run '^$' deselects unit tests so only # benchmarks run — `just do test go` already covers the tests themselves. diff --git a/aqua-checksums.json b/aqua-checksums.json index b975ef1..e4ad97f 100644 --- a/aqua-checksums.json +++ b/aqua-checksums.json @@ -46,28 +46,28 @@ "algorithm": "sha256" }, { - "id": "github_release/github.com/farcloser/limen/v0.0.13/limen_0.0.13_darwin_arm64.tar.gz", - "checksum": "8739EA67AE2404A33E56EC9E89DE228C4DB73BFE37E2E814D7592289576FDBF8", + "id": "github_release/github.com/farcloser/limen/v0.0.15/limen_0.0.15_darwin_arm64.tar.gz", + "checksum": "2B5134579B4CEB587815C8040B46DB018D15ECA7CC89E1886BC60557224B8A71", "algorithm": "sha256" }, { - "id": "github_release/github.com/farcloser/limen/v0.0.13/limen_0.0.13_linux_amd64.tar.gz", - "checksum": "C5A3990CF1307CB14DA8986FF45AD634A569DD35B3E536F7694C7BD9E9BF4557", + "id": "github_release/github.com/farcloser/limen/v0.0.15/limen_0.0.15_linux_amd64.tar.gz", + "checksum": "1D8D568FBC83606B3308942D7A140A99E35FAFB4AD88776D2B50DD9B80A951F8", "algorithm": "sha256" }, { - "id": "github_release/github.com/farcloser/limen/v0.0.13/limen_0.0.13_linux_arm64.tar.gz", - "checksum": "6D19477293359E262C2E6E882974355B1F339A5249EBC1D42620783BBD23B3B0", + "id": "github_release/github.com/farcloser/limen/v0.0.15/limen_0.0.15_linux_arm64.tar.gz", + "checksum": "53AF14EC37198DF904CD41DB8D161AAC490AECCE641718102BCC65793D1F2120", "algorithm": "sha256" }, { - "id": "github_release/github.com/farcloser/limen/v0.0.13/limen_0.0.13_windows_amd64.tar.gz", - "checksum": "942522F4AB937B9DDDCFE2E369E2AF13AF64C1041934CA20D098AA9C8321FC20", + "id": "github_release/github.com/farcloser/limen/v0.0.15/limen_0.0.15_windows_amd64.tar.gz", + "checksum": "4CEA9B938B3B166B6365BABF2ECA4CADEF2433B7DBF3584B636172A0EF6DCDEB", "algorithm": "sha256" }, { - "id": "github_release/github.com/farcloser/limen/v0.0.13/limen_0.0.13_windows_arm64.tar.gz", - "checksum": "C331B8BA5495406BC1A5C6DB62549B4AB562FDD808DFB71B18D3FD6ADE3FCE42", + "id": "github_release/github.com/farcloser/limen/v0.0.15/limen_0.0.15_windows_arm64.tar.gz", + "checksum": "948C4AF4713B73543FFEA1C06B11D235DBB01002626259313713253464F3D896", "algorithm": "sha256" }, { diff --git a/aqua.yaml b/aqua.yaml index 95d5914..a05dcdb 100644 --- a/aqua.yaml +++ b/aqua.yaml @@ -18,9 +18,11 @@ registries: packages: # --- go install tools (local registry, GOSUMDB-verified) --- - - name: github.com/google/go-licenses/v2@v2.0.1 + - name: github.com/google/go-licenses/v2 + version: v2.0.1 # renovate: depName=_go/github.com/google/go-licenses/v2 registry: local - - name: github.com/vbatts/git-validation@v1.2.2 + - name: github.com/vbatts/git-validation + version: v1.2.2 # renovate: depName=_go/github.com/vbatts/git-validation registry: local - name: golang.org/x/vuln/cmd/govulncheck@v1.5.0 registry: local @@ -29,13 +31,15 @@ packages: # Pseudo-version: the nested cmd/dot module carries no tags upstream. - name: github.com/goccy/go-graphviz/cmd/dot@v0.0.0-20251129032125-76e04975df88 registry: local - - name: github.com/farcloser/godolint/cmd/godolint@v0.1.0 + - name: github.com/farcloser/godolint/cmd/godolint + version: v0.1.0 # renovate: depName=_go/github.com/farcloser/godolint/cmd/godolint registry: local # --- farcloser tools (local registry; standard once registered upstream) --- - - name: farcloser/limen@v0.0.13 # renovate: depName=farcloser/limen + - name: farcloser/limen@v0.0.15 # renovate: depName=farcloser/limen registry: local # --- toolchain + binary-release tools (standard registry, aqua-verified) --- - - name: golang/go@go1.26.5 + - name: golang/go + version: go1.26.5 # renovate: depName=golang/go - name: casey/just@1.57.0 - name: koalaman/shellcheck@v0.11.0 - name: golangci/golangci-lint@v2.12.2 @@ -44,5 +48,6 @@ packages: - name: goreleaser/goreleaser@v2.17.1 - name: sigstore/cosign@v3.1.1 - name: gotestyourself/gotestsum@v1.13.0 - - name: jqlang/jq@jq-1.8.2 + - name: jqlang/jq + version: jq-1.8.2 # renovate: depName=jqlang/jq - name: cli/cli@v2.96.0