From 1a4c38b59e2c2b915fbac84f9ab064751e648cf4 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sun, 27 Sep 2026 06:22:48 +0300 Subject: [PATCH 1/2] ci: pin workflow actions by commit SHA Floating major tags can be moved to arbitrary code by whoever controls the action repository. The release job holds packages:write and contents:write, so a retargeted tag would run with the rights to overwrite the published image. Pin each action to the commit of the latest release in the major already in use. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/release.yml | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39ffbc1..a6c271b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,8 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 with: go-version-file: go.mod - name: build @@ -26,10 +26,10 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 with: go-version-file: go.mod - - uses: golangci/golangci-lint-action@v7 + - uses: golangci/golangci-lint-action@9fae48acfc02a90574d7c304a1758ef9895495fa # v7.0.1 with: version: v2.12.2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c251bac..8e753d0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,22 +19,22 @@ jobs: image: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - uses: docker/setup-buildx-action@v3 - - uses: docker/login-action@v3 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: ${{ env.IMAGE }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=raw,value=latest - - uses: docker/build-push-action@v6 + - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . # pg_query_go links the embedded PostgreSQL parser via cgo and the @@ -52,7 +52,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 with: fetch-depth: 0 - name: Create GitHub Release From 19e2828a165faaf8fad539df4b70c89acac02caf Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sun, 27 Sep 2026 06:23:49 +0300 Subject: [PATCH 2/2] feat(image): publish linux/amd64 and linux/arm64 The image was amd64-only because the Dockerfile hardcoded GOARCH=amd64, so arm64 nodes could not run the proxy at all. cgo stays on: pg_query_go compiles the libpg_query C parser into the binary. The build stage now runs on the build host and cross-compiles with Debian's cross gcc for the target arch instead of building under QEMU, which would compile the whole C parser emulated. The cross toolchain links against bookworm's glibc, the same one the distroless/base-debian12 runtime ships. Release publishes both platforms as one index. CI builds the image for both platforms without pushing, so a change that breaks the arm64 cross-build fails on the pull request instead of at release time. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin --- .github/workflows/ci.yml | 11 +++++++++++ .github/workflows/release.yml | 5 ++--- Dockerfile | 31 ++++++++++++++++++++++++++++--- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6c271b..566b6eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,17 @@ jobs: - name: test run: go test -race -count=1 ./... + image: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: false + lint: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8e753d0..d6784d3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,9 +37,8 @@ jobs: - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . - # pg_query_go links the embedded PostgreSQL parser via cgo and the - # Dockerfile pins GOARCH=amd64, so the image is amd64-only for now. - platforms: linux/amd64 + # The Dockerfile cross-compiles on the runner, so no QEMU is needed. + platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index b4eca0e..b3bacaf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,27 @@ # Multi-stage image for the keycloak-kms-proxy server. pg_query_go links the # C PostgreSQL parser via cgo, so the binary needs glibc at runtime — we use # distroless/base-debian12 (minimal, nonroot, ships glibc). - -FROM golang:1.26.2-bookworm AS build +# +# The build stage runs on the build host and cross-compiles with a Debian +# cross gcc: compiling libpg_query under emulation takes far longer, and the +# cross toolchain links against the same bookworm glibc as the runtime base. + +FROM --platform=$BUILDPLATFORM golang:1.26.2-bookworm AS build + +ARG BUILDARCH +ARG TARGETARCH + +RUN set -eu; \ + if [ "$BUILDARCH" != "$TARGETARCH" ]; then \ + case "$TARGETARCH" in \ + amd64) triplet=x86-64-linux-gnu ;; \ + arm64) triplet=aarch64-linux-gnu ;; \ + *) echo "unsupported TARGETARCH: $TARGETARCH" >&2; exit 1 ;; \ + esac; \ + apt-get update; \ + apt-get install --yes --no-install-recommends "gcc-$triplet" "libc6-dev-$TARGETARCH-cross"; \ + rm -rf /var/lib/apt/lists/*; \ + fi WORKDIR /src @@ -13,7 +32,13 @@ RUN go mod download COPY . . ARG VERSION=dev -RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \ +RUN set -eu; \ + case "$TARGETARCH" in \ + amd64) cross=x86_64-linux-gnu-gcc ;; \ + arm64) cross=aarch64-linux-gnu-gcc ;; \ + esac; \ + if [ "$BUILDARCH" != "$TARGETARCH" ]; then export CC="$cross"; fi; \ + CGO_ENABLED=1 GOOS=linux GOARCH="$TARGETARCH" \ go build -trimpath \ -ldflags="-s -w -X main.version=${VERSION}" \ -o /out/proxy ./cmd/proxy