Skip to content

Commit fa6bc6b

Browse files
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
1 parent 43385ef commit fa6bc6b

10 files changed

Lines changed: 181 additions & 115 deletions

File tree

.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-

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

CLAUDE.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
AGENT SAFEGUARDS (non-negotiable)
2+
3+
Operating principles
4+
1) Prefer clear code over comments.
5+
- Use comments only for: non-obvious reasoning, security invariants, protocol quirks, or “why” that code cannot express.
6+
- Prefer descriptive names, small functions, and explicit types over commentary.
7+
8+
2) Solve root cause, not band-aids.
9+
- Do not add retries/timeouts/logging to hide failures unless the root cause is addressed or explicitly impossible to fix.
10+
- If a workaround is necessary, document the root cause and the exact reason it can’t be fixed now.
11+
12+
3) Use idioms of the language and ecosystem.
13+
- Follow standard style guides, conventions, directory layout, and tooling.
14+
- Avoid clever patterns that fight the ecosystem. Prefer boring, maintainable solutions.
15+
16+
Quality gates
17+
4) Tests must run after each modification.
18+
- After any functional change, run the relevant test suite locally (or in CI steps) and ensure it passes.
19+
- If tests cannot run (missing dependency, environment), add or update a runnable test harness or clearly state what is required.
20+
- Never leave the repo in a state where tests are known failing.
21+
22+
5) Documentation for all features.
23+
- Every new feature must have usage docs + one runnable example.
24+
- Docs must include intent, flags/config, and failure modes.
25+
- Prefer docs that answer user questions (“How do I…”) and include copy/paste snippets.
26+
27+
6) Update CHANGELOG with all changes.
28+
- Every user-visible change must be added to CHANGELOG.md under “Unreleased”.
29+
- Use categories: Added / Changed / Fixed / Security / Deprecated / Removed.
30+
- Mention migration steps if behavior changes.
31+
32+
Robustness & correctness
33+
7) Include error handling everywhere it matters.
34+
- Never ignore errors; propagate with context.
35+
- Wrap/annotate errors so the caller has actionable info.
36+
- Ensure exit codes/return values are correct and consistent.
37+
38+
8) Test edge cases and invariants.
39+
- Add tests for: empty inputs, invalid inputs, boundary values, timeouts, large payloads (reasonable), and concurrency/ordering if relevant.
40+
- Include at least one test for each bug fixed to prevent regressions.
41+
42+
Security & safety (important for agentic tooling)
43+
9) No harmful actions by default.
44+
- Do not delete data, rotate secrets, publish releases, or mutate external systems unless explicitly requested.
45+
- Treat external calls (network, cloud APIs) as “dangerous”: require explicit opt-in via config/flags.
46+
47+
10) Least privilege and safe defaults.
48+
- Minimize permissions, capabilities, scopes, and access tokens.
49+
- For Kubernetes artifacts: runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation=false, drop ALL capabilities unless justified.
50+
51+
11) No secret leakage.
52+
- Never print tokens, passwords, or full credential material to logs.
53+
- Redact known secret patterns; avoid echoing env vars that might contain secrets.
54+
55+
12) Deterministic builds and reproducibility.
56+
- Prefer pinned versions, lockfiles, and deterministic packaging.
57+
- Avoid “download latest at build time” unless necessary.
58+
59+
Change management rules
60+
13) Small, reviewable diffs.
61+
- Prefer incremental changes with clear commit boundaries.
62+
- If a refactor is needed, do it in a separate commit/PR before feature changes.
63+
64+
14) Respect existing standards and tooling.
65+
- Use the repo's existing lint/format/test tools (Makefile/package scripts/cargo test/etc.).
66+
- If tooling is missing, add it in a minimal conventional way.
67+
68+
15) Provide a “How to verify” section in PR descriptions/output.
69+
- Include exact commands: build, lint, unit tests, integration tests (if any).
70+
71+
Agent execution constraints (for local runners / GH actions)
72+
16) Only modify files that are in-scope for the task.
73+
- Do not reformat unrelated files.
74+
- Do not introduce new dependencies unless justified.
75+
76+
17) When uncertain, choose the safer option and make it explicit.
77+
- Prefer failing fast with actionable errors over silent fallback.
78+
- If ambiguity remains, implement a guardrail and document the decision.
79+
80+
18) When really uncertain, ask for help.
81+
- Avoid making assumptions without asking for confirmation.
82+
83+
19) When running locally, prefer the mcp edit tool to direct file edits.
84+
- If issues arise where files seems unedited, alert the user before continuing
85+
86+
20) Prefer bash commands/scripts to python3 when investigating
87+
88+
Definition of done
89+
- Code compiles.
90+
- Code is formatted.
91+
- Tests pass.
92+
- Docs updated.
93+
- CHANGELOG updated.
94+
- Edge cases tested.
95+
- Security posture maintained.
96+
- Output includes a concise summary of changes + how to verify.

FAQ.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ A `scratch` base image contains zero OS packages, zero libraries, zero shells. T
280280

281281
- **Zero CVEs** from base image packages — nothing to scan, nothing to patch
282282
- **No shell** for attackers to use if the container is compromised
283-
- **Tiny image** — the final image is ~10MB (just the Go binary + CA certificates)
283+
- **Tiny image** — the final image is ~2MB (just the Rust binary + CA certificates)
284284

285285
The trade-off is that you cannot `kubectl exec` into the container for debugging. This is acceptable for initContainers, which run once and exit.
286286

@@ -424,9 +424,9 @@ Then reference your internal registry in the pod spec. If your registry requires
424424
```bash
425425
git clone https://github.com/KitStream/initium.git
426426
cd initium
427-
make build # produces bin/initium
428-
make test # runs all unit tests with race detector
429-
make lint # runs go vet + staticcheck
427+
make build # produces target/release/initium
428+
make test # runs all unit tests
429+
make lint # runs cargo clippy + cargo fmt --check
430430
```
431431

432432
### How do I build a custom Docker image?

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ kubectl apply -f https://raw.githubusercontent.com/kitstream/initium/main/exampl
4444
| **Structured logging** | `echo` statements | JSON or text with timestamps |
4545
| **Security** | Runs as root, full shell | Non-root, no shell, read-only FS |
4646
| **Secret handling** | Easily leaked in logs | Automatic redaction |
47-
| **Multiple tools** | Install curl, netcat, psql… | Single 10MB image |
48-
| **Reproducibility** | Shell differences across distros | Single Go binary, `FROM scratch` |
47+
| **Multiple tools** | Install curl, netcat, psql… | Single 2MB image |
48+
| **Reproducibility** | Shell differences across distros | Single Rust binary, `FROM scratch` |
4949
| **Vulnerability surface** | Full OS + shell utils | Zero OS packages |
5050

5151
## Subcommands

0 commit comments

Comments
 (0)