Skip to content

Commit 0b19757

Browse files
arodageCopilot
andauthored
docs: add copilot instructions and PR documentation checklist (open-edge-platform#425)
* docs: add copilot instructions and PR documentation checklist Introduce .github/copilot-instructions.md to guide GitHub Copilot with project-specific conventions covering architecture, build/test workflow, logging, code style, security, CI quality gates, documentation requirements, image template conventions, and key file references. Add a documentation checklist item to the PR template to ensure docs stay in sync with code. * Update .github/PULL_REQUEST_TEMPLATE.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * docs: add Go fallback commands for environments without Earthly --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent c3a1699 commit 0b19757

File tree

2 files changed

+158
-2
lines changed

2 files changed

+158
-2
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
**All** boxes should be checked before merging the PR
44

5-
- [] The changes in the PR have been built and tested
6-
- [] Ready to merge
5+
- [ ] The changes in the PR have been built and tested
6+
- [ ] Documentation has been updated to reflect the changes (or no doc update needed)
7+
- [ ] Ready to merge
78

89
#### Description <!-- REQUIRED -->
910
<!-- Please include a summary of the changes and the related issue. List

.github/copilot-instructions.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Copilot Instructions for os-image-composer
2+
3+
## Architecture Overview
4+
5+
OS Image Composer builds custom Linux images from pre-built packages. Key components:
6+
7+
- **Provider** (`internal/provider/`) - Orchestrates builds per OS (azl, elxr, emt, rcd, ubuntu). Implements `Provider` interface with `Name`, `Init`, `PreProcess`, `BuildImage`, `PostProcess` methods. Each provider exports an `OsName` constant and a `Register()` function
8+
- **Image makers** (`internal/image/`) - Creates output formats: `rawmaker/`, `isomaker/`, `initrdmaker/`
9+
- **Chroot** (`internal/chroot/`) - Isolated build environments with package installers for `deb/` and `rpm/`
10+
- **Config** (`internal/config/`) - Template loading, merging defaults with user templates, validation
11+
- **OsPackage** (`internal/ospackage/`) - Package utilities: `debutils/`, `rpmutils/` for dependency resolution
12+
13+
Data flow: CLI → Config loads template → Provider.Init → Provider.PreProcess (downloads packages) → Provider.BuildImage (creates chroot, installs packages, generates image) → Provider.PostProcess
14+
15+
## Build and Test
16+
17+
Always use **Earthly** for builds and testing when available. If Earthly is not configured in your environment, you can fall back to standard Go commands:
18+
19+
| Task | Earthly (preferred) | Go fallback |
20+
|------|---------------------|-------------|
21+
| Build | `earthly +build` | `go build ./...` |
22+
| Test (fast) | `earthly +test-quick` | `go test ./...` |
23+
| Test (coverage) | `earthly +test` | `go test -coverprofile=coverage.out ./...` |
24+
| Lint | `earthly +lint` | `golangci-lint run` |
25+
26+
Note: CI runs Earthly, so always verify with `earthly +test` and `earthly +lint` before opening a PR if possible, to avoid CI failures.
27+
28+
Coverage threshold is enforced in CI and auto-ratcheted — see `.coverage-threshold` for the current value
29+
30+
## Adding a New OS Provider
31+
32+
1. Create package in `internal/provider/{osname}/`
33+
2. Implement `provider.Provider` interface (see `internal/provider/provider.go`)
34+
3. Register in `cmd/os-image-composer/build.go` switch statement
35+
4. Add default configs in `config/osv/{osname}/`
36+
5. Create example templates in `image-templates/`
37+
38+
## Testing Patterns
39+
40+
- Use **stdlib `testing` only** — no testify or external assertion libraries
41+
- Use **table-driven tests** with `t.Run()` for multiple cases:
42+
```go
43+
tests := []struct{ name string; input string; want error }{...}
44+
for _, tt := range tests {
45+
t.Run(tt.name, func(t *testing.T) { ... })
46+
}
47+
```
48+
- Follow the **AAA pattern**: Arrange (setup), Act (execute), Assert (verify)
49+
- Test file naming: `*_test.go` in same package
50+
- Reset shared state in tests (see `resetBuildFlags()` pattern in `cmd/os-image-composer/build_test.go`)
51+
52+
## Error Handling
53+
54+
- **Always wrap** with context: `fmt.Errorf("failed to X: %w", err)`
55+
- Use named returns with defer for cleanup (see `docs/architecture/os-image-composer-coding-style.md`)
56+
- Never ignore errors with `_`
57+
58+
## Logging
59+
60+
- Use the project logger, **not** `fmt.Println` or `log` stdlib:
61+
```go
62+
import "github.com/open-edge-platform/os-image-composer/internal/utils/logger"
63+
64+
var log = logger.Logger()
65+
```
66+
- Every package that logs should declare `var log = logger.Logger()` at package level
67+
- **Three-layer logging strategy**:
68+
- **Utilities** (`internal/utils/`): primarily return errors; use `log.Debugf()` sparingly
69+
- **Business logic** (`internal/provider/`, `internal/config/`, etc.): log with business context (`log.Infof`, `log.Warnf`, `log.Errorf`) and return errors with technical context
70+
- **Top-level orchestrators** (`cmd/`): only return errors — logging happens at lower levels
71+
- Available levels: `log.Debugf()`, `log.Infof()`, `log.Warnf()`, `log.Errorf()`
72+
73+
## Code Style
74+
75+
- **Line length**: 120 characters max
76+
- **Function length**: under 50 lines — break up larger functions
77+
- **Parameters**: max 4–5 per function; use a config/options struct beyond that
78+
- **Imports**: stdlib → third-party → local (blank line separated)
79+
- **Struct-based design over globals** — prefer dependency injection
80+
- **Interface naming**: should end with `-er` when possible (e.g., `PackageInstaller`, `ConfigReader`)
81+
- **Named returns + defer for cleanup** — the standard cleanup pattern (not "goto fail"); see [coding style Section 4.3](docs/architecture/os-image-composer-coding-style.md)
82+
- **Linters** (`earthly +lint`): `govet`, `gofmt`, `errcheck`, `staticcheck`, `unused`, `gosimple` — all errors must be handled (`errcheck` is enforced)
83+
- Shell scripts: `set -euo pipefail`
84+
- See `docs/architecture/os-image-composer-coding-style.md` for the full guide
85+
86+
## Security
87+
88+
- **HTTP clients**: Always use `network.NewSecureHTTPClient()` or the singleton `network.GetSecureHTTPClient()` from `internal/utils/network/` — enforces TLS 1.2+ with approved cipher suites. Never use `http.DefaultClient`
89+
- **Command execution**: Use the `internal/utils/shell/` package which maintains an allowlist of approved system commands. Never use raw `exec.Command()`
90+
- **Input validation**: Sanitize user-provided filenames and paths; use `filepath.Clean()` on paths
91+
- **Template validation**: Templates are validated against JSON schema (`os-image-template.schema.json`) via `os-image-composer validate`
92+
- **File permissions**: `0700` for chroot dirs, `0755` for general dirs, `0644` for data files, `0640` for log files
93+
- CI runs **Trivy** (dependency vulnerability scanning — fails on HIGH/CRITICAL), **Gitleaks** (secret detection), and **Zizmor** (GitHub Actions security auditing)
94+
95+
## Documentation
96+
97+
**Every PR that changes behavior must include corresponding documentation updates.** Documentation is a first-class deliverable — treat it as part of the code change, not an afterthought.
98+
99+
Before opening a PR, check whether your changes affect any of these and update accordingly:
100+
101+
| What changed | Docs to update |
102+
|---|---|
103+
| CLI flags or commands | `docs/architecture/os-image-composer-cli-specification.md`, `docs/tutorial/usage-guide.md` |
104+
| Build process or Earthfile targets | `docs/tutorial/usage-guide.md`, this file's **Build and Test** section |
105+
| Image template schema or fields | `docs/architecture/os-image-composer-templates.md`, relevant `image-templates/*.yml` examples |
106+
| New OS provider | `docs/architecture/architecture.md`, this file's **Adding a New OS Provider** section |
107+
| New tutorial-worthy feature | Add or update a guide in `docs/tutorial/` |
108+
| Architecture or design decisions | Add an ADR in `docs/architecture/` |
109+
| Security-related changes | `docs/architecture/image-composition-tool-security-objectives.md` |
110+
| Caching behavior | `docs/architecture/os-image-composer-caching.md` |
111+
| Coding conventions | `docs/architecture/os-image-composer-coding-style.md` |
112+
| Dependencies or multi-repo setup | `docs/architecture/os-image-composer-multi-repo-support.md` |
113+
| User-facing features or fixes | `docs/release-notes.md` |
114+
115+
## Git Commits & PRs
116+
117+
- Sign commits: `git commit -S`
118+
- Conventional commits: `type(scope): description` (feat, fix, docs, test, refactor, chore)
119+
- **Always use** `.github/PULL_REQUEST_TEMPLATE.md` for PRs
120+
- Branch prefixes: `feature/`, `fix/`, `docs/`, `refactor/`
121+
- **Always update documentation** alongside code changes (see **Documentation** section above). If no docs need updating, explicitly state so in the PR description
122+
123+
## CI Quality Gates
124+
125+
All PRs must pass these checks before merging:
126+
127+
| Gate | What it checks |
128+
|------|----------------|
129+
| Unit tests + coverage | `earthly +test` — threshold auto-ratchets via `.coverage-threshold` |
130+
| Lint | `earthly +lint` — golangci-lint with `govet`, `gofmt`, `errcheck`, `staticcheck`, `unused`, `gosimple` |
131+
| Trivy scan | Dependency vulnerabilities (HIGH/CRITICAL) + SBOM generation |
132+
| Gitleaks | Secret leak detection in commits |
133+
| Zizmor | GitHub Actions workflow security auditing |
134+
| Integration builds | Per-OS/arch image builds |
135+
136+
## Image Template Conventions
137+
138+
- **Naming**: `<dist>-<arch>-<purpose>-<imageType>.yml` (e.g., `emt3-x86_64-minimal-raw.yml`)
139+
- **Minimal user templates**: only `image` + `target` sections required; OS defaults handle the rest
140+
- **Always include a `metadata` block** with `description`, `use_cases`, and `keywords` for discoverability
141+
- **Merge behavior**: packages are _additive_ (merged by name); `disk` configuration _replaces_ entirely
142+
- **Validate** before committing: `os-image-composer validate -t <template.yml>`
143+
144+
## Key Files
145+
146+
- `image-templates/*.yml` - Example image templates
147+
- `config/osv/` - OS-specific default configurations
148+
- `internal/config/config.go` - `ImageTemplate` struct definition
149+
- `internal/provider/provider.go` - Provider interface
150+
- `internal/utils/logger/` - Project logger (zap-based)
151+
- `internal/utils/network/securehttp.go` - Secure HTTP client
152+
- `internal/utils/shell/shell.go` - Command execution with allowlist
153+
- `.golangci.yml` - Linter configuration
154+
- `.coverage-threshold` - Current test coverage threshold
155+
- `docs/architecture/` - ADRs and design docs

0 commit comments

Comments
 (0)