Skip to main content

Transformation: Go

Open Repo Download ZIP

git clone https://github.com/AEEF-AI/aeef-transform.git

The Transformation tier extends the Quick Start Go setup with a full 7-stage CI pipeline, mutation testing via go-mutesting, vulnerability checking with govulncheck, and provenance generation. This guide covers every addition.

Full Pipeline Walkthrough

The CI pipeline runs seven stages:

golangci-lint --> go-vet --> go-test --> go-mutesting --> govulncheck --> license-check --> schema-validate

Stage 1: Lint (golangci-lint)

- name: Lint
run: golangci-lint run --timeout 5m ./...

golangci-lint runs with an expanded linter set (see configuration below). The 5-minute timeout accommodates large codebases.

Stage 2: Vet

- name: Vet
run: go vet ./...

go vet catches issues that linters may miss, such as incorrect printf format strings and unreachable code.

Stage 3: Test with Coverage

- name: Test
run: |
go test -race -coverprofile=coverage.out -covermode=atomic ./...
go tool cover -func=coverage.out | grep total | awk '{print $3}' | \
awk -F. '{if ($1 < 80) {print "Coverage below 80%"; exit 1}}'

Runs tests with the race detector and enforces 80% line coverage.

Stage 4: Mutation Testing (go-mutesting)

- name: Mutation Testing
run: |
go install github.com/zimmski/go-mutesting/cmd/go-mutesting@latest
go-mutesting ./... > mutation-results.txt
go run scripts/check_mutation_score.go --threshold 70 --input mutation-results.txt

go-mutesting applies mutations to Go source code and runs the test suite against each mutation. A custom script validates the mutation score.

The threshold check script:

package main

import (
"bufio"
"flag"
"fmt"
"os"
"strings"
)

func main() {
threshold := flag.Float64("threshold", 70.0, "Minimum mutation score")
input := flag.String("input", "mutation-results.txt", "Mutation results file")
flag.Parse()

file, err := os.Open(*input)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
defer file.Close()

var killed, total int
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "FAIL") {
killed++
}
if strings.Contains(line, "FAIL") || strings.Contains(line, "PASS") {
total++
}
}

score := float64(killed) / float64(total) * 100
if score < *threshold {
fmt.Fprintf(os.Stderr, "Mutation score %.1f%% below threshold %.1f%%\n", score, *threshold)
os.Exit(1)
}
fmt.Printf("Mutation score: %.1f%% (threshold: %.1f%%)\n", score, *threshold)
}

Stage 5: Vulnerability Check (govulncheck)

- name: Vulnerability Check
run: govulncheck ./...

govulncheck queries the Go vulnerability database and reports any known vulnerabilities in dependencies that are actually reachable from your code.

Stage 6: License Check

- name: License Check
run: |
go install github.com/google/go-licenses@latest
go-licenses check ./... --allowed_licenses=MIT,ISC,BSD-2-Clause,BSD-3-Clause,Apache-2.0

Verifies all dependency licenses are on the organization's allow list.

Stage 7: Schema Validation

- name: Schema Validation
run: |
go install github.com/santhosh-tekuri/jsonschema/cmd/jv@latest
jv schemas/kpi-record.schema.json metrics/*.json

Validates KPI records and provenance logs against AEEF JSON schemas.

golangci-lint Configuration

The Transformation tier expands the linter set:

# .golangci.yml
linters:
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
- gocritic
- gocyclo
- gosec
- revive
- misspell
- bodyclose # Added: HTTP response body close check
- noctx # Added: HTTP request context check
- exportloopref # Added: loop variable capture check
- prealloc # Added: slice preallocation hints
- unparam # Added: unused parameter detection

linters-settings:
gocyclo:
min-complexity: 10
gocritic:
enabled-tags:
- diagnostic
- style
- performance
- opinionated
gosec:
severity: medium
confidence: medium
revive:
rules:
- name: unexported-return
- name: unused-parameter
- name: early-return

run:
timeout: 5m

Provenance Generation

A post-pipeline step generates provenance records:

- name: Generate Provenance
if: always()
run: go run scripts/generate_provenance.go --output provenance/

The provenance record captures all stage outcomes, coverage metrics, mutation scores, and dependency information.

Next Steps