Skip to content

Commit 70763ed

Browse files
committed
feat: implement Phase A foundation and Phase B Postgres walking skeleton
Phase A: Go module, Cobra CLI, Bubble Tea TUI placeholder, Driver interface + registry, and the errs/config/secrets/profile support packages, with golangci-lint + depguard layer enforcement and cross-platform CI. Phase B: backup, restore, sync, verify, inspect, dumps, config, and profile working end-to-end against PostgreSQL via pg_dump/pg_restore shell-out + pgx; checksummed dump catalog; job runner with streamed progress events. schedule/tunnel are Phase G stubs.
1 parent 6bfb4b6 commit 70763ed

62 files changed

Lines changed: 4269 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
test:
13+
name: Test (${{ matrix.os }})
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
os: [ubuntu-latest, macos-latest, windows-latest]
18+
runs-on: ${{ matrix.os }}
19+
steps:
20+
- uses: actions/checkout@v4
21+
- uses: actions/setup-go@v5
22+
with:
23+
go-version: stable
24+
cache: true
25+
- name: go vet
26+
run: go vet ./...
27+
- name: go test
28+
run: go test ./...
29+
30+
lint:
31+
name: Lint
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v4
35+
- uses: actions/setup-go@v5
36+
with:
37+
go-version: stable
38+
cache: true
39+
- uses: golangci/golangci-lint-action@v6
40+
with:
41+
version: latest

.golangci.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
version: "2"
2+
3+
run:
4+
timeout: 5m
5+
6+
linters:
7+
default: none
8+
enable:
9+
- errcheck
10+
- govet
11+
- ineffassign
12+
- misspell
13+
- staticcheck
14+
- unused
15+
- depguard
16+
# Note: revive is intentionally NOT enabled in Phase A. Its `exported`
17+
# rule would require doc comments on every exported symbol, which is
18+
# bikeshedding at scaffold stage. Reconsider in a later phase.
19+
settings:
20+
depguard:
21+
rules:
22+
cli-may-not-import-domain:
23+
list-mode: lax
24+
files:
25+
- "**/internal/cli/**"
26+
- "!**/_test.go"
27+
deny:
28+
- pkg: "github.com/nixrajput/siphon/internal/driver"
29+
desc: "CLI must go through internal/app, not Driver directly"
30+
tui-may-not-import-cli:
31+
list-mode: lax
32+
files:
33+
- "**/internal/tui/**"
34+
- "!**/_test.go"
35+
deny:
36+
- pkg: "github.com/nixrajput/siphon/internal/cli"
37+
desc: "TUI and CLI are siblings and may not depend on each other"
38+
cli-may-not-import-tui-except-root:
39+
list-mode: lax
40+
files:
41+
- "**/internal/cli/**"
42+
- "!**/internal/cli/root.go"
43+
- "!**/_test.go"
44+
deny:
45+
- pkg: "github.com/nixrajput/siphon/internal/tui"
46+
desc: "Only the root command may launch the TUI"
47+
driver-may-not-import-presentation:
48+
list-mode: lax
49+
files:
50+
- "**/internal/driver/**"
51+
- "!**/_test.go"
52+
deny:
53+
- pkg: "github.com/nixrajput/siphon/internal/cli"
54+
desc: "Drivers must not depend on presentation"
55+
- pkg: "github.com/nixrajput/siphon/internal/tui"
56+
desc: "Drivers must not depend on presentation"
57+
- pkg: "github.com/nixrajput/siphon/internal/app"
58+
desc: "Drivers must not depend on Application — dependency flows down"
59+
exclusions:
60+
rules:
61+
- path: _test\.go
62+
linters:
63+
- errcheck
64+
65+
formatters:
66+
enable:
67+
- gofmt

Makefile

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
SHELL := /usr/bin/env bash
2+
.DEFAULT_GOAL := help
3+
4+
help: ## Show this help
5+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
6+
| sort \
7+
| awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
8+
9+
lint: ## Run golangci-lint
10+
golangci-lint run
11+
12+
test: ## Run unit tests
13+
go test ./...
14+
15+
test-verbose: ## Run unit tests verbosely
16+
go test -v ./...
17+
18+
test-integration: ## Run integration tests (build tag: integration)
19+
go test -tags=integration ./...
20+
21+
build: ## Build the siphon binary into ./bin
22+
@mkdir -p bin
23+
go build -ldflags "-s -w -X github.com/nixrajput/siphon/internal/cli.Version=$$(git describe --tags --always --dirty 2>/dev/null || echo dev)" -o bin/siphon ./cmd/siphon
24+
25+
run: ## Run siphon from source (bare invocation -> TUI)
26+
go run ./cmd/siphon
27+
28+
install: ## Install siphon to GOBIN
29+
go install ./cmd/siphon
30+
31+
tidy: ## Run go mod tidy
32+
go mod tidy
33+
34+
clean: ## Remove build artifacts
35+
rm -rf bin/ dist/ coverage.out coverage.html
36+
37+
.PHONY: help lint test test-verbose test-integration build run install tidy clean

