Fixes nightly build failures caused by: GoReleaser v2 requiring version 2 config syntax Zig cross-compilation failing for macOS CGO targets SQLite Driver Migration: Replace gorm.io/driver/sqlite with github.com/glebarez/sqlite (pure-Go) Execute PRAGMA statements via SQL instead of DSN parameters All platforms now build with CGO_ENABLED=0 GoReleaser v2 Migration: Update version: 1 → version: 2 snapshot.name_template → version_template archives.format → formats (array syntax) archives.builds → ids nfpms.builds → ids Remove Zig cross-compilation environment Also fixes Docker Compose E2E image reference: Use CHARON_E2E_IMAGE_TAG instead of bare digest Add fallback default for local development All database tests pass with the pure-Go SQLite driver.
558 lines
16 KiB
Markdown
558 lines
16 KiB
Markdown
# GoReleaser v2 Migration & Nightly Build Failure Remediation
|
|
|
|
**Status**: Active
|
|
**Created**: 2026-01-30
|
|
**Priority**: CRITICAL (Blocking Nightly Builds)
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
The nightly build workflow (`nightly-build.yml`) is failing with multiple issues:
|
|
|
|
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**:
|
|
```
|
|
only version: 2 configuration files are supported, yours is version: 1, please update your configuration
|
|
```
|
|
|
|
**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
|
|
```
|
|
|
|
---
|
|
|
|
## 🔴 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
|
|
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 **`-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.
|
|
|
|
**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-none
|
|
```
|
|
|
|
The current config is correct (`-macos-none`), but CGO may be interfering.
|
|
|
|
### ~~Recommended Fix: Disable CGO for Darwin~~
|
|
|
|
> **⚠️ 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**.
|
|
|
|
### ✅ Actual Fix: Migrate to Pure-Go SQLite
|
|
|
|
By migrating from `gorm.io/driver/sqlite` (CGO) to `github.com/glebarez/sqlite` (pure-Go):
|
|
|
|
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
|
|
|
|
This completely eliminates Issue 2 as a side effect of fixing the SQLite dependency issue.
|
|
|
|
---
|
|
|
|
## Complete Updated `.goreleaser.yaml`
|
|
|
|
> **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
|
|
version: 2
|
|
|
|
project_name: charon
|
|
|
|
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}}
|
|
|
|
archives:
|
|
- formats: [tar.gz]
|
|
id: nix
|
|
ids:
|
|
- linux
|
|
- darwin
|
|
name_template: >-
|
|
{{ .ProjectName }}_
|
|
{{- .Version }}_
|
|
{{- .Os }}_
|
|
{{- .Arch }}
|
|
files:
|
|
- LICENSE
|
|
- README.md
|
|
|
|
- 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
|
|
|
|
checksum:
|
|
name_template: 'checksums.txt'
|
|
|
|
snapshot:
|
|
version_template: "{{ .Tag }}-next"
|
|
|
|
changelog:
|
|
sort: asc
|
|
filters:
|
|
exclude:
|
|
- '^docs:'
|
|
- '^test:'
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Plan
|
|
|
|
### Phase 0: SQLite Driver Migration (PREREQUISITE)
|
|
|
|
**Objective:** Migrate from CGO-dependent SQLite to pure-Go implementation.
|
|
|
|
**Files to Modify:**
|
|
|
|
| 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 |
|
|
|
|
**Steps:**
|
|
|
|
```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
|
|
|
|
# 2. Update import statements in Go files
|
|
# (Manual step - update imports in 3 files listed above)
|
|
|
|
# 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 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
|
|
|
|
**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
|
|
|
|
---
|
|
|
|
## Risk Assessment
|
|
|
|
| Risk | Likelihood | Impact | Mitigation |
|
|
|------|------------|--------|------------|
|
|
| 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
|
|
|
|
- [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)
|