Skip to content

Commit 66728a3

Browse files
Rewrite Initium from Go to Rust (#13)
* Rewrite Initium from Go to Rust Complete reimplementation of all 6 subcommands in Rust: - wait-for (TCP + HTTP/HTTPS with retries, backoff, jitter) - migrate (command exec with lock file idempotency) - seed (command exec with structured logging) - render (envsubst + Jinja2 templates via minijinja) - fetch (HTTP fetch with auth, TLS, retry) - exec (arbitrary command with workdir support) Key dependencies: clap, ureq+rustls, serde_json, minijinja, regex, chrono 36 unit tests covering: logging, retry, safety, render modules All tests passing. Binary size comparison (release, stripped, musl-linked): - Go binary (scratch): ~7.4 MB - Rust binary (scratch): ~1.8 MB (76% reduction) Docker image (scratch + binary + CA certs): 1.83 MB total * Update all build files, workflows, and docs for Rust - CI workflow: replace setup-go with dtolnay/rust-toolchain, use cargo test/clippy/fmt instead of go test/vet/staticcheck - Release workflow: use dtolnay/rust-toolchain for pre-push tests - jyq.Dockerfile: rewrite for Rust (rust:1.85-alpine builder, cargo build) - Dockerfile: already updated in prior commit - docs/design.md: update architecture diagram, directory structure, and 'How to Add a Subcommand' guide for Rust/clap - docs/usage.md: update template mode description (Go text/template -> minijinja) - README.md, FAQ.md: update image sizes (10MB -> 2MB), tool references - CHANGELOG.md: add Rust rewrite entry, update references - CLAUDE.md: add project config with cargo test references - tests/README.md: update from go test to cargo test * Fix clippy warnings and cargo fmt formatting - Fix dead_code warnings: allow unused Warn variant and warn() method - Fix useless .into() conversion in logging JSON output - Fix manual Range::contains in fetch status check - Fix unit let-binding in command execution - Fix lines().flatten() -> lines().map_while(Result::ok) - Apply cargo fmt to all source files
1 parent e86526c commit 66728a3

53 files changed

Lines changed: 2864 additions & 3678 deletions

Some content is hidden

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

.dockerignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
target/
2+
.git/
3+
bin/
4+
*.md
5+
docs/
6+
examples/
7+
charts/
8+
tests/
9+
.github/

.github/workflows/ci.yml

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,28 @@ jobs:
1111
runs-on: ubuntu-latest
1212
steps:
1313
- uses: actions/checkout@v4
14-
- uses: actions/setup-go@v5
14+
- uses: dtolnay/rust-toolchain@stable
1515
with:
16-
go-version: "1.25"
17-
- run: go vet ./...
18-
- run: |
19-
go install golang.org/x/tools/cmd/staticcheck@latest || true
20-
if command -v staticcheck >/dev/null 2>&1; then
21-
staticcheck ./...
22-
else
23-
echo "staticcheck not available, skipping"
24-
fi
16+
components: clippy, rustfmt
17+
- run: cargo fmt --check
18+
- run: cargo clippy -- -D warnings
2519
test:
2620
runs-on: ubuntu-latest
2721
steps:
2822
- uses: actions/checkout@v4
29-
- uses: actions/setup-go@v5
30-
with:
31-
go-version: "1.25"
32-
- run: go test ./... -count=1 -timeout 60s -race -coverprofile=coverage.out
33-
- uses: actions/upload-artifact@v4
34-
with:
35-
name: coverage
36-
path: coverage.out
23+
- uses: dtolnay/rust-toolchain@stable
24+
- run: cargo test --all
3725
build:
3826
runs-on: ubuntu-latest
3927
needs: [lint, test]
4028
steps:
4129
- uses: actions/checkout@v4
42-
- uses: actions/setup-go@v5
43-
with:
44-
go-version: "1.25"
45-
- run: make build
30+
- uses: dtolnay/rust-toolchain@stable
31+
- run: cargo build --release
4632
- uses: actions/upload-artifact@v4
4733
with:
4834
name: initium-binary
49-
path: bin/initium
35+
path: target/release/initium
5036
helm-lint:
5137
runs-on: ubuntu-latest
5238
steps:

.github/workflows/release.yml

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,29 @@
11
name: Release
2-
32
on:
43
push:
54
tags:
65
- "v*"
7-
86
permissions:
97
contents: read
108
packages: write
119
id-token: write
12-
1310
jobs:
1411
release:
1512
runs-on: ubuntu-latest
1613
steps:
1714
- uses: actions/checkout@v4
18-
19-
- uses: actions/setup-go@v5
20-
with:
21-
go-version: "1.25"
22-
23-
- run: go test ./... -count=1 -timeout 60s -race
24-
15+
- uses: dtolnay/rust-toolchain@stable
16+
- run: cargo test --all
2517
- uses: docker/setup-qemu-action@v3
2618
- uses: docker/setup-buildx-action@v3
27-
2819
- uses: docker/login-action@v3
2920
with:
3021
registry: ghcr.io
3122
username: ${{ github.actor }}
3223
password: ${{ secrets.GITHUB_TOKEN }}
33-
3424
- name: Extract version
3525
id: version
3626
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
37-
3827
- uses: docker/build-push-action@v6
3928
with:
4029
context: .
@@ -47,7 +36,6 @@ jobs:
4736
ghcr.io/kitstream/initium:latest
4837
sbom: true
4938
provenance: true
50-
5139
- uses: docker/build-push-action@v6
5240
with:
5341
context: .
@@ -61,4 +49,3 @@ jobs:
6149
ghcr.io/kitstream/initium-jyq:latest
6250
sbom: true
6351
provenance: true
64-

.gitignore

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,4 @@
1-
# IDE
21
.idea/
3-
*.iml
4-
# Go
2+
target/
53
bin/
6-
*.exe
7-
*.dll
8-
*.so
9-
*.dylib
10-
# Test
11-
*.test
12-
*.out
13-
coverage.out
14-
# OS
15-
.DS_Store
16-
Thumbs.db
17-
CLAUDE.md
4+
CLAUDE.md

CHANGELOG.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
- Complete rewrite from Go to Rust for ~76% smaller Docker images (7.4MB → 1.8MB)
12+
- CLI framework changed from cobra to clap
13+
- Template engine changed from Go text/template to minijinja (Jinja2-style); access env vars via `{{ env.VAR }}`
14+
- CI/CD workflows updated for Rust toolchain (cargo test, clippy, rustfmt)
15+
- Dockerfiles updated to use rust:1.85-alpine builder with musl static linking
16+
1017
### Added
1118
- `exec` subcommand: run arbitrary commands with structured logging, exit code forwarding, and optional `--workdir` for child process working directory
1219
- `jyq.Dockerfile` and `initium-jyq` container image variant with pre-built `jq` and `yq` tools
1320
- Documentation for building custom images using Initium as a base
1421
- `fetch` subcommand and `internal/fetch` package: fetch secrets/config from HTTP(S) endpoints with auth header via env var, retry with backoff, TLS options, redirect control (same-site by default), and path traversal prevention
15-
- `render` subcommand and `internal/render` package: render templates into config files with `envsubst` (default) and Go `text/template` modes, path traversal prevention, and automatic intermediate directory creation
22+
- `render` subcommand and `internal/render` package: render templates into config files with `envsubst` (default) and Jinja2 template modes, path traversal prevention, and automatic intermediate directory creation
1623
- `seed` subcommand: run database seed commands with structured logging and exit code forwarding (no idempotency — distinct from `migrate`)
1724
- `migrate` subcommand: run database migration commands with structured logging, exit code forwarding, and optional idempotency via `--lock-file`
1825
- FAQ.md with functionality, security, and deployment questions for junior-to-mid-level engineers
19-
- Project scaffolding with Go module, CLI framework (cobra), and repo layout
26+
- Project scaffolding with Rust/Cargo, CLI framework (clap), and repo layout
2027
- `wait-for` subcommand: wait for TCP and HTTP(S) endpoints with retries, exponential backoff, and jitter
2128
- `internal/retry` package with configurable retry logic, backoff, and jitter
2229
- `internal/logging` package with text and JSON structured logging, automatic secret redaction

0 commit comments

Comments
 (0)