cmd/siphon/main.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Command siphon is the CLI entry point. All real work lives in
2+
// internal/cli; this file exists only to satisfy the Go executable layout.
3+
package main
4+
5+
import (
6+
"os"
7+
8+
"github.com/nixrajput/siphon/internal/cli"
9+
)
10+
11+
func main() { os.Exit(cli.Execute()) }

go.mod

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
module github.com/nixrajput/siphon
2+
3+
go 1.26.3
4+
5+
require (
6+
github.com/charmbracelet/bubbletea v1.3.10
7+
github.com/charmbracelet/lipgloss v1.1.0
8+
github.com/jackc/pgx/v5 v5.9.2
9+
github.com/oklog/ulid/v2 v2.1.1
10+
github.com/spf13/cobra v1.10.2
11+
github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0
12+
gopkg.in/yaml.v3 v3.0.1
13+
)
14+
15+
require (
16+
dario.cat/mergo v1.0.2 // indirect
17+
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
18+
github.com/Microsoft/go-winio v0.6.2 // indirect
19+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
20+
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
21+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
22+
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
23+
github.com/charmbracelet/x/ansi v0.10.1 // indirect
24+
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
25+
github.com/charmbracelet/x/term v0.2.1 // indirect
26+
github.com/containerd/errdefs v1.0.0 // indirect
27+
github.com/containerd/errdefs/pkg v0.3.0 // indirect
28+
github.com/containerd/log v0.1.0 // indirect
29+
github.com/containerd/platforms v0.2.1 // indirect
30+
github.com/cpuguy83/dockercfg v0.3.2 // indirect
31+
github.com/davecgh/go-spew v1.1.1 // indirect
32+
github.com/distribution/reference v0.6.0 // indirect
33+
github.com/docker/go-connections v0.6.0 // indirect
34+
github.com/docker/go-units v0.5.0 // indirect
35+
github.com/ebitengine/purego v0.10.0 // indirect
36+
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
37+
github.com/felixge/httpsnoop v1.0.4 // indirect
38+
github.com/go-logr/logr v1.4.3 // indirect
39+
github.com/go-logr/stdr v1.2.2 // indirect
40+
github.com/go-ole/go-ole v1.2.6 // indirect
41+
github.com/google/uuid v1.6.0 // indirect
42+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
43+
github.com/jackc/pgpassfile v1.0.0 // indirect
44+
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
45+
github.com/jackc/puddle/v2 v2.2.2 // indirect
46+
github.com/klauspost/compress v1.18.5 // indirect
47+
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
48+
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
49+
github.com/magiconair/properties v1.8.10 // indirect
50+
github.com/mattn/go-isatty v0.0.20 // indirect
51+
github.com/mattn/go-localereader v0.0.1 // indirect
52+
github.com/mattn/go-runewidth v0.0.16 // indirect
53+
github.com/moby/docker-image-spec v1.3.1 // indirect
54+
github.com/moby/go-archive v0.2.0 // indirect
55+
github.com/moby/moby/api v1.54.1 // indirect
56+
github.com/moby/moby/client v0.4.0 // indirect
57+
github.com/moby/patternmatcher v0.6.1 // indirect
58+
github.com/moby/sys/sequential v0.6.0 // indirect
59+
github.com/moby/sys/user v0.4.0 // indirect
60+
github.com/moby/sys/userns v0.1.0 // indirect
61+
github.com/moby/term v0.5.2 // indirect
62+
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
63+
github.com/muesli/cancelreader v0.2.2 // indirect
64+
github.com/muesli/termenv v0.16.0 // indirect
65+
github.com/opencontainers/go-digest v1.0.0 // indirect
66+
github.com/opencontainers/image-spec v1.1.1 // indirect
67+
github.com/pmezard/go-difflib v1.0.0 // indirect
68+
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
69+
github.com/rivo/uniseg v0.4.7 // indirect
70+
github.com/rogpeppe/go-internal v1.15.0 // indirect
71+
github.com/shirou/gopsutil/v4 v4.26.3 // indirect
72+
github.com/sirupsen/logrus v1.9.4 // indirect
73+
github.com/spf13/pflag v1.0.9 // indirect
74+
github.com/stretchr/testify v1.11.1 // indirect
75+
github.com/testcontainers/testcontainers-go v0.42.0 // indirect
76+
github.com/tklauser/go-sysconf v0.3.16 // indirect
77+
github.com/tklauser/numcpus v0.11.0 // indirect
78+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
79+
github.com/yusufpapurcu/wmi v1.2.4 // indirect
80+
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
81+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
82+
go.opentelemetry.io/otel v1.41.0 // indirect
83+
go.opentelemetry.io/otel/metric v1.41.0 // indirect
84+
go.opentelemetry.io/otel/trace v1.41.0 // indirect
85+
golang.org/x/crypto v0.48.0 // indirect
86+
golang.org/x/sync v0.19.0 // indirect
87+
golang.org/x/sys v0.42.0 // indirect
88+
golang.org/x/text v0.34.0 // indirect
89+
)

0 commit comments

Comments
 (0)