Rename the reusable workflows to release.yml and update-release.yml, add UPX compression for release binaries, and sync the standalone update-release workflow with the active release pipeline fixes. Update README, AGENTS, compliance notes, and changelog references to match the new workflow names and usage patterns.
372 lines
13 KiB
Markdown
372 lines
13 KiB
Markdown
# Vociferate Standards Compliance Analysis
|
|
|
|
**Date:** March 21, 2026
|
|
**Repository:** git.hrafn.xyz/aether/vociferate
|
|
**Analysis Scope:** Go codebase, CI workflows, and engineering practices
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
The vociferate codebase demonstrates **solid fundamentals** in testing, error handling, and package organization but **lacks critical CI/CD workflow validation** steps documented in the project standards. The main gaps are:
|
|
|
|
- ✅ **Strong:** Test structure (testify suites), coverage (80%+), error handling (proper wrapping)
|
|
- ⚠️ **Acceptable:** Dependency injection patterns (functional options pattern used appropriately)
|
|
- ❌ **Critical Gaps:** Missing `go fmt`, `go mod tidy/verify`, `gosec`, `govulncheck` in CI workflows
|
|
|
|
---
|
|
|
|
## 1. Testing Structure
|
|
|
|
### ✅ Status: COMPLIANT
|
|
|
|
**Findings:**
|
|
|
|
- **Test file format:** Properly organized in `*_test.go` files
|
|
- [cmd/vociferate/main_test.go](cmd/vociferate/main_test.go)
|
|
- [internal/vociferate/vociferate_test.go](internal/vociferate/vociferate_test.go)
|
|
- [internal/vociferate/vociferate_internal_test.go](internal/vociferate/vociferate_internal_test.go)
|
|
|
|
- **Testify suite usage:** ✅ Yes, properly implemented
|
|
- `PrepareSuite` in [vociferate_test.go](internal/vociferate/vociferate_test.go#L12) uses `suite.Suite`
|
|
- Tests use `require` assertions from testify
|
|
- Setup/teardown via `SetupTest()` method
|
|
- **Coverage analysis:**
|
|
- **cmd/vociferate:** 84.6% ✅ (exceeds 80% target)
|
|
- **internal/vociferate:** 80.9% ✅ (meets 80% target)
|
|
- **Total:** Both packages meet or exceed target
|
|
- Coverage methodology: `go test -covermode=atomic -coverprofile=coverage.out ./...`
|
|
|
|
**Compliance:** ✅ Full compliance with testing standards
|
|
|
|
---
|
|
|
|
## 2. Dependency Injection
|
|
|
|
### ⚠️ Status: PARTIAL COMPLIANCE
|
|
|
|
**Findings:**
|
|
|
|
**What's Good:**
|
|
|
|
- ✅ No global singletons or hidden state
|
|
- ✅ Package state is minimal and functions are stateless
|
|
- ✅ Functional options pattern used (`vociferate.Options` struct):
|
|
```go
|
|
type Options struct {
|
|
VersionFile string
|
|
VersionPattern string
|
|
Changelog string
|
|
}
|
|
```
|
|
- ✅ Functions accept options explicitly (not constructor-injected, but appropriate for this use case)
|
|
|
|
**What Needs Attention:**
|
|
|
|
- ⚠️ **No explicit `New*` constructor functions** — This is acceptable for a utility library, but pattern not followed
|
|
- ⚠️ **Global regex variables** (4 instances, should be const or lazy-initialized):
|
|
|
|
```go
|
|
var releasedSectionRe = regexp.MustCompile(`(?m)^## \[(\d+\.\d+\.\d+)\] - `)
|
|
var linkedReleasedSectionRe = regexp.MustCompile(...)
|
|
var unreleasedHeadingRe = regexp.MustCompile(...)
|
|
var releaseHeadingRe = regexp.MustCompile(...)
|
|
var refLinkLineRe = regexp.MustCompile(...)
|
|
```
|
|
|
|
- **Issue:** Mutable global state; should be const or initialized once
|
|
- **Low risk** for this codebase (single-use CLI), but violates best practices
|
|
|
|
**Compliance:** ⚠️ Acceptable for library code; regex vars could be improved
|
|
|
|
---
|
|
|
|
## 3. Error Handling
|
|
|
|
### ✅ Status: EXCELLENT
|
|
|
|
**Findings:**
|
|
|
|
- ✅ All errors wrapped with context using `fmt.Errorf("%w", err)`
|
|
- ✅ Consistent error wrapping throughout codebase:
|
|
- [vociferate.go lines 68, 73, 81, 87, 104](internal/vociferate/vociferate.go#L68-L87)
|
|
- `"version must not be empty"` → `fmt.Errorf("version must not be empty")`
|
|
- `"compile version pattern: %w"` → wraps underlying error
|
|
- `"read version file: %w"` → proper context wrapping
|
|
- `"write changelog: %w"` → proper context wrapping
|
|
|
|
- ✅ No log-and-return anti-pattern observed
|
|
- ✅ Error propagation allows callers to decide handling
|
|
|
|
**Examples of proper error handling:**
|
|
|
|
```go
|
|
// From updateVersionFile
|
|
if err := os.ReadFile(path); err != nil {
|
|
if os.IsNotExist(err) {
|
|
return os.WriteFile(...)
|
|
}
|
|
return fmt.Errorf("read version file: %w", err)
|
|
}
|
|
|
|
// From resolveOptions
|
|
versionExpr, err := regexp.Compile(pattern)
|
|
if err != nil {
|
|
return resolvedOptions{}, fmt.Errorf("compile version pattern: %w", err)
|
|
}
|
|
```
|
|
|
|
**Compliance:** ✅ Full compliance with error handling standards
|
|
|
|
---
|
|
|
|
## 4. Package Organization
|
|
|
|
### ✅ Status: COMPLIANT
|
|
|
|
**Findings:**
|
|
|
|
- ✅ **Domain-driven structure:**
|
|
- `internal/vociferate/` — Core domain logic
|
|
- `cmd/vociferate/` — CLI entry point
|
|
- No layer-based top-level packages (no `service/`, `handler/`, `repository/`)
|
|
|
|
- ✅ **Clear separation of concerns:**
|
|
- CLI parsing and execution in `cmd/vociferate/main.go`
|
|
- Domain logic in `internal/vociferate/vociferate.go`
|
|
- Tests colocated with implementations
|
|
|
|
- ✅ **Version placeholder package** (empty, future-ready):
|
|
- `internal/vociferate/version/` — Prepared for versioning but not yet populated
|
|
|
|
- ✅ **Minimal, focused code organization:**
|
|
- No unnecessary intermediate packages
|
|
- Clear domain boundaries
|
|
|
|
**Compliance:** ✅ Full compliance with package organization standards
|
|
|
|
---
|
|
|
|
## 5. CI/CD Workflows
|
|
|
|
### ✅ Status: COMPLIANT
|
|
|
|
**Workflows analyzed:**
|
|
|
|
- [push-validation.yml](.gitea/workflows/push-validation.yml)
|
|
- [release.yml](.gitea/workflows/release.yml)
|
|
- [update-release.yml](.gitea/workflows/update-release.yml)
|
|
|
|
#### What's Implemented
|
|
|
|
**push-validation.yml:**
|
|
|
|
- ✅ Go 1.26.1 setup with `actions/setup-go@v5`
|
|
- ✅ Caching enabled (`cache: true`, `cache-dependency-path: go.sum`)
|
|
- ✅ Code formatting validation (`go fmt` check)
|
|
- ✅ Module hygiene checks (`go mod tidy` and `go mod verify`)
|
|
- ✅ Security analysis with `gosec`
|
|
- ✅ Vulnerability scanning with `govulncheck`
|
|
- ✅ Full unit test suite with coverage (`go test -covermode=atomic -coverprofile=coverage.out`)
|
|
- ✅ Coverage badge publication
|
|
- ✅ Release tag recommendation on `main` branch
|
|
|
|
**release.yml:**
|
|
|
|
- ✅ Go setup and caching
|
|
- ✅ Tests run before release preparation
|
|
- ✅ Version and changelog updates
|
|
- ✅ Tag creation
|
|
|
|
#### What's Fixed
|
|
|
|
| Step | Documented Requirement | Push Validation | Status |
|
|
| --------------------- | ----------------------------------------- | --------------- | -------- |
|
|
| **go fmt validation** | Required | ✅ YES | Enforced |
|
|
| **go mod tidy** | Required | ✅ YES | Enforced |
|
|
| **go mod verify** | Required | ✅ YES | Enforced |
|
|
| **gosec** | Required (`securego/gosec@v2`) | ✅ YES | Enforced |
|
|
| **govulncheck** | Required (`golang/govulncheck-action@v1`) | ✅ YES | Enforced |
|
|
|
|
**Implemented Actions (commit 7cb7b05):**
|
|
|
|
```yaml
|
|
# Now in push-validation.yml:
|
|
- name: Validate formatting
|
|
run: test -z "$(gofmt -l .)"
|
|
|
|
- name: Module hygiene
|
|
run: |
|
|
set -euo pipefail
|
|
go mod tidy
|
|
go mod verify
|
|
|
|
- name: Run gosec security analysis
|
|
uses: securego/gosec@v2
|
|
with:
|
|
args: ./...
|
|
|
|
- name: Run govulncheck
|
|
uses: golang/govulncheck-action@v1
|
|
with:
|
|
go-package: ./...
|
|
cache: true
|
|
cache-dependency-path: go.sum
|
|
```
|
|
|
|
**Note:** Changelog gate is a PR-level feature implemented in the `decorate-pr` action, not a push validation check.
|
|
|
|
---
|
|
|
|
## 6. Validation Sequence
|
|
|
|
### ✅ Status: NOW FOLLOWING DOCUMENTED STANDARD
|
|
|
|
**Documented sequence (from copilot-instructions.md):**
|
|
|
|
1. ✅ Run `go fmt ./...` for code formatting
|
|
2. ✅ **Validate formatting** — **NOW IMPLEMENTED**
|
|
3. ✅ **Run `go mod tidy` and `go mod verify`** — **NOW IMPLEMENTED**
|
|
4. ✅ Run focused package tests
|
|
5. ✅ Run broader test suites
|
|
6. ✅ **Run `gosec ./...`** — **NOW IMPLEMENTED**
|
|
7. ✅ **Run `govulncheck ./...`** — **NOW IMPLEMENTED**
|
|
8. ✅ Run full project validation (coverage checks)
|
|
9. ✅ Verify coverage gates per module (target 80%)
|
|
|
|
**Current workflow sequence (after commit 7cb7b05):**
|
|
|
|
1. Setup Go environment with caching ✅
|
|
2. Validate code formatting ✅
|
|
3. Check module hygiene (tidy + verify) ✅
|
|
4. Run security analysis (gosec) ✅
|
|
5. Run vulnerability scanning (govulncheck) ✅
|
|
6. Run full unit test suite with coverage ✅
|
|
7. Publish coverage badge ✅
|
|
8. (On main) Recommend next release tag ✅
|
|
|
|
**Impact:** All security, formatting, and module checks now run in CI, preventing:
|
|
|
|
- Inconsistent code formatting from merging ✅
|
|
- Stale/incorrect `go.mod` from merging ✅
|
|
- Known vulnerabilities from going undetected ✅
|
|
|
|
---
|
|
|
|
## 7. Additional Observations
|
|
|
|
### Code Quality Improvements (commit 7cb7b05)
|
|
|
|
**Regex Variables in `internal/vociferate/vociferate.go`:**
|
|
|
|
- ✅ Grouped into `var (...)` block for clarity
|
|
- ✅ Added clarifying comment about read-only nature
|
|
- Maintains Go idioms while signaling immutability intent
|
|
- No functional changes; improves code organization
|
|
|
|
### Justfile (Local Automation)
|
|
|
|
**Current state:** Aligned with CI baseline for local validation
|
|
|
|
```bash
|
|
go-build
|
|
go-test
|
|
validate-fmt
|
|
validate-mod
|
|
security
|
|
validate
|
|
```
|
|
|
|
**Implemented locally (commit 383aad4):**
|
|
|
|
- ✅ `validate-fmt` runs `go fmt ./...` and verifies `gofmt -l .` is clean
|
|
- ✅ `validate-mod` runs `go mod tidy` and `go mod verify`
|
|
- ✅ `security` runs `gosec ./...` and `govulncheck ./...`
|
|
- ✅ `validate` composes formatting, module hygiene, tests, and security checks
|
|
|
|
### Go Module Configuration
|
|
|
|
✅ **go.mod** is properly configured:
|
|
|
|
- Go 1.26 with toolchain 1.26.1
|
|
- Dependencies: `github.com/stretchr/testify v1.10.0` (for test suites)
|
|
- No extraneous dependencies
|
|
|
|
### Code Formatting
|
|
|
|
✅ **Code appears to follow Go conventions:**
|
|
|
|
- Consistent naming (camelCase for exported names)
|
|
- Proper error returns
|
|
- Clear package documentation
|
|
|
|
---
|
|
|
|
## Recommendations (Priority Order)
|
|
|
|
### ✅ COMPLETED (commit 7cb7b05)
|
|
|
|
1. ✅ **`gosec` security scanning** — Now implemented in `push-validation.yml`
|
|
2. ✅ **`govulncheck` vulnerability scanning** — Now implemented in `push-validation.yml`
|
|
3. ✅ **`go fmt` validation** — Now implemented in `push-validation.yml`
|
|
4. ✅ **Module hygiene checks** (`go mod tidy` + `go mod verify`) — Now implemented in `push-validation.yml`
|
|
5. ✅ **Regex variable organization** — Grouped with clarifying comments in `vociferate.go`
|
|
6. ✅ **DI service boundary** — `internal/vociferate` now uses a constructor-backed service with injected filesystem, environment, and git dependencies (commit 383aad4)
|
|
7. ✅ **Local validation parity** — `justfile` now mirrors CI checks for format, modules, tests, and security (commit 383aad4)
|
|
|
|
### 🟡 FUTURE (Lower Priority)
|
|
|
|
8. **Implement changelog gate in PR workflows** — The `decorate-pr` action has changelog gate support; consider enabling `changelog-gate-mode: soft` in workflow if desired for future enhancement.
|
|
|
|
---
|
|
|
|
## Summary Table
|
|
|
|
| Category | Standard | Status | Details |
|
|
| ------------------------ | ------------------------------------ | ------- | ------------------------------------------------------ |
|
|
| **Testing** | `*_test.go` + testify suites | ✅ PASS | 80%+ coverage in all packages |
|
|
| **DI Pattern** | Constructor functions, no singletons | ✅ PASS | Constructor-backed service with injected collaborators |
|
|
| **Error Handling** | fmt.Errorf with `%w` wrapping | ✅ PASS | Consistent throughout codebase |
|
|
| **Package Organization** | Domain-driven, no layer-based | ✅ PASS | Clean structure, no over-engineering |
|
|
| **go fmt validation** | Fail if formatting inconsistent | ✅ PASS | Enforced in workflows and local automation |
|
|
| **go mod checks** | tidy + verify | ✅ PASS | Enforced in workflows and local automation |
|
|
| **gosec** | Static security analysis | ✅ PASS | Enforced in workflows and local automation |
|
|
| **govulncheck** | Vulnerability scanning | ✅ PASS | Enforced in workflows and local automation |
|
|
| **Coverage gates** | 80% target per module | ✅ PASS | Both packages exceed/meet target |
|
|
| **Changelog gate** | Enforce changelog entries | ❌ FAIL | Not implemented |
|
|
|
|
---
|
|
|
|
## Conclusion
|
|
|
|
**Current State (Updated):** The codebase now demonstrates strong engineering fundamentals in testing, error handling, structure, **and CI/CD validation**.
|
|
|
|
✅ **All critical standards gaps have been addressed** across commits 7cb7b05 and 383aad4:
|
|
|
|
- Security scanning (`gosec` + `govulncheck`) now enforced
|
|
- Code formatting validation now required
|
|
- Module hygiene checks (`go mod tidy`/`verify`) now enforced
|
|
- Regex variable organization clarified
|
|
- Dependency injection implemented through a constructor-backed service
|
|
- Local `justfile` validation now mirrors CI checks
|
|
|
|
**Validation Sequence:** The workflow now follows the documented 8-step validation sequence from copilot-instructions.md:
|
|
|
|
1. Format validation
|
|
2. Module hygiene
|
|
3. Security analysis
|
|
4. Vulnerability scanning
|
|
5. Full test suite
|
|
6. Coverage analysis
|
|
|
|
**Effort Invested:**
|
|
|
|
- CI/CD improvements: workflow hardening in `push-validation.yml` and `release.yml`
|
|
- Code organization: injected service boundaries for filesystem, environment, and git access
|
|
- Local automation: `justfile` validation parity for format, modules, tests, and security
|
|
- **Primary commits:** 7cb7b05, 383aad4, 5c903c9
|
|
|
|
**Next Steps (Optional):**
|
|
|
|
- Consider enabling changelog gate in PR workflows for future enhancement
|