Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ This eco uses **independent SemVer per repo** (see [VERSIONING.md](./VERSIONING.
That gives each component its own release cadence, but raises an obvious
question: *which combinations of versions are actually tested together?*

The answer lives in [`compatibility-matrix.json`](./compatibility-matrix.json).
The answer lives in [`testdata/compatibility-matrix.json`](./testdata/compatibility-matrix.json).

Platform/provider capability metadata is separate: [`platform-capabilities.json`](./platform-capabilities.json).

## What it records

Expand Down Expand Up @@ -46,7 +48,7 @@ existing consumers.
`.shared-templates/workflows/compatibility-test.yml.tmpl` is a reusable
workflow that:

1. Reads `compatibility-matrix.json` from the eco repo.
1. Reads `testdata/compatibility-matrix.json` from the hawk repo.
2. Checks out each component at the version listed in the named matrix.
3. Builds + tests the cross-repo integration scenarios.

Expand All @@ -68,21 +70,14 @@ It runs on:

## Validating the file

The file is validated against [`compatibility-matrix.schema.json`](./compatibility-matrix.schema.json)
The file is validated against [`testdata/compatibility-matrix.schema.json`](./testdata/compatibility-matrix.schema.json)
in CI. To validate locally:

```bash
# Quick check using ajv (Node)
make compat-check # structural validation + version pins

# Or with ajv (Node)
npx ajv-cli validate \
-s compatibility-matrix.schema.json \
-d compatibility-matrix.json

# Or with Python
python3 -c "
import json, jsonschema
schema = json.load(open('compatibility-matrix.schema.json'))
data = json.load(open('compatibility-matrix.json'))
jsonschema.validate(data, schema)
print('ok')
"
-s testdata/compatibility-matrix.schema.json \
-d testdata/compatibility-matrix.json
```
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ security: ## Run govulncheck.
@command -v $(GOVULNCHECK) >/dev/null 2>&1 || (echo "install: go install golang.org/x/vuln/cmd/govulncheck@latest" && exit 1)
$(GOVULNCHECK) ./...

tidy: ## Tidy go.mod / go.sum.
go mod tidy
tidy: ## Sync workspace modules and verify checksums.
go work sync
go mod verify

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -190,11 +190,11 @@ help: ## Show this help.
# ---------------------------------------------------------------------------
.PHONY: compat-test compat-check

compat-test: ## Validate compatibility-matrix.json and report the 'next' matrix.
@go run ./cmd/compat-test -matrix=next
compat-test: ## Validate testdata/compatibility-matrix.json and report the 'next' matrix.
@go run ./cmd/compat-test -matrix=next -file=testdata/compatibility-matrix.json

compat-check: ## Strict validation — non-zero exit if any component lacks a version.
@go run ./cmd/compat-test -matrix=next -strict
@go run ./cmd/compat-test -matrix=next -strict -file=testdata/compatibility-matrix.json

.PHONY: hooks
hooks:
Expand Down
16 changes: 11 additions & 5 deletions cmd/compat-test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,23 @@ func report(mf matrixFile, m matrix, strict bool) error {
return nil
}

// findMatrixFile looks for compatibility-matrix.json in the current dir, then
// walks up looking for one. Returns "" if not found within 6 levels.
// findMatrixFile locates the cross-repo compatibility matrix (testdata/compatibility-matrix.json).
// It must not pick hawk/platform-capabilities.json, which is a different document.
func findMatrixFile() string {
dir, err := os.Getwd()
if err != nil {
return ""
}
candidates := []string{
"testdata/compatibility-matrix.json",
"hawk/testdata/compatibility-matrix.json",
}
for i := 0; i < 6; i++ {
p := filepath.Join(dir, "compatibility-matrix.json")
if _, err := os.Stat(p); err == nil {
return p
for _, rel := range candidates {
p := filepath.Join(dir, rel)
if _, err := os.Stat(p); err == nil {
return p
}
}
parent := filepath.Dir(dir)
if parent == dir {
Expand Down
3 changes: 2 additions & 1 deletion cmd/testfirst_workflow.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"context"
"fmt"
"os"
"os/exec"
Expand Down Expand Up @@ -84,7 +85,7 @@ func RunTestFirstWorkflow(cfg TestFirstConfig, chatFn ReviewChatFn) TestFirstRes

// runTests executes the test command and returns output + pass status.
func runTests(testCmd string) (string, bool) {
cmd := exec.Command("sh", "-c", testCmd)
cmd := exec.CommandContext(context.Background(), "sh", "-c", testCmd)
cmd.Dir, _ = os.Getwd()
out, err := cmd.CombinedOutput()
output := strings.TrimSpace(string(out))
Expand Down
2 changes: 1 addition & 1 deletion external/eyrie
Submodule eyrie updated from 5205d4 to d5c3b9
2 changes: 1 addition & 1 deletion external/inspect
2 changes: 1 addition & 1 deletion external/sight
Submodule sight updated from a55274 to 6d3b83
2 changes: 1 addition & 1 deletion external/tok
Submodule tok updated from ad094a to fe2534
2 changes: 1 addition & 1 deletion external/trace
Submodule trace updated from d7a722 to 997be1
2 changes: 1 addition & 1 deletion external/yaad
Submodule yaad updated from 03b6f0 to abb300
7 changes: 4 additions & 3 deletions internal/bench/suite.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bench

import (
"context"
"encoding/json"
"fmt"
"os"
Expand Down Expand Up @@ -54,7 +55,7 @@ func runYaadBench(projectDir string) ([]BenchmarkResult, error) {
}

start := time.Now()
cmd := exec.Command("go", "test", "-bench=.", "-benchmem", "-count=1", "-timeout=60s", "./engine/...")
cmd := exec.CommandContext(context.Background(), "go", "test", "-bench=.", "-benchmem", "-count=1", "-timeout=60s", "./engine/...")
cmd.Dir = yaadDir
output, err := cmd.CombinedOutput()
duration := time.Since(start)
Expand All @@ -81,7 +82,7 @@ func runTokBench(projectDir string) ([]BenchmarkResult, error) {
}

start := time.Now()
cmd := exec.Command("go", "test", "-bench=.", "-benchmem", "-count=1", "-timeout=60s", "./...")
cmd := exec.CommandContext(context.Background(), "go", "test", "-bench=.", "-benchmem", "-count=1", "-timeout=60s", "./...")
cmd.Dir = tokDir
output, err := cmd.CombinedOutput()
duration := time.Since(start)
Expand All @@ -108,7 +109,7 @@ func runHawkBuildBench(projectDir string) (BenchmarkResult, error) {
}

start := time.Now()
cmd := exec.Command("go", "build", "-o", "/dev/null", ".")
cmd := exec.CommandContext(context.Background(), "go", "build", "-o", "/dev/null", ".")
cmd.Dir = hawkDir
err := cmd.Run()
duration := time.Since(start)
Expand Down
35 changes: 18 additions & 17 deletions internal/codegraph/algorithms_cgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package codegraph

import (
"context"
"fmt"
"sort"
"strings"
Expand Down Expand Up @@ -38,7 +39,7 @@ func (cg *CodeGraph) BetweennessCentrality(topN int) (*BetweennessResult, error)

// Build adjacency list from edges
adj := make(map[string][]string)
rows, err := cg.db.Query("SELECT source, target FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements')")
rows, err := cg.db.QueryContext(context.Background(), "SELECT source, target FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements')")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -150,7 +151,7 @@ func (cg *CodeGraph) BetweennessCentrality(topN int) (*BetweennessResult, error)
}
// Try to get node name and file
var name, filePath, kind string
err := cg.db.QueryRow("SELECT name, file_path, kind FROM nodes WHERE id = ?", s.id).Scan(&name, &filePath, &kind)
err := cg.db.QueryRowContext(context.Background(), "SELECT name, file_path, kind FROM nodes WHERE id = ?", s.id).Scan(&name, &filePath, &kind)
if err == nil {
nc.Name = name
nc.FilePath = filePath
Expand Down Expand Up @@ -194,7 +195,7 @@ func (cg *CodeGraph) CommunityDetection() (*CommunityDetectionResult, error) {
adj := make(map[string]map[string]float64)
var edges []edge

rows, err := cg.db.Query("SELECT source, target, kind FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements', 'contains')")
rows, err := cg.db.QueryContext(context.Background(), "SELECT source, target, kind FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements', 'contains')")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -349,7 +350,7 @@ func (cg *CodeGraph) ConnectedComponents() ([][]string, error) {

// Build adjacency list
adj := make(map[string][]string)
rows, err := cg.db.Query("SELECT source, target FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements')")
rows, err := cg.db.QueryContext(context.Background(), "SELECT source, target FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements')")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -426,7 +427,7 @@ func (cg *CodeGraph) DiffGraph(beforeNodes map[string]bool, beforeEdges map[stri

// Get current nodes
currentNodes := make(map[string]bool)
rows, _ := cg.db.Query("SELECT id, file_path FROM nodes")
rows, _ := cg.db.QueryContext(context.Background(), "SELECT id, file_path FROM nodes")
if rows != nil {
for rows.Next() {
var id, filePath string
Expand All @@ -450,7 +451,7 @@ func (cg *CodeGraph) DiffGraph(beforeNodes map[string]bool, beforeEdges map[stri

// Get current edges
currentEdges := make(map[string]bool)
rows, _ = cg.db.Query("SELECT source || '->' || target || ':' || kind FROM edges")
rows, _ = cg.db.QueryContext(context.Background(), "SELECT source || '->' || target || ':' || kind FROM edges")
if rows != nil {
for rows.Next() {
var edgeKey string
Expand Down Expand Up @@ -483,7 +484,7 @@ func (cg *CodeGraph) SnapshotGraph() (nodes map[string]bool, edges map[string]bo
nodes = make(map[string]bool)
edges = make(map[string]bool)

rows, err := cg.db.Query("SELECT id FROM nodes")
rows, err := cg.db.QueryContext(context.Background(), "SELECT id FROM nodes")
if err != nil {
return nil, nil, err
}
Expand All @@ -501,7 +502,7 @@ func (cg *CodeGraph) SnapshotGraph() (nodes map[string]bool, edges map[string]bo
}
rows.Close()

rows, err = cg.db.Query("SELECT source || '->' || target || ':' || kind FROM edges")
rows, err = cg.db.QueryContext(context.Background(), "SELECT source || '->' || target || ':' || kind FROM edges")
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -537,7 +538,7 @@ func (cg *CodeGraph) FindDeadCode() ([]DeadCodeEntry, error) {
defer cg.mu.RUnlock()

// Get all nodes
rows, err := cg.db.Query(
rows, err := cg.db.QueryContext(context.Background(),
`SELECT id, kind, name, qualified_name, file_path, language,
start_line, end_line, signature, docstring, visibility, is_exported
FROM nodes WHERE kind IN ('function', 'method', 'class', 'interface', 'struct')`,
Expand All @@ -551,7 +552,7 @@ func (cg *CodeGraph) FindDeadCode() ([]DeadCodeEntry, error) {

// Get all referenced node IDs
referenced := make(map[string]bool)
edgeRows, _ := cg.db.Query("SELECT DISTINCT target FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements')")
edgeRows, _ := cg.db.QueryContext(context.Background(), "SELECT DISTINCT target FROM edges WHERE kind IN ('calls', 'references', 'imports', 'extends', 'implements')")
if edgeRows != nil {
for edgeRows.Next() {
var target string
Expand All @@ -565,7 +566,7 @@ func (cg *CodeGraph) FindDeadCode() ([]DeadCodeEntry, error) {
}

// Also mark source nodes as referenced (they're being used)
edgeRows, _ = cg.db.Query("SELECT DISTINCT source FROM edges")
edgeRows, _ = cg.db.QueryContext(context.Background(), "SELECT DISTINCT source FROM edges")
if edgeRows != nil {
for edgeRows.Next() {
var source string
Expand Down Expand Up @@ -677,7 +678,7 @@ func (cg *CodeGraph) PageRank(iterations int, damping float64) (map[string]float
inlinks := make(map[string][]string)
nodes := make(map[string]bool)

rows, err := cg.db.Query("SELECT source, target FROM edges WHERE kind IN ('calls', 'references', 'imports')")
rows, err := cg.db.QueryContext(context.Background(), "SELECT source, target FROM edges WHERE kind IN ('calls', 'references', 'imports')")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -768,7 +769,7 @@ func (cg *CodeGraph) ImpactAnalysis(nodeID string, maxDepth int) (*ImpactResult,
result.Impacted[s.id] = s.depth

// Get all nodes that depend on this one
rows, _ := cg.db.Query(
rows, _ := cg.db.QueryContext(context.Background(),
`SELECT source FROM edges WHERE target = ? AND kind IN ('calls', 'references', 'imports', 'extends', 'implements')`, s.id,
)
if rows != nil {
Expand All @@ -789,7 +790,7 @@ func (cg *CodeGraph) ImpactAnalysis(nodeID string, maxDepth int) (*ImpactResult,
// Load node details
for id, depth := range result.Impacted {
var n Node
err := cg.db.QueryRow(
err := cg.db.QueryRowContext(context.Background(),
`SELECT id, kind, name, qualified_name, file_path, language,
start_line, end_line, signature, docstring, visibility, is_exported
FROM nodes WHERE id = ?`, id,
Expand Down Expand Up @@ -840,7 +841,7 @@ func (cg *CodeGraph) AnalyzeCoupling(topN int) ([]CouplingMetric, error) {

// Build file -> set of referenced symbols
fileDeps := make(map[string]map[string]bool)
rows, err := cg.db.Query("SELECT file_path, target FROM edges e JOIN nodes n ON n.id = e.source WHERE e.kind IN ('calls', 'references', 'imports')")
rows, err := cg.db.QueryContext(context.Background(), "SELECT file_path, target FROM edges e JOIN nodes n ON n.id = e.source WHERE e.kind IN ('calls', 'references', 'imports')")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -975,7 +976,7 @@ func FindCrossRepoCalls(repos []string) ([]CrossRepoCall, error) {
repoNodes[repoRoot] = make(map[string]bool)

// Get all nodes
rows, err := cg.db.Query("SELECT id, kind, name, qualified_name, file_path, language, start_line, end_line, signature, docstring, visibility, is_exported FROM nodes")
rows, err := cg.db.QueryContext(context.Background(), "SELECT id, kind, name, qualified_name, file_path, language, start_line, end_line, signature, docstring, visibility, is_exported FROM nodes")
if err != nil {
cg.Close()
continue
Expand All @@ -1002,7 +1003,7 @@ func FindCrossRepoCalls(repos []string) ([]CrossRepoCall, error) {
}

// Get unresolved refs (calls to symbols not in this repo)
rows, err := cg.db.Query("SELECT from_node_id, reference_name, file_path, line FROM unresolved_refs")
rows, err := cg.db.QueryContext(context.Background(), "SELECT from_node_id, reference_name, file_path, line FROM unresolved_refs")
if err != nil {
cg.Close()
continue
Expand Down
Loading
Loading