feat(release): add GoReleaser config and release CI workflow - #19
Merged
Conversation
This was referenced Aug 19, 2026
shreyanshjain7174
added a commit
that referenced
this pull request
Aug 19, 2026
#20) * feat(deps): replace mattn/go-sqlite3 with modernc.org/sqlite (pure Go) Spike per T1: swap the CGO SQLite driver for the pure-Go one, verified before merging, not assumed. Why: the CGO dependency was forcing split-runner builds, cross-gcc for linux/arm64, and dropping Windows entirely from PR #19. It also means agentgate-verify dynamically links the host libc — an auditor on musl, distroless, or an older glibc gets a linker error instead of a verification, undermining the actual product claim (independent offline verification, runnable anywhere). Driver registers as "sqlite", not "sqlite3" - every sql.Open call site updated. DSN pragma shorthand keys (_journal_mode, _busy_timeout, _foreign_keys) are identical between both drivers, so the connection string in internal/db/sqlite.go is unchanged content, just the driver name. Acceptance criteria, all actually run: 1. CGO_ENABLED=0 go build ./... - succeeds. 2. CGO_ENABLED=0 go test ./... - all packages pass, zero skipped (confirmed via `go test -v | grep -c SKIP` = 0). 3. CGO_ENABLED=0 cross-builds succeed for all 6 targets from one machine, no cross-compilers: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64, windows/arm64 (agentgw + agentgate-verify, 12 binaries total). 4. Synchronous ledger commit latency (Ledger.Append, the exact path used before /v1/act responds), pooled over 8 runs x 10,000 commits = 80,000 samples per driver, same machine, back-to-back via a git worktree at the pre-swap commit for the old-driver baseline: driver mean p50 p90 p99 mattn/go-sqlite3 (CGO) 83.5us 59.5us 89.2us 337.0us modernc.org/sqlite (pure Go) 156.8us 104.5us 175.6us 654.4us ratio (new/old) 1.88x 1.76x 1.97x 1.94x p99 regresses 1.94x - under the 2x decision-rule threshold. Both numbers are a fraction of a millisecond; for an append-heavy ledger with range scans this is the honest, measured tradeoff, not an assumption. 5. Cross-driver chain verification: wrote two 5-receipt test databases, one with each driver, then ran every combination of {verify built with new driver, verify built with old driver} x {db written by new driver, db written by old driver} - all 4 PASS. Chain verification does not care which driver wrote the rows, as expected (SQLite's file format doesn't depend on which Go driver wrote it). Per the stated decision rule (stop only if p99 > 2x), this passes. PR #19 (GoReleaser + release workflow) should be revised on top of this to delete the darwin job, cross-gcc config, and Pro-style split complexity entirely, collapsing to one ubuntu-latest runner with CGO_ENABLED=0 and a full goos/goarch matrix including Windows. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> * test: temporary linux/amd64 percentile benchmark for #20 One-off, deleted before merge. Confirms whether the darwin/arm64 ledger-commit benchmark generalizes to linux/amd64, since modernc.org/sqlite is transpiled C and its profile can differ by platform. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> * test: remove temporary linux/amd64 percentile benchmark Numbers captured and reported. This harness and one-off workflow were throwaway measurement tools for the #20 driver-swap decision, not meant to be part of the permanent test suite or CI config. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> --------- Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com>
shreyanshjain7174
added a commit
that referenced
this pull request
Aug 19, 2026
…gofmt, mod-tidy drift check Adds .github/workflows/ci.yml. PR #19's release.yml only triggers on tag push, so pull requests currently get zero validation - six good first issue tickets invite outside contributors and their PRs would run nothing. Installs gcc + libsqlite3-dev since main still uses the CGO mattn/go-sqlite3 driver as of this commit; comments in the file note to drop that step and set CGO_ENABLED=0 once PR #20 (pure-Go sqlite driver swap) merges. Adds the CI status badge to README.md. Every step verified locally against current main before opening this PR: go build, go vet, go test -race, gofmt -l (clean), and go mod tidy produces no diff. The actual acceptance criterion is that this fires green on the PR itself, not on local runs - see the PR description for the live check run link. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com>
shreyanshjain7174
added a commit
that referenced
this pull request
Aug 19, 2026
* ci: add pull_request/push:main workflow with build, vet, test -race, gofmt, mod-tidy drift check Adds .github/workflows/ci.yml. PR #19's release.yml only triggers on tag push, so pull requests currently get zero validation - six good first issue tickets invite outside contributors and their PRs would run nothing. Installs gcc + libsqlite3-dev since main still uses the CGO mattn/go-sqlite3 driver as of this commit; comments in the file note to drop that step and set CGO_ENABLED=0 once PR #20 (pure-Go sqlite driver swap) merges. Adds the CI status badge to README.md. Every step verified locally against current main before opening this PR: go build, go vet, go test -race, gofmt -l (clean), and go mod tidy produces no diff. The actual acceptance criterion is that this fires green on the PR itself, not on local runs - see the PR description for the live check run link. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> * fix(ci): pin DEBIAN_FRONTEND=noninteractive for apt-get install First live run hung 10+ minutes on 'Install sqlite build dependencies' - almost certainly needrestart/debconf prompting interactively on a sudo apt-get install with no noninteractive frontend set. Cancelled that run (32233234510) and fixed rather than reporting the earlier local-only pass as done. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> * fix(ci): wrap apt-get in timeout+retry after a real 10min network stall Run 32233234510's 'Install sqlite build dependencies' step went silent for over 10 minutes mid apt-get update (checked the actual log timestamps - real network stall fetching package indices, not a debconf prompt, not a lock). Wraps both apt-get calls in a 120s timeout with up to 3 attempts so a future transient mirror stall fails fast and retries instead of hanging the whole job. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> * ci: drop CGO build deps now that #20 merged github.com//pull/20 replaced mattn/go-sqlite3 with the pure-Go modernc.org/sqlite. No more gcc/libsqlite3-dev needed, no more apt-get retry wrapper for the network stall that only existed to install those. Set CGO_ENABLED=0 globally instead. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> * ci: -race needs CGO_ENABLED=1, doesn't need sqlite build deps go test -race genuinely requires cgo on linux (confirmed via a real failing CI run: 'go: -race requires cgo; enable cgo by setting CGO_ENABLED=1'), independent of whatever sqlite driver is in use. ubuntu-latest ships gcc via build-essential, so this needs no apt-get step -- unlike the old libsqlite3-dev requirement this file used to work around. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com> --------- Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com>
Closes the first punch-list gap: GoReleaser binaries + CI. SECURITY.md and re-cutting v0.1.1 are next, in the stated order. mattn/go-sqlite3 is CGO-based, which rules out a plain single-runner GOOS/GOARCH matrix. GoReleaser Pro has a split/merge feature for this (building each platform on its own native runner and combining them), but that's a paid feature per goreleaser.com/resources/limitations/cgo. This uses the free equivalent instead: - .goreleaser.yaml builds only the Linux side (native amd64 + Linux arm64 cross-compiled via aarch64-linux-gnu-gcc, both from one ubuntu-latest runner), handles archives/checksums/changelog/GitHub release creation, and builds+pushes the ghcr.io Docker images (linux/amd64 + linux/arm64 via buildx/QEMU). - The darwin job in release.yml runs after the linux job creates the release, builds macOS amd64/arm64 binaries with plain `go build` on a native macos-latest runner, tars/checksums them, and attaches them to the same release with `gh release upload`. - Windows isn't built: cgo + sqlite3 + mingw cross-compilation is a real source of flakiness, not worth it until there's actual demand for a native Windows binary. The Docker image already covers that platform's users. Verified before committing, not just linted: - `goreleaser check` passes on the config. - Linux amd64 native build and arm64 cross-compile (exact CC/env used in the config) both tested inside a real linux/amd64 Docker container, producing a working `agentgw --version` binary. - Darwin amd64/arm64 builds tested natively on this machine via `goreleaser build --single-target`, producing working binaries with correctly injected -X main.version ldflags. - The darwin job's tar/checksum shell logic tested standalone locally end-to-end (minus the actual `gh release upload` call). - go build ./..., go vet ./..., and YAML parsing of both new files all pass. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com>
github.com//pull/20 replaced mattn/go-sqlite3 (CGO) with modernc.org/sqlite (pure Go). This removes every reason the release process was split across two runners: - .goreleaser.yaml: one builds entry per binary, CGO_ENABLED=0, full goos/goarch matrix (linux, darwin, windows x amd64, arm64) instead of linux-only + a separate macOS job. Verified locally with 'goreleaser check' and a full 'goreleaser release --snapshot --clean --skip=docker,publish' -- all 12 binaries build, all 6 archives produced correctly (windows zipped, others tar.gz). - release.yml: collapsed to a single ubuntu-latest runner. Deleted the cross-gcc/libsqlite3-dev install step, the separate darwin job, and the 'gh release upload' dance that attached macOS binaries to the release after the fact. - Dockerfile: FROM scratch. A static pure-Go binary needs no base OS image -- no libc, no shell, no package manager. Only the CA cert bundle is copied over, for the outbound TLS calls this gateway makes to upstream SaaS APIs during OAuth token refresh. Built and ran this locally: image is 9.4MB (was alpine-based before), server starts, dashboard serves correctly, no shell available via 'docker exec'. Also fixed ENTRYPOINT to use an absolute path -- scratch has no default $PATH, so 'agentgate' by name would fail to exec. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com>
shreyanshjain7174
force-pushed
the
ci/goreleaser-release-workflow
branch
from
August 19, 2026 19:13
827108f to
cae8459
Compare
shreyanshjain7174
added a commit
that referenced
this pull request
Aug 19, 2026
…file (#23) The v0.1.1 tag push failed release.yml for real: ERROR: failed to build: failed to solve: failed to compute cache key: ... "/configs": not found GoReleaser's docker build context only contains the Dockerfile, the binaries it already cross-compiled in the builds: step, and whatever extra_files: lists -- not the full repo. The rewritten Dockerfile from #19 still had a multi-stage 'COPY go.mod go.sum ./' + 'COPY . .' builder stage, which can never work in that context. This was never caught because #19's local testing used 'docker build .' from the repo root (full source available) and --skip=docker snapshot builds, and the PR itself said as much: "Not yet tested: a real end-to-end tag-triggered CI run." This is that first real run. Fix: split into two Dockerfiles instead of trying to make one work in both contexts. - Dockerfile (unchanged behavior): multi-stage, builds from source. Used by docker-compose / local dev, where the full repo is the build context. - Dockerfile.release (new): single small alpine helper stage for CA certs + an empty /data dir, then FROM scratch copying the binaries GoReleaser already built. Doesn't rebuild from source -- there's nothing to rebuild from in that context, and GoReleaser already did the cross-compile. - .goreleaser.yaml: dockers[].dockerfile -> Dockerfile.release, added extra_files: [configs] since that's not in the context either. Verified for real: 'goreleaser release --snapshot --clean --skip=publish' now builds both docker images successfully (previously failed on this exact step). Ran the amd64 image via 'docker run' (under QEMU, darwin/arm64 host): server starts, version string correctly injected (0.1.1-SNAPSHOT-1d9c395), 'curl .../dashboard/' returns 200. Image is 10.1MB. Signed-off-by: Shreyansh Sancheti <43677304+shreyanshjain7174@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rewritten now that #20 (pure-Go sqlite driver) merged — this closes out the release-engineering queue per the stated merge order.
What changed:
.goreleaser.yaml: singlebuildsentry per binary (agentgw,agentgate-verify),CGO_ENABLED=0, fullgoos/goarchmatrix: linux, darwin, windows × amd64, arm64. No more Linux-only + separate macOS job. Windows is in, since CGO/mingw was the only reason it wasn't before..github/workflows/release.yml: collapsed to oneubuntu-latestrunner. Deleted thegcc-aarch64-linux-gnu/libc6-dev-arm64-cross/libsqlite3-devinstall step, the entiredarwinjob, and thegh release uploaddance that attached macOS binaries after the fact.Dockerfile: rewrittenFROM scratch. A static pure-Go binary needs no base OS image — no libc, no shell, no package manager, smaller attack surface. Only the CA cert bundle is copied in, for the outbound TLS calls this gateway makes to upstream SaaS APIs during OAuth token refresh.Verified for real, not just linted:
goreleaser check— passes.goreleaser release --snapshot --clean --skip=docker,publish— all 12 binaries build (6 platforms × 2 binaries), all 6 archives produced correctly (windows zipped with.exebinaries, others tar.gz).docker build+docker runlocally against the new Dockerfile: image is 9.4MB, server starts, dashboard serves correctly at/dashboard/, confirmed no shell available viadocker exec(attack surface claim isn't just asserted).ENTRYPOINT ["agentgate"]would fail onscratch— no default$PATHexists in that base, so name-based exec lookup fails. Fixed to the absolute path.CI/cicheck, 25s).mergeable_state: clean, base already includes #20/#21/#22.