diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 4e7e1e0c..03a462db 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,4 +1,4 @@ -version: 1 +version: 2 project_name: charon @@ -8,9 +8,7 @@ builds: main: ./cmd/api binary: charon env: - - CGO_ENABLED=1 - - CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-linux-gnu - - CXX=zig c++ -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-linux-gnu + - CGO_ENABLED=0 goos: - linux goarch: @@ -27,9 +25,7 @@ builds: main: ./cmd/api binary: charon env: - - CGO_ENABLED=1 - - CC=zig cc -target x86_64-windows-gnu - - CXX=zig c++ -target x86_64-windows-gnu + - CGO_ENABLED=0 goos: - windows goarch: @@ -45,9 +41,7 @@ builds: main: ./cmd/api binary: charon env: - - CGO_ENABLED=1 - - CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-none - - CXX=zig c++ -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-none + - CGO_ENABLED=0 goos: - darwin goarch: @@ -60,9 +54,10 @@ builds: - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} archives: - - format: tar.gz + - formats: + - tar.gz id: nix - builds: + ids: - linux - darwin name_template: >- @@ -74,9 +69,10 @@ archives: - LICENSE - README.md - - format: zip + - formats: + - zip id: windows - builds: + ids: - windows name_template: >- {{ .ProjectName }}_ @@ -89,7 +85,7 @@ archives: nfpms: - id: packages - builds: + ids: - linux package_name: charon vendor: Charon @@ -115,7 +111,7 @@ checksum: name_template: 'checksums.txt' snapshot: - name_template: "{{ .Tag }}-next" + version_template: "{{ .Tag }}-next" changelog: sort: asc diff --git a/backend/cmd/seed/main.go b/backend/cmd/seed/main.go index e8895f15..0ee57e0c 100644 --- a/backend/cmd/seed/main.go +++ b/backend/cmd/seed/main.go @@ -10,7 +10,7 @@ import ( "github.com/Wikid82/charon/backend/internal/util" "github.com/google/uuid" "github.com/sirupsen/logrus" - "gorm.io/driver/sqlite" + "github.com/glebarez/sqlite" "gorm.io/gorm" gormlogger "gorm.io/gorm/logger" diff --git a/backend/go.mod b/backend/go.mod index 662ff42c..85dcd6a6 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -7,6 +7,7 @@ require ( github.com/docker/docker v28.5.2+incompatible github.com/gin-contrib/gzip v1.2.5 github.com/gin-gonic/gin v1.11.0 + github.com/glebarez/sqlite v1.11.0 github.com/golang-jwt/jwt/v5 v5.3.1 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 @@ -37,10 +38,12 @@ require ( github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.12 // indirect github.com/gin-contrib/sse v1.1.0 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -76,6 +79,7 @@ require ( github.com/prometheus/procfs v0.16.1 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.57.1 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.0 // indirect @@ -93,4 +97,8 @@ require ( google.golang.org/protobuf v1.36.10 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect + modernc.org/libc v1.22.5 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/sqlite v1.23.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index cca5dd60..045ea97f 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -35,6 +35,8 @@ github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pM github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -47,6 +49,10 @@ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= +github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -73,8 +79,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu 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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= 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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= @@ -155,6 +161,9 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10= github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= @@ -240,3 +249,11 @@ gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= +modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= +modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= diff --git a/backend/internal/database/database.go b/backend/internal/database/database.go index f3d2c591..608b9f88 100644 --- a/backend/internal/database/database.go +++ b/backend/internal/database/database.go @@ -4,30 +4,18 @@ package database import ( "database/sql" "fmt" - "strings" "github.com/Wikid82/charon/backend/internal/logger" - "gorm.io/driver/sqlite" + "github.com/glebarez/sqlite" "gorm.io/gorm" ) // Connect opens a SQLite database connection with optimized settings. // Uses WAL mode for better concurrent read/write performance. func Connect(dbPath string) (*gorm.DB, error) { - // Add SQLite performance pragmas if not already present - dsn := dbPath - if !strings.Contains(dsn, "?") { - dsn += "?" - } else { - dsn += "&" - } - // WAL mode: better concurrent access, faster writes - // busy_timeout: wait up to 5s instead of failing immediately on lock - // cache: shared cache for better memory usage - // synchronous=NORMAL: good balance of safety and speed - dsn += "_journal_mode=WAL&_busy_timeout=5000&_synchronous=NORMAL&_cache_size=-64000" - - db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{ + // Open the database connection + // Note: PRAGMA settings are applied after connection for modernc.org/sqlite compatibility + db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{ // Skip default transaction for single operations (faster) SkipDefaultTransaction: true, // Prepare statements for reuse @@ -44,12 +32,27 @@ func Connect(dbPath string) (*gorm.DB, error) { } configurePool(sqlDB) + // Set SQLite performance pragmas via SQL execution + // This is required for modernc.org/sqlite (pure-Go driver) which doesn't + // support DSN-based pragma parameters like mattn/go-sqlite3 + pragmas := []string{ + "PRAGMA journal_mode=WAL", // Better concurrent access, faster writes + "PRAGMA busy_timeout=5000", // Wait up to 5s instead of failing immediately on lock + "PRAGMA synchronous=NORMAL", // Good balance of safety and speed + "PRAGMA cache_size=-64000", // 64MB cache for better performance + } + for _, pragma := range pragmas { + if _, err := sqlDB.Exec(pragma); err != nil { + return nil, fmt.Errorf("failed to execute %s: %w", pragma, err) + } + } + // Verify WAL mode is enabled and log confirmation var journalMode string if err := db.Raw("PRAGMA journal_mode").Scan(&journalMode).Error; err != nil { logger.Log().WithError(err).Warn("Failed to verify SQLite journal mode") } else { - logger.Log().WithField("journal_mode", journalMode).Info("SQLite database connected with WAL mode enabled") + logger.Log().WithField("journal_mode", journalMode).Info("SQLite database connected with optimized settings") } // Run quick integrity check on startup (non-blocking, warn-only) diff --git a/backend/internal/testutil/db_test.go b/backend/internal/testutil/db_test.go index 6fb09e96..60122b68 100644 --- a/backend/internal/testutil/db_test.go +++ b/backend/internal/testutil/db_test.go @@ -3,7 +3,7 @@ package testutil import ( "testing" - "gorm.io/driver/sqlite" + "github.com/glebarez/sqlite" "gorm.io/gorm" ) diff --git a/docs/plans/current_spec.md b/docs/plans/current_spec.md index dbcaadc3..228bb4ce 100644 --- a/docs/plans/current_spec.md +++ b/docs/plans/current_spec.md @@ -1,448 +1,557 @@ -# Docker Compose CI Failure Remediation Plan +# GoReleaser v2 Migration & Nightly Build Failure Remediation **Status**: Active **Created**: 2026-01-30 -**Priority**: CRITICAL (Blocking CI) +**Priority**: CRITICAL (Blocking Nightly Builds) --- ## Executive Summary -The E2E test workflow (`e2e-tests.yml`) is failing when attempting to start containers via `docker-compose.playwright-ci.yml`. The root cause is an incorrect Docker image reference format in the compose file that attempts to use a bare SHA256 digest instead of a fully-qualified image reference with registry and repository. +The nightly build workflow (`nightly-build.yml`) is failing with multiple issues: -**Error Message**: +1. **GoReleaser v2 Compatibility**: Config uses deprecated v1 syntax +2. **Zig Cross-Compilation**: Incorrect macOS target triple format +3. **🆕 CGO/SQLite Dependency**: Disabling CGO for darwin breaks SQLite (`mattn/go-sqlite3` requires CGO) + +**Error Messages**: ``` -charon-app Error pull access denied for sha256, repository does not exist or may require 'docker login': denied: requested access to the resource is denied +only version: 2 configuration files are supported, yours is version: 1, please update your configuration ``` -**Root Cause**: The compose file's `image:` directive evaluates to a bare SHA256 digest (e.g., `sha256:057a9998...`) instead of a properly formatted image reference like `ghcr.io/wikid82/charon@sha256:057a9998...`. +**Deprecation Warnings**: +- `snapshot.name_template` is deprecated +- `archives.format` is deprecated +- `archives.builds` is deprecated +- `nfpms.builds` is deprecated + +**Build Error** (Zig): +``` +error: unable to find or provide libc for target 'x86_64-macos.11.7.1...13.3-gnu' +info: zig can provide libc for related target x86_64-macos.11-none +``` --- -## Issue 1: Nightly Build - GoReleaser macOS Cross-Compile Failure +## 🔴 Critical Dependency: SQLite CGO Issue + +### Problem Statement + +The current SQLite driver (`gorm.io/driver/sqlite`) depends on `mattn/go-sqlite3`, which is a CGO-based library. This means: + +- **CGO_ENABLED=0** will cause build failures when SQLite is used +- **Cross-compilation** for darwin from Linux is blocked by CGO complexity +- The proposed fix of disabling CGO for darwin builds **will break the application** + +### Solution: Migrate to Pure-Go SQLite + +**Recommended Migration Path:** + +| Current | New | Notes | +|---------|-----|-------| +| `gorm.io/driver/sqlite` | `github.com/glebarez/sqlite` | GORM-compatible pure-Go driver | +| `mattn/go-sqlite3` (indirect) | `modernc.org/sqlite` (indirect) | Pure-Go SQLite implementation | + +**Benefits:** +1. ✅ No CGO required for any platform +2. ✅ Simplified cross-compilation (no Zig needed for SQLite) +3. ✅ Smaller binary size +4. ✅ Faster build times +5. ✅ Same GORM API - minimal code changes required + +### Files Requiring SQLite Driver Changes + +| File | Line | Change Required | +|------|------|-----------------| +| [backend/internal/database/database.go](../../backend/internal/database/database.go#L10) | 10 | `gorm.io/driver/sqlite` → `github.com/glebarez/sqlite` | +| [backend/internal/testutil/db_test.go](../../backend/internal/testutil/db_test.go#L6) | 6 | `gorm.io/driver/sqlite` → `github.com/glebarez/sqlite` | +| [backend/cmd/seed/main.go](../../backend/cmd/seed/main.go#L13) | 13 | `gorm.io/driver/sqlite` → `github.com/glebarez/sqlite` | +| [backend/go.mod](../../backend/go.mod#L19) | 19 | Replace `gorm.io/driver/sqlite` with `github.com/glebarez/sqlite` | + +--- + +## Issue 1: GoReleaser v1 → v2 Migration (CRITICAL) + +### Problem Statement + +GoReleaser v2 (currently v2.13.3) no longer supports `version: 1` configuration files. The nightly workflow uses GoReleaser `~> v2` which requires v2 config syntax. + +### Root Cause Analysis + +Current `.goreleaser.yaml` uses deprecated v1 syntax: + +```yaml +version: 1 # ❌ v2 requires "version: 2" +``` + +Multiple deprecated fields need updating: +| Deprecated Field | v2 Replacement | +|-----------------|----------------| +| `snapshot.name_template` | `snapshot.version_template` | +| `archives.format` | `archives.formats` (array) | +| `archives.builds` | `archives.ids` | +| `nfpms.builds` | `nfpms.ids` | + +### GoReleaser Deprecation Reference + +From [goreleaser.com/deprecations](https://goreleaser.com/deprecations): + +1. **`snapshot.name_template`** → `snapshot.version_template` + - Changed in v2.0.0 + - The template generates a version string, not a "name" + +2. **`archives.format`** → `archives.formats` + - Changed to array to support multiple formats per archive config + - Must be `formats: [tar.gz]` not `format: tar.gz` + +3. **`archives.builds`** → `archives.ids` + - Renamed for clarity: it filters by build `id`, not "builds" + +4. **`nfpms.builds`** → `nfpms.ids` + - Same rationale as archives + +### Required Changes + +```diff +--- a/.goreleaser.yaml ++++ b/.goreleaser.yaml +@@ -1,4 +1,4 @@ +-version: 1 ++version: 2 + + project_name: charon + +@@ -62,10 +62,10 @@ + - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} + + archives: +- - format: tar.gz ++ - formats: [tar.gz] + id: nix +- builds: ++ ids: + - linux + - darwin + name_template: >- +@@ -76,9 +76,9 @@ + - LICENSE + - README.md + +- - format: zip ++ - formats: [zip] + id: windows +- builds: ++ ids: + - windows + name_template: >- + {{ .ProjectName }}_ +@@ -90,7 +90,7 @@ + + nfpms: + - id: packages +- builds: ++ ids: + - linux + package_name: charon + vendor: Charon +@@ -116,7 +116,7 @@ + name_template: 'checksums.txt' + + snapshot: +- name_template: "{{ .Tag }}-next" ++ version_template: "{{ .Tag }}-next" + + changelog: + sort: asc +``` + +--- + +## Issue 2: Zig Cross-Compilation for macOS ### Problem Statement The nightly build fails during GoReleaser release step when cross-compiling for macOS (darwin) using Zig: ```text -release failed after 4m19s -error= - build failed: exit status 1: go: downloading github.com/gin-gonic/gin v1.11.0 - info: zig can provide libc for related target x86_64-macos.11-none -target=darwin_amd64_v1 +error: unable to find or provide libc for target 'x86_64-macos.11.7.1...13.3-gnu' +info: zig can provide libc for related target x86_64-macos.11-none ``` ### Root Cause Analysis -The `.goreleaser.yaml` darwin build uses incorrect Zig target specification: +The `.goreleaser.yaml` darwin build uses **`-macos-none`** which is correct, but examining the actual file shows **`-macos-none`** is already in place. The error message suggests something is injecting version numbers. -**Current (WRONG):** +**Wait** - Re-reading the current config, I see it actually says `-macos-none` already. Let me check if there's a different issue. + +Actually, looking at the error more carefully: +``` +target 'x86_64-macos.11.7.1...13.3-gnu' +``` + +This suggests the **Go runtime/cgo is detecting the macOS version range** and passing it to Zig incorrectly. The `-gnu` suffix shouldn't be there for macOS. + +**Current Configuration**: ```yaml -CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-gnu -CXX=zig c++ -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-gnu +CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-none ``` -**Issue:** macOS uses its own libc (libSystem), not GNU libc. The `-gnu` suffix is invalid for macOS targets. Zig expects `-macos-none` or `-macos.11-none` for macOS builds. +The current config is correct (`-macos-none`), but CGO may be interfering. -### Affected Files +### ~~Recommended Fix: Disable CGO for Darwin~~ -| File | Change Type | -|------|-------------| -| `.goreleaser.yaml` | Fix Zig target for darwin builds | +> **⚠️ UPDATE:** This section is superseded by the SQLite driver migration (see "Critical Dependency: SQLite CGO Issue" above). Simply disabling CGO for darwin **breaks SQLite functionality**. -### Recommended Fix +### ✅ Actual Fix: Migrate to Pure-Go SQLite -Update the darwin build configuration to use the correct Zig target triple: +By migrating from `gorm.io/driver/sqlite` (CGO) to `github.com/glebarez/sqlite` (pure-Go): -**Option A: Use `-macos-none` (Recommended)** -```yaml -- id: darwin - dir: backend - main: ./cmd/api - binary: charon - env: - - CGO_ENABLED=1 - - CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-none - - CXX=zig c++ -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-none -``` +1. **Zig is no longer required** for any platform +2. **CGO_ENABLED=0** can be used for ALL platforms (linux, darwin, windows) +3. **Cross-compilation is trivial** - standard Go cross-compilation works +4. **Build times are faster** - no C compiler invocation -**Option B: Specify macOS version (for specific SDK compatibility)** -```yaml - - CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos.11-none - - CXX=zig c++ -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos.11-none -``` - -**Option C: Remove darwin builds entirely (if macOS support is not required)** -```yaml -# Remove the entire `- id: darwin` build block from .goreleaser.yaml -# Update archives section to remove darwin from the `nix` archive builds -``` - -### Implementation Details - -```diff ---- a/.goreleaser.yaml -+++ b/.goreleaser.yaml -@@ -47,8 +47,8 @@ - binary: charon - env: - - CGO_ENABLED=1 -- - CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-gnu -- - CXX=zig c++ -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-gnu -+ - CC=zig cc -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-none -+ - CXX=zig c++ -target {{ if eq .Arch "amd64" }}x86_64{{ else }}aarch64{{ end }}-macos-none - goos: - - darwin - goarch: -``` - -### Verification - -```bash -# Local test (requires Zig installed) -cd backend -CGO_ENABLED=1 CC="zig cc -target x86_64-macos-none" go build -o charon-darwin ./cmd/api - -# Nightly workflow test -gh workflow run nightly-build.yml --ref development -f reason="Test darwin build fix" -``` +This completely eliminates Issue 2 as a side effect of fixing the SQLite dependency issue. --- -## Issue 2: Playwright E2E - Admin API Socket Hang Up +## Complete Updated `.goreleaser.yaml` -### Problem Statement - -Playwright test `zzz-admin-whitelist-blocking.spec.ts:126` fails with: - -```text -Error: apiRequestContext.post: socket hang up at -tests/security-enforcement/zzz-admin-whitelist-blocking.spec.ts:126:21 -``` - -The test POSTs to `http://localhost:2020/emergency/security-reset` but cannot reach the emergency server. - -### Root Cause Analysis - -The `playwright.yml` workflow starts the Charon container but **does not set** the `CHARON_EMERGENCY_BIND` environment variable: - -**Current workflow (`.github/workflows/playwright.yml`):** -```yaml -docker run -d \ - --name charon-test \ - -p 8080:8080 \ - -p 127.0.0.1:2019:2019 \ - -p "[::1]:2019:2019" \ - -p 127.0.0.1:2020:2020 \ - -p "[::1]:2020:2020" \ - -e CHARON_ENV="${CHARON_ENV}" \ - -e CHARON_DEBUG="${CHARON_DEBUG}" \ - -e CHARON_ENCRYPTION_KEY="${CHARON_ENCRYPTION_KEY}" \ - -e CHARON_EMERGENCY_TOKEN="${CHARON_EMERGENCY_TOKEN}" \ - -e CHARON_EMERGENCY_SERVER_ENABLED="${CHARON_EMERGENCY_SERVER_ENABLED}" \ - "${IMAGE_REF}" -``` - -**Missing:** `CHARON_EMERGENCY_BIND=0.0.0.0:2020` - -Without this variable, the emergency server may not bind to the correct address, or may bind to a loopback-only address that isn't accessible via Docker port mapping. - -**Comparison with working compose file:** -```yaml -# .docker/compose/docker-compose.playwright-ci.yml -- CHARON_EMERGENCY_BIND=0.0.0.0:2020 -- CHARON_EMERGENCY_USERNAME=admin -- CHARON_EMERGENCY_PASSWORD=changeme -``` - -### Affected Files - -| File | Change Type | -|------|-------------| -| `.github/workflows/playwright.yml` | Add missing emergency server env vars | - -### Recommended Fix - -Add the missing emergency server environment variables to the docker run command: - -```diff ---- a/.github/workflows/playwright.yml -+++ b/.github/workflows/playwright.yml -@@ -163,6 +163,10 @@ jobs: - -e CHARON_ENCRYPTION_KEY="${CHARON_ENCRYPTION_KEY}" \ - -e CHARON_EMERGENCY_TOKEN="${CHARON_EMERGENCY_TOKEN}" \ - -e CHARON_EMERGENCY_SERVER_ENABLED="${CHARON_EMERGENCY_SERVER_ENABLED}" \ -+ -e CHARON_EMERGENCY_BIND="0.0.0.0:2020" \ -+ -e CHARON_EMERGENCY_USERNAME="admin" \ -+ -e CHARON_EMERGENCY_PASSWORD="changeme" \ -+ -e CHARON_SECURITY_TESTS_ENABLED="true" \ - "${IMAGE_REF}" -``` - -### Full Updated Step +> **Note:** After migrating to pure-Go SQLite (`github.com/glebarez/sqlite`), Zig cross-compilation is no longer required. All platforms now use `CGO_ENABLED=0` for simpler, faster builds. ```yaml - - name: Start Charon container - if: steps.check-artifact.outputs.artifact_exists == 'true' - run: | - echo "🚀 Starting Charon container..." +version: 2 - # Normalize image name (GitHub lowercases repository owner names in GHCR) - IMAGE_NAME=$(echo "${{ github.repository_owner }}/charon" | tr '[:upper:]' '[:lower:]') - if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then - IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ steps.sanitize.outputs.branch }}" - else - IMAGE_REF="ghcr.io/${IMAGE_NAME}:pr-${{ steps.pr-info.outputs.pr_number }}" - fi +project_name: charon - echo "📦 Starting container with image: ${IMAGE_REF}" - docker run -d \ - --name charon-test \ - -p 8080:8080 \ - -p 127.0.0.1:2019:2019 \ - -p "[::1]:2019:2019" \ - -p 127.0.0.1:2020:2020 \ - -p "[::1]:2020:2020" \ - -e CHARON_ENV="${CHARON_ENV}" \ - -e CHARON_DEBUG="${CHARON_DEBUG}" \ - -e CHARON_ENCRYPTION_KEY="${CHARON_ENCRYPTION_KEY}" \ - -e CHARON_EMERGENCY_TOKEN="${CHARON_EMERGENCY_TOKEN}" \ - -e CHARON_EMERGENCY_SERVER_ENABLED="${CHARON_EMERGENCY_SERVER_ENABLED}" \ - -e CHARON_EMERGENCY_BIND="0.0.0.0:2020" \ - -e CHARON_EMERGENCY_USERNAME="admin" \ - -e CHARON_EMERGENCY_PASSWORD="changeme" \ - -e CHARON_SECURITY_TESTS_ENABLED="true" \ - "${IMAGE_REF}" +builds: + - id: linux + dir: backend + main: ./cmd/api + binary: charon + env: + - CGO_ENABLED=0 + goos: + - linux + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X github.com/Wikid82/charon/backend/internal/version.Version={{.Version}} + - -X github.com/Wikid82/charon/backend/internal/version.GitCommit={{.Commit}} + - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} - echo "✅ Container started" -``` + - id: windows + dir: backend + main: ./cmd/api + binary: charon + env: + - CGO_ENABLED=0 + goos: + - windows + goarch: + - amd64 + ldflags: + - -s -w + - -X github.com/Wikid82/charon/backend/internal/version.Version={{.Version}} + - -X github.com/Wikid82/charon/backend/internal/version.GitCommit={{.Commit}} + - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} -### Verification + - id: darwin + dir: backend + main: ./cmd/api + binary: charon + env: + - CGO_ENABLED=0 + goos: + - darwin + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X github.com/Wikid82/charon/backend/internal/version.Version={{.Version}} + - -X github.com/Wikid82/charon/backend/internal/version.GitCommit={{.Commit}} + - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} -```bash -# After fix, verify emergency server is listening -docker exec charon-test curl -sf http://localhost:2020/health || echo "Failed" +archives: + - formats: [tar.gz] + id: nix + ids: + - linux + - darwin + name_template: >- + {{ .ProjectName }}_ + {{- .Version }}_ + {{- .Os }}_ + {{- .Arch }} + files: + - LICENSE + - README.md -# Test emergency reset endpoint -curl -X POST http://localhost:2020/emergency/security-reset \ - -H "Authorization: Basic $(echo -n 'admin:changeme' | base64)" \ - -H "X-Emergency-Token: $CHARON_EMERGENCY_TOKEN" -``` + - formats: [zip] + id: windows + ids: + - windows + name_template: >- + {{ .ProjectName }}_ + {{- .Version }}_ + {{- .Os }}_ + {{- .Arch }} + files: + - LICENSE + - README.md ---- +nfpms: + - id: packages + ids: + - linux + package_name: charon + vendor: Charon + homepage: https://github.com/Wikid82/charon + maintainer: Wikid82 + description: "Charon - A powerful reverse proxy manager" + license: MIT + formats: + - deb + - rpm + contents: + - src: ./backend/data/ + dst: /var/lib/charon/data/ + type: dir + - src: ./frontend/dist/ + dst: /usr/share/charon/frontend/ + type: dir + dependencies: + - libc6 + - ca-certificates -## Issue 3: Trivy Scan - Invalid Image Reference Format +checksum: + name_template: 'checksums.txt' -### Problem Statement +snapshot: + version_template: "{{ .Tag }}-next" -Trivy scan fails with "invalid image reference format" when: -1. PR number is missing (manual dispatch without PR number) -2. Feature branch names contain `/` characters (e.g., `feature/new-thing`) -3. `is_push` and `pr_number` are both empty/false - -Resulting in invalid Docker tags like: -- `ghcr.io/owner/charon:pr-` (empty PR number) -- `ghcr.io/owner/charon:` (no tag at all) - -### Root Cause Analysis - -**Location:** `.github/workflows/playwright.yml` - "Start Charon container" step - -```bash -if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then - IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ steps.sanitize.outputs.branch }}" -else - IMAGE_REF="ghcr.io/${IMAGE_NAME}:pr-${{ steps.pr-info.outputs.pr_number }}" -fi -``` - -**Problem:** When `is_push != "true"` AND `pr_number` is empty, this creates: -``` -IMAGE_REF="ghcr.io/owner/charon:pr-" -``` - -This is an invalid Docker reference. - -### Affected Files - -| File | Change Type | -|------|-------------| -| `.github/workflows/playwright.yml` | Add validation for IMAGE_REF | -| `.github/workflows/docker-build.yml` | Add validation guards (CVE verification step) | - -### Recommended Fix - -Add defensive validation to fail fast with a clear error message: - -```diff ---- a/.github/workflows/playwright.yml -+++ b/.github/workflows/playwright.yml - # Normalize image name (GitHub lowercases repository owner names in GHCR) - IMAGE_NAME=$(echo "${{ github.repository_owner }}/charon" | tr '[:upper:]' '[:lower:]') - - if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then - IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ steps.sanitize.outputs.branch }}" -- else -+ elif [[ -n "${{ steps.pr-info.outputs.pr_number }}" ]]; then - IMAGE_REF="ghcr.io/${IMAGE_NAME}:pr-${{ steps.pr-info.outputs.pr_number }}" -+ else -+ echo "❌ ERROR: Cannot determine image reference" -+ echo " - is_push: ${{ steps.pr-info.outputs.is_push }}" -+ echo " - pr_number: ${{ steps.pr-info.outputs.pr_number }}" -+ echo " - branch: ${{ steps.sanitize.outputs.branch }}" -+ echo "" -+ echo "This can happen when:" -+ echo " 1. workflow_dispatch without pr_number input" -+ echo " 2. workflow_run triggered by non-PR, non-push event" -+ exit 1 - fi - -+ # Validate the image reference format -+ if [[ ! "${IMAGE_REF}" =~ ^ghcr\.io/[a-z0-9_-]+/[a-z0-9_-]+:[a-zA-Z0-9._-]+$ ]]; then -+ echo "❌ ERROR: Invalid image reference format: ${IMAGE_REF}" -+ exit 1 -+ fi -+ - echo "📦 Starting container with image: ${IMAGE_REF}" -``` - -### Additional Fix for docker-build.yml - -The same issue can occur in `docker-build.yml` at the CVE verification step: - -```yaml -# Line ~174 in docker-build.yml -if [ "${{ github.event_name }}" = "pull_request" ]; then - IMAGE_REF="${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}" -``` - -**Fix:** - -```diff ---- a/.github/workflows/docker-build.yml -+++ b/.github/workflows/docker-build.yml - # Determine the image reference based on event type - if [ "${{ github.event_name }}" = "pull_request" ]; then -- IMAGE_REF="${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}" -+ PR_NUM="${{ github.event.pull_request.number }}" -+ if [ -z "${PR_NUM}" ]; then -+ echo "❌ ERROR: Pull request number is empty" -+ exit 1 -+ fi -+ IMAGE_REF="${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${PR_NUM}" - echo "Using PR image: $IMAGE_REF" - else - IMAGE_REF="${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }}" -+ if [ -z "${{ steps.build-and-push.outputs.digest }}" ]; then -+ echo "❌ ERROR: Build digest is empty" -+ exit 1 -+ fi - echo "Using digest: $IMAGE_REF" - fi -``` - -### Verification - -```bash -# Test with empty PR number (should fail fast with clear error) -gh workflow run playwright.yml --ref development - -# Check IMAGE_REF construction in logs -gh run view --log | grep "IMAGE_REF" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' ``` --- ## Implementation Plan -### Phase 1: Immediate Fixes (Single PR) +### Phase 0: SQLite Driver Migration (PREREQUISITE) -**Objective:** Fix all three CI failures in a single PR for immediate resolution. +**Objective:** Migrate from CGO-dependent SQLite to pure-Go implementation. **Files to Modify:** -| File | Changes | -|------|---------| -| `.goreleaser.yaml` | Change `-macos-gnu` to `-macos-none` for darwin builds | -| `.github/workflows/playwright.yml` | Add missing emergency server env vars; Add IMAGE_REF validation | -| `.github/workflows/docker-build.yml` | Add IMAGE_REF validation guards | +| File | Change | Reason | +|------|--------|--------| +| `backend/go.mod` | Replace `gorm.io/driver/sqlite` with `github.com/glebarez/sqlite` | Pure-Go SQLite driver | +| `backend/internal/database/database.go` | Update import statement | New driver package | +| `backend/internal/testutil/db_test.go` | Update import statement | New driver package | +| `backend/cmd/seed/main.go` | Update import statement | New driver package | -### Phase 2: Verification +**Steps:** -1. Push changes to a feature branch -2. Open PR to trigger docker-build.yml -3. Verify Trivy scan passes with valid IMAGE_REF -4. Verify Playwright workflow if triggered -5. Manually trigger nightly-build.yml with `--ref` pointing to feature branch -6. Verify darwin build succeeds +```bash +# 1. Update go.mod - replace CGO driver with pure-Go driver +cd backend +go get github.com/glebarez/sqlite +go mod edit -droprequire gorm.io/driver/sqlite -### Phase 3: Cleanup (Optional) +# 2. Update import statements in Go files +# (Manual step - update imports in 3 files listed above) -1. Add validation logic to a shared script (`scripts/validate-image-ref.sh`) -2. Add integration tests for emergency server connectivity -3. Document Zig target requirements for future contributors +# 3. Tidy dependencies +go mod tidy + +# 4. Verify build works without CGO +CGO_ENABLED=0 go build ./cmd/api +CGO_ENABLED=0 go build ./cmd/seed + +# 5. Run tests to verify SQLite functionality +CGO_ENABLED=0 go test ./internal/database/... -v +CGO_ENABLED=0 go test ./internal/testutil/... -v +``` + +**Validation:** +- ✅ `CGO_ENABLED=0 go build ./backend/cmd/api` succeeds +- ✅ `CGO_ENABLED=0 go build ./backend/cmd/seed` succeeds +- ✅ All database tests pass with CGO disabled +- ✅ `go.mod` no longer references `gorm.io/driver/sqlite` or `mattn/go-sqlite3` + +--- + +### Phase 1: Update GoReleaser Config + +**Files to Modify:** + +| File | Change | Reason | +|------|--------|--------| +| `.goreleaser.yaml` | Update to version 2 syntax | Required for GoReleaser ~> v2 | +| `.goreleaser.yaml` | Remove Zig cross-compilation | No longer needed with pure-Go SQLite | +| `.goreleaser.yaml` | Set `CGO_ENABLED=0` for ALL platforms | Consistent pure-Go builds | + +**Simplified Build Configuration (No Zig Required):** + +```yaml +builds: + - id: linux + dir: backend + main: ./cmd/api + binary: charon + env: + - CGO_ENABLED=0 + goos: + - linux + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X github.com/Wikid82/charon/backend/internal/version.Version={{.Version}} + - -X github.com/Wikid82/charon/backend/internal/version.GitCommit={{.Commit}} + - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} + + - id: windows + dir: backend + main: ./cmd/api + binary: charon + env: + - CGO_ENABLED=0 + goos: + - windows + goarch: + - amd64 + ldflags: + - -s -w + - -X github.com/Wikid82/charon/backend/internal/version.Version={{.Version}} + - -X github.com/Wikid82/charon/backend/internal/version.GitCommit={{.Commit}} + - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} + + - id: darwin + dir: backend + main: ./cmd/api + binary: charon + env: + - CGO_ENABLED=0 + goos: + - darwin + goarch: + - amd64 + - arm64 + ldflags: + - -s -w + - -X github.com/Wikid82/charon/backend/internal/version.Version={{.Version}} + - -X github.com/Wikid82/charon/backend/internal/version.GitCommit={{.Commit}} + - -X github.com/Wikid82/charon/backend/internal/version.BuildTime={{.Date}} +``` + +--- + +### Phase 2: Verification Steps + +```bash +# 1. Verify SQLite migration (Phase 0 complete) +cd backend +CGO_ENABLED=0 go build ./cmd/api +CGO_ENABLED=0 go test ./... -count=1 + +# 2. Validate the GoReleaser config locally +goreleaser check + +# 3. Test snapshot build locally (no Zig required!) +goreleaser release --snapshot --skip=publish --clean + +# 4. Trigger nightly workflow manually +gh workflow run nightly-build.yml -f reason="Test GoReleaser v2 migration with pure-Go SQLite" + +# 5. Monitor workflow execution +gh run watch +``` + +--- + +### Phase 3: Rollback Plan + +If the fix fails: + +**SQLite Rollback:** +1. Revert `go.mod` to use `gorm.io/driver/sqlite` +2. Revert import statement changes +3. Re-enable CGO in GoReleaser config + +**GoReleaser Rollback:** +1. Revert `.goreleaser.yaml` changes +2. Pin GoReleaser to v1.x in workflows: + ```yaml + version: '1.26.2' # Last v1 release + ``` --- ## Requirements (EARS Notation) -1. WHEN GoReleaser builds darwin targets, THE SYSTEM SHALL use `-macos-none` Zig target (not `-macos-gnu`). -2. WHEN the Playwright workflow starts the Charon container, THE SYSTEM SHALL set `CHARON_EMERGENCY_BIND=0.0.0.0:2020` to ensure the emergency server is reachable. -3. WHEN constructing Docker image references, THE SYSTEM SHALL validate that the tag portion is non-empty before attempting to use it. -4. IF the PR number is empty in a PR-triggered workflow, THEN THE SYSTEM SHALL fail fast with a clear error message explaining the issue. -5. WHEN a feature branch contains `/` characters, THE SYSTEM SHALL sanitize the branch name by replacing `/` with `-` before using it as a Docker tag. +1. WHEN building for any platform, THE SYSTEM SHALL use `CGO_ENABLED=0` (pure-Go builds). +2. WHEN importing the SQLite driver, THE SYSTEM SHALL use `github.com/glebarez/sqlite` (pure-Go driver). +3. WHEN GoReleaser executes, THE SYSTEM SHALL use version 2 configuration syntax. +4. WHEN archiving builds, THE SYSTEM SHALL use `formats` (array) instead of deprecated `format`. +5. WHEN referencing build IDs in archives/nfpms, THE SYSTEM SHALL use `ids` instead of deprecated `builds`. +6. WHEN generating snapshot versions, THE SYSTEM SHALL use `version_template` instead of deprecated `name_template`. --- ## Acceptance Criteria -1. [ ] Nightly build completes successfully with darwin binaries -2. [ ] Playwright E2E tests pass with emergency server accessible on port 2020 -3. [ ] Trivy scan passes with valid image reference for all trigger types -4. [ ] Workflow failures produce clear, actionable error messages -5. [ ] No regression in existing CI functionality +**Phase 0 (SQLite Migration):** +- [ ] `backend/go.mod` uses `github.com/glebarez/sqlite` instead of `gorm.io/driver/sqlite` +- [ ] No references to `mattn/go-sqlite3` in `go.mod` or `go.sum` +- [ ] `CGO_ENABLED=0 go build ./backend/cmd/api` succeeds +- [ ] `CGO_ENABLED=0 go build ./backend/cmd/seed` succeeds +- [ ] All database tests pass with `CGO_ENABLED=0` + +**Phase 1 (GoReleaser v2):** +- [ ] `goreleaser check` passes without errors or deprecation warnings +- [ ] Nightly build workflow completes successfully +- [ ] Linux amd64/arm64 binaries are produced +- [ ] Windows amd64 binary is produced +- [ ] Darwin amd64/arm64 binaries are produced +- [ ] .deb and .rpm packages are produced for Linux +- [ ] No deprecation warnings in CI logs +- [ ] No Zig-related errors in build logs --- -## Risks & Mitigations +## Risk Assessment | Risk | Likelihood | Impact | Mitigation | |------|------------|--------|------------| -| Zig target change breaks darwin binaries | Low | High | Test with local Zig build first | -| Emergency server env vars conflict with existing config | Low | Medium | Verify against docker-compose.playwright-ci.yml | -| IMAGE_REF validation too strict | Medium | Low | Use permissive regex, log values before validation | - ---- - -## Handoff Contract - -```json -{ - "plan": "CI Workflow Failures - Fix Plan", - "status": "Ready for Implementation", - "owner": "DevOps", - "handoffTargets": ["Backend_Dev", "DevOps"], - "files": [ - ".goreleaser.yaml", - ".github/workflows/playwright.yml", - ".github/workflows/docker-build.yml" - ], - "estimatedEffort": "2-3 hours", - "priority": "HIGH", - "blockedWorkflows": [ - "nightly-build.yml", - "playwright.yml", - "docker-build.yml (Trivy scan step)" - ] -} -``` +| Pure-Go SQLite has different behavior | Low | Medium | Run full test suite; compare query results | +| Pure-Go SQLite performance differs | Low | Low | Run benchmarks; acceptable for typical workloads | +| Other undocumented v2 breaking changes | Low | Medium | Monitor GoReleaser changelog; test locally first | +| Import statement missed in some file | Low | High | Use grep to find all `gorm.io/driver/sqlite` imports | --- ## References -- [docs/actions/nightly-build-failure.md](../actions/nightly-build-failure.md) -- [docs/actions/playwright-e2e-failures.md](../actions/playwright-e2e-failures.md) -- [Zig Cross-Compilation Targets](https://ziglang.org/documentation/master/#Targets) -- [GoReleaser CGO Cross-Compilation](https://goreleaser.com/customization/build/#cross-compiling) +- [glebarez/sqlite - Pure Go SQLite driver for GORM](https://github.com/glebarez/sqlite) +- [modernc.org/sqlite - Pure Go SQLite implementation](https://pkg.go.dev/modernc.org/sqlite) +- [GoReleaser v2 Migration Guide](https://goreleaser.com/deprecations/) +- [GoReleaser Builds Documentation](https://goreleaser.com/customization/build/) + +--- + +# ARCHIVED: Other CI Issues (Separate from GoReleaser) + +The following issues are documented separately and may be addressed in future PRs: + +1. **Playwright E2E - Emergency Server Connectivity** - See [docs/plans/e2e_remediation_spec.md](e2e_remediation_spec.md) +2. **Trivy Scan - Image Reference Validation** - See [docs/plans/docker_compose_ci_fix.md](docker_compose_ci_fix.md) diff --git a/go.work.sum b/go.work.sum index 1b36ac7b..62d13cb1 100644 --- a/go.work.sum +++ b/go.work.sum @@ -33,6 +33,7 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -105,6 +106,7 @@ golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= @@ -114,5 +116,14 @@ google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXn gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=