|
1 | | -# Contributing to Gradient Linux / concave |
| 1 | +# Contributing to concave |
2 | 2 |
|
3 | | -`concave` is the control-plane CLI for Gradient Linux. This document is the public |
4 | | -source of truth for contributor-facing expectations in this repository: architecture |
5 | | -rules, documentation layout, code conventions, testing gates, and pull request flow. |
| 3 | +Contributions are welcome for CLI behavior, API handlers, suite lifecycle, workspace tooling, GPU support, tests, and documentation. Keep changes focused on the control plane. Client-side presentation work belongs in `concave-tui` and `concave-web`. |
6 | 4 |
|
7 | | -Maintainers may use their own internal tooling, automation, or agentic workflows while |
8 | | -building and reviewing the project. Those internal workflows are not part of the public |
9 | | -contribution contract. If you contribute with your own local tooling or agents, the |
10 | | -result still needs to follow this document. |
| 5 | +## Before you start |
11 | 6 |
|
12 | | -## Scope |
| 7 | +Read these documents before changing behavior: |
13 | 8 |
|
14 | | -- Active repository: `github.com/Gradient-Linux/concave` |
15 | | -- Go module: `github.com/Gradient-Linux/concave` |
16 | | -- Target platform: Ubuntu 24.04 LTS |
17 | | -- Primary deliverable: a static `concave` Go binary |
| 9 | +- [README.md](README.md) |
| 10 | +- [docs/architecture.md](docs/architecture.md) |
| 11 | +- [docs/concave-reference.md](docs/concave-reference.md) |
| 12 | +- [docs/suite-guide.md](docs/suite-guide.md) |
18 | 13 |
|
19 | | -Gradient Linux keeps the host thin. Docker Engine and the `concave` binary live on the |
20 | | -host. AI frameworks, notebooks, model services, tracking, and orchestration all run in |
21 | | -containers. Do not add host Python installation paths to this project. |
| 14 | +## Development setup |
22 | 15 |
|
23 | | -## Repository Layout |
24 | | - |
25 | | -```text |
26 | | -concave/ |
27 | | - CONTRIBUTING.md |
28 | | - README.md |
29 | | - CHANGELOG.md |
30 | | - main.go |
31 | | - go.mod |
32 | | - cmd/ |
33 | | - internal/ |
34 | | - templates/ |
35 | | - scripts/ |
36 | | - tests/ |
37 | | - integration/ |
38 | | - benchmarks/ |
39 | | - docs/ |
40 | | - architecture.md |
41 | | - concave-reference.md |
42 | | - gpu-setup.md |
43 | | - system-admin.md |
44 | | - suite-guide.md |
45 | | - suites/ |
46 | | - boosting.md |
47 | | - neural.md |
48 | | - flow.md |
49 | | - forge.md |
50 | | -``` |
51 | | - |
52 | | -## Documentation Layout |
53 | | - |
54 | | -There are exactly two documentation locations in this repo: |
55 | | - |
56 | | -- `docs/` |
57 | | -- inline godoc in Go source |
58 | | - |
59 | | -Rules: |
60 | | - |
61 | | -- System-wide behavior belongs in `docs/`. |
62 | | -- Suite-level prose belongs in `docs/suites/*.md`, one file per suite. |
63 | | -- Service-level details belong inside the relevant suite doc, not in a separate tree. |
64 | | -- There is no `services/` directory. |
65 | | -- There is no `docs/suites/<suite>/` directory tree. |
66 | | -- There are no README files inside `templates/`. |
67 | | -- `templates/` is a flat directory containing only the four Compose YAML files. |
68 | | - |
69 | | -If your change alters user-facing behavior, command flow, suite topology, container |
70 | | -ports, environment variables, or workspace mounts, update the matching document in the |
71 | | -same pull request. |
72 | | - |
73 | | -## Local Setup |
74 | | - |
75 | | -Requirements: |
76 | | - |
77 | | -- Ubuntu 24.04 LTS preferred |
78 | | -- Go 1.25.0 or newer locally |
79 | | -- Docker Engine |
80 | | -- `golangci-lint` for local lint checks |
81 | | -- optional: `goreleaser` for local release artifact validation |
82 | | -- optional: `syft` for local SPDX SBOM generation during release validation |
83 | | - |
84 | | -Clone and build: |
| 16 | +Use Ubuntu 24.04 with Go 1.25 or newer and Docker Engine installed. |
85 | 17 |
|
86 | 18 | ```bash |
87 | | -git clone git@github.com:Gradient-Linux/concave.git |
| 19 | +git clone <repo-url> |
88 | 20 | cd concave |
89 | | -go build -o concave . |
| 21 | +CGO_ENABLED=0 go build -o concave . |
90 | 22 | go test ./... |
91 | 23 | go test -race ./... |
92 | | -go vet ./... |
93 | | -bash scripts/build.sh |
| 24 | +./concave --help |
94 | 25 | ``` |
95 | 26 |
|
96 | | -Optional local lint: |
| 27 | +If you want to exercise live suite flows, start from a machine with Docker available and a writable `~/gradient/` workspace. |
97 | 28 |
|
98 | | -```bash |
99 | | -golangci-lint run ./... |
100 | | -``` |
| 29 | +## Making changes |
101 | 30 |
|
102 | | -## Branching and Pull Requests |
| 31 | +### Branching |
103 | 32 |
|
104 | | -Human contributors branch from `main` using one of these prefixes: |
| 33 | +Use one of these branch prefixes: |
105 | 34 |
|
106 | | -- `feat/` |
107 | | -- `fix/` |
108 | | -- `docs/` |
109 | | -- `refactor/` |
110 | | -- `test/` |
| 35 | +- `feat/<slug>` |
| 36 | +- `fix/<slug>` |
| 37 | +- `docs/<slug>` |
111 | 38 |
|
112 | | -Examples: |
| 39 | +### Commit messages |
113 | 40 |
|
114 | | -- `feat/boosting-log-follow` |
115 | | -- `fix/compose-rollback-cleanup` |
116 | | -- `docs/update-suite-guide` |
| 41 | +Format commits as `<type>(<scope>): <summary>`. |
117 | 42 |
|
118 | | -Workflow: |
119 | | - |
120 | | -1. Branch from `main`. |
121 | | -2. Make the smallest coherent change possible. |
122 | | -3. Run the required checks locally. |
123 | | -4. Update docs in the same branch when behavior changes. |
124 | | -5. Open a pull request targeting `dev`, never `main`. |
125 | | - |
126 | | -Maintainers handle review, additional automation, and the final `dev` to `main` merge. |
127 | | - |
128 | | -## Commit Format |
129 | | - |
130 | | -Use Conventional Commits: |
131 | | - |
132 | | -```text |
133 | | -<type>(<scope>): <short description> |
134 | | -``` |
135 | | - |
136 | | -Common types: |
| 43 | +Use these types: |
137 | 44 |
|
138 | 45 | - `feat` |
139 | 46 | - `fix` |
140 | | -- `docs` |
141 | 47 | - `refactor` |
142 | 48 | - `test` |
| 49 | +- `docs` |
143 | 50 | - `chore` |
144 | | -- `perf` |
145 | | - |
146 | | -Common scopes: |
147 | 51 |
|
148 | | -- `core` |
149 | | -- `suite` |
150 | | -- `gpu` |
151 | | -- `infra` |
152 | | -- `templates` |
153 | | -- `docs` |
| 52 | +Keep the summary under 72 characters. |
154 | 53 |
|
155 | 54 | Examples: |
156 | 55 |
|
157 | | -- `feat(suite): add boosting install rollback cleanup` |
158 | | -- `fix(infra): delete invalid compose files on validation failure` |
159 | | -- `docs(docs): align suite guide with current install flow` |
160 | | - |
161 | | -## Code Rules |
162 | | - |
163 | | -### General |
164 | | - |
165 | | -- Use Go 1.25-compatible code. CI runs on Go 1.26.1. |
166 | | -- Direct dependencies are intentionally minimal and require maintainer approval. |
167 | | -- Approved direct dependencies today are: |
168 | | - - `github.com/spf13/cobra v1.8.0` |
169 | | - - `github.com/msteinert/pam` |
170 | | - - `github.com/golang-jwt/jwt/v5` |
171 | | - - `github.com/gorilla/websocket` |
172 | | - - `github.com/creack/pty` |
173 | | -- New dependencies require explicit maintainer approval. |
174 | | -- Keep functions small and easy to test. |
175 | | -- Wrap errors with context. |
176 | | -- Leave the system clean on failure. |
177 | | - |
178 | | -### Output and UX |
| 56 | +- `feat(gpu): add secure boot enrollment guidance` |
| 57 | +- `fix(workspace): keep outputs cleanup scoped to workspace root` |
| 58 | +- `docs(reference): document resolver status commands` |
179 | 59 |
|
180 | | -- All command output in `cmd/` goes through `internal/ui/`. |
181 | | -- Do not use `fmt.Println` or `log.Printf` in `cmd/`. |
182 | | -- User-facing errors must explain recovery when practical. |
183 | | - |
184 | | -### Paths, images, and ports |
185 | | - |
186 | | -- Do not hardcode image tags outside `internal/suite/registry.go`. |
187 | | -- Do not hardcode workspace paths outside `internal/workspace/init.go`. |
188 | | -- Do not hardcode port assignments outside suite definitions and the shared port logic. |
189 | | -- `~/gradient/` is the fixed workspace root. |
190 | | - |
191 | | -### External commands |
192 | | - |
193 | | -- Use `exec.Command` or `exec.CommandContext` with separate arguments. |
194 | | -- Never build shell commands through string interpolation. |
195 | | -- Code that shells out must stay testable through an injectable command seam. |
196 | | -- Never call real Docker or GPU binaries in unit tests. |
197 | | - |
198 | | -### Privilege boundaries |
199 | | - |
200 | | -- Direct system privilege escalation is tightly scoped. |
201 | | -- CLI privilege helpers live in `internal/system/privileged.go`. |
202 | | -- Server-side host controls are mediated by the packaged `gradient-svc` systemd service and its locked sudoers rule. |
203 | | -- Do not write to `/etc`, `/usr`, or `/var` outside approved packaging, service, or GPU/setup flows. |
204 | | -- Do not use `--privileged` or `--network host`. |
205 | | - |
206 | | -### Data safety |
| 60 | +### Tests |
207 | 61 |
|
208 | | -- `remove` and `rollback` must never touch: |
209 | | - - `~/gradient/data/` |
210 | | - - `~/gradient/models/` |
211 | | - - `~/gradient/notebooks/` |
212 | | -- Invalid generated Compose files must be deleted before returning an error. |
213 | | -- Mutating commands must remain safe to interrupt and safe to rerun. |
214 | | - |
215 | | -## Testing and Quality Gates |
216 | | - |
217 | | -Run these locally before opening a PR: |
218 | | - |
219 | | -```bash |
220 | | -go test ./... |
221 | | -go test -race ./... |
222 | | -go vet ./... |
223 | | -CGO_ENABLED=0 go build -o concave . |
224 | | -``` |
| 62 | +- Add or update unit tests for any new function or behavior change. |
| 63 | +- Run `go test ./...` before opening a pull request. |
| 64 | +- Run `go test -race ./...` when you touch shared state, jobs, or long-lived goroutines. |
| 65 | +- Integration tests belong in `tests/integration/` and should stay opt-in. |
225 | 66 |
|
226 | | -Coverage gate: |
| 67 | +### Pull requests |
227 | 68 |
|
228 | | -- overall coverage must be at least 80% |
229 | | -- no package may fall below 60% |
| 69 | +- Keep pull requests focused on one logical change. |
| 70 | +- Explain what changed, why it changed, and how you verified it. |
| 71 | +- Update user-facing docs in the same pull request when command behavior changes. |
230 | 72 |
|
231 | | -Integration tests: |
| 73 | +## Code conventions |
232 | 74 |
|
233 | | -- live under `tests/integration/` |
234 | | -- must skip unless `CONCAVE_INTEGRATION=1` is set |
235 | | -- are for real environment validation, not default CI execution |
236 | | - |
237 | | -Example: |
238 | | - |
239 | | -```bash |
240 | | -CONCAVE_INTEGRATION=1 go test ./tests/integration -v |
241 | | -``` |
242 | | - |
243 | | -GPU-related changes must include manual validation notes in the PR description. |
244 | | - |
245 | | -## Documentation Expectations |
246 | | - |
247 | | -Update docs when you change: |
248 | | - |
249 | | -- command behavior |
250 | | -- suite topology |
251 | | -- ports |
252 | | -- environment variables |
253 | | -- workspace mounts |
254 | | -- GPU setup flow |
255 | | -- rollback/update behavior |
256 | | - |
257 | | -Required doc targets: |
258 | | - |
259 | | -- system behavior: `docs/*.md` |
260 | | -- suite behavior and service internals: `docs/suites/<suite>.md` |
261 | | -- exported Go symbols: godoc comments in source |
262 | | - |
263 | | -## What Gets Rejected |
264 | | - |
265 | | -These changes will be rejected: |
266 | | - |
267 | | -- PRs opened directly to `main` |
268 | | -- new dependencies without approval |
269 | | -- `fmt.Println` or `log.Printf` in `cmd/` |
270 | | -- hardcoded image tags outside `internal/suite/registry.go` |
271 | | -- hardcoded workspace paths outside `internal/workspace/init.go` |
272 | | -- docs added outside `docs/` or inline godoc |
273 | | -- a `services/` directory or docs in `templates/` |
274 | | -- shell string interpolation in `exec.Command` |
275 | | -- `sudo` outside approved GPU/setup files |
276 | | -- changes that modify user data during remove or rollback |
277 | | -- undocumented behavior changes |
278 | | - |
279 | | -## Internal Workflows |
| 75 | +- All terminal output in `cmd/` must go through `internal/ui/printer.go`. |
| 76 | +- Do not use `fmt.Println` or `log.Printf` in `cmd/`. |
| 77 | +- Docker-facing functions should accept `context.Context` first. |
| 78 | +- Keep direct dependencies tightly controlled. Any new dependency needs prior discussion in an issue. |
| 79 | +- `internal/suite/registry.go` is the single source of truth for suite names, images, ports, and mounts. |
| 80 | +- `cmd/` is the only layer that may call `os.Exit`. |
| 81 | +- Return errors up the call stack and wrap them with context, for example `fmt.Errorf("docker pull %s: %w", image, err)`. |
280 | 82 |
|
281 | | -This repository may also be developed with private internal scaffolding that is not |
282 | | -checked into version control. That internal workflow is not the contributor contract. |
| 83 | +## What we don't accept |
283 | 84 |
|
284 | | -For public contributions, `CONTRIBUTING.md` is the repo policy. |
| 85 | +- Dependencies added without prior discussion in an issue. |
| 86 | +- Code that writes outside `~/gradient/` without explicit user confirmation. |
| 87 | +- Hardcoded image tags outside `internal/suite/registry.go`. |
| 88 | +- Shell string interpolation with user-controlled input. |
285 | 89 |
|
286 | | -## Security Reports |
| 90 | +## License |
287 | 91 |
|
288 | | -Do not open public issues for security vulnerabilities. Report them privately to the |
289 | | -maintainers through the project security contact. |
| 92 | +By contributing, you agree that your contributions are licensed under the MIT License. |
0 commit comments