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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ version: 2
updates:
# ----- Go modules (the codeiq application) -----
- package-ecosystem: "gomod"
directory: "/go"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/go-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ jobs:
runs-on: ubuntu-latest
env:
CGO_ENABLED: "1"
defaults:
run:
working-directory: go
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
Expand All @@ -32,7 +29,7 @@ jobs:
# infinite loop) which is reachable via review.Client.Review.
go-version: '1.25.10'
cache: true
cache-dependency-path: go/go.sum
cache-dependency-path: go.sum
- name: Install C toolchain
run: sudo apt-get update -y && sudo apt-get install -y build-essential
- name: go vet
Expand Down
18 changes: 3 additions & 15 deletions .github/workflows/perf-gate.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
name: perf-gate

# Performance regression gate. Runs `codeiq index` against fixture-multi-lang
# and asserts wall-clock + node-count budgets. Catches regressions like:
# - Regex pathology re-introduced (e.g. the CertificateAuthDetector
# pre-screen miss that pushed indexing from 0.1s → 42s on PSA).
# - Detector over-emission past the dedup budget.
#
# Trigger: push to main + PRs that touch go/**. Manual via workflow_dispatch.
# Trigger: push to main + PRs that touch any source. Manual via workflow_dispatch.
# Failure is informational on PRs (`continue-on-error`) until the threshold
# is curated against real-world load; once stable, set strict gate.

on:
push:
branches: [main]
Expand All @@ -20,10 +18,8 @@ on:
# status to be reported" on non-Go PRs. Wall-clock is ~1 minute; the
# signal is worth the cost.
workflow_dispatch:

permissions:
contents: read

jobs:
bench:
name: index perf gate (fixture-multi-lang)
Expand Down Expand Up @@ -51,14 +47,13 @@ jobs:
with:
go-version: '1.25.10'
cache: true
cache-dependency-path: go/go.sum
cache-dependency-path: go.sum
- name: Install C toolchain
run: sudo apt-get update -y && sudo apt-get install -y build-essential
- name: Build codeiq
working-directory: go
run: go build -o /tmp/codeiq ./cmd/codeiq
- name: Stage fixture (separate copy so cache writes don't dirty git)
run: cp -r go/testdata/fixture-multi-lang /tmp/fm-perf
run: cp -r testdata/fixture-multi-lang /tmp/fm-perf
- name: Run + measure
id: bench
run: |
Expand All @@ -67,7 +62,6 @@ jobs:
/tmp/codeiq index /tmp/fm-perf > /tmp/perf.log 2>&1
END=$(date +%s.%N)
ELAPSED=$(awk "BEGIN{printf \"%.3f\", $END - $START}")

# Parse the "Files: F Nodes: N Edges: E ..." summary line.
NODES=$(awk -F'[ ]+' '/^Files:/ {print $4}' /tmp/perf.log)
EDGES=$(awk -F'[ ]+' '/^Files:/ {print $6}' /tmp/perf.log)
Expand All @@ -77,12 +71,10 @@ jobs:
DEDUP_NODES=${DEDUP_NODES:-0}
DROPPED=$(awk -F'[ ]+' '/^Deduped:/ {for(i=1;i<=NF;i++) if($i=="Dropped:") print $(i+1)}' /tmp/perf.log)
DROPPED=${DROPPED:-0}

echo "elapsed=$ELAPSED" >> "$GITHUB_OUTPUT"
echo "nodes=$NODES" >> "$GITHUB_OUTPUT"
echo "edges=$EDGES" >> "$GITHUB_OUTPUT"
echo "dropped=$DROPPED" >> "$GITHUB_OUTPUT"

{
echo "## codeiq perf gate"
echo ""
Expand All @@ -94,9 +86,7 @@ jobs:
echo "| deduped nodes | $DEDUP_NODES | — |"
echo "| dropped phantom edges | $DROPPED | ratio gated |"
} >> "$GITHUB_STEP_SUMMARY"

cat /tmp/perf.log >> "$GITHUB_STEP_SUMMARY"

# --- Hard gates ---
fail=0
if awk "BEGIN{exit !($ELAPSED > $MAX_INDEX_SECONDS)}"; then
Expand Down Expand Up @@ -129,7 +119,6 @@ jobs:
RSS=$(awk -F': ' '/Maximum resident set size/ {print $2}' /tmp/perf-enrich.time)
RSS=${RSS:-0}
ELAPSED=$(awk -F': ' '/Elapsed \(wall clock\)/ {print $2}' /tmp/perf-enrich.time)

{
echo ""
echo "## codeiq enrich memory gate"
Expand All @@ -140,7 +129,6 @@ jobs:
echo "| wall-clock | $ELAPSED | — |"
} >> "$GITHUB_STEP_SUMMARY"
cat /tmp/perf-enrich.log >> "$GITHUB_STEP_SUMMARY"

if [ "$RSS" -gt "$MAX_ENRICH_RSS_KB" ]; then
echo "::error::enrich peak RSS ${RSS} KB exceeds budget ${MAX_ENRICH_RSS_KB} KB"
exit 1
Expand Down
31 changes: 9 additions & 22 deletions .github/workflows/release-darwin.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
name: release-darwin

# darwin/arm64 release on a macos-14 runner. Attaches binaries to the
# existing GitHub Release created by release-go.yml (which only builds
# linux). Runs after the linux release lands so the target Release
Expand All @@ -11,7 +10,6 @@ name: release-darwin
# - macos-14 runners are arm64 (M1+); cross-compile to darwin/arm64
# happens via native CC = clang.
# - The two workflows publish to the same tag → same Release.

on:
push:
tags:
Expand All @@ -21,18 +19,15 @@ on:
tag:
description: 'Tag to release (e.g. v0.3.0). Release must already exist.'
required: true

permissions:
contents: write
id-token: write # Sigstore keyless via GitHub OIDC
attestations: write

# Pass the input/ref to the shell via env vars (not inline `${{ }}`
# interpolation) — Semgrep `yaml.github-actions.security.run-shell-injection`
# rule. inputs.tag for workflow_dispatch; GITHUB_REF_NAME for tag pushes.
env:
TAG: ${{ github.event.inputs.tag || github.ref_name }}

jobs:
release-darwin:
name: release (darwin / arm64)
Expand All @@ -45,10 +40,8 @@ jobs:
with:
go-version: '1.25.10'
cache: true
cache-dependency-path: go/go.sum

cache-dependency-path: go.sum
- name: Build darwin/arm64 binary
working-directory: go
env:
CGO_ENABLED: '1'
GOOS: darwin
Expand All @@ -58,32 +51,28 @@ jobs:
go build \
-trimpath \
-ldflags "-s -w \
-X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Version=${VERSION}' \
-X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Commit=$(git rev-parse --short HEAD)' \
-X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Date=$(date -u +%Y-%m-%dT%H:%M:%SZ)' \
-X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Dirty=false'" \
-X 'github.com/randomcodespace/codeiq/internal/buildinfo.Version=${VERSION}' \
-X 'github.com/randomcodespace/codeiq/internal/buildinfo.Commit=$(git rev-parse --short HEAD)' \
-X 'github.com/randomcodespace/codeiq/internal/buildinfo.Date=$(date -u +%Y-%m-%dT%H:%M:%SZ)' \
-X 'github.com/randomcodespace/codeiq/internal/buildinfo.Dirty=false'" \
-o codeiq ./cmd/codeiq

- name: Package archive
working-directory: go
run: |
VERSION="${TAG#v}"
ARCHIVE_DIR="codeiq_${VERSION}_darwin_arm64"
mkdir -p "${ARCHIVE_DIR}"
cp codeiq "${ARCHIVE_DIR}/"
cp ../LICENSE "${ARCHIVE_DIR}/" 2>/dev/null || true
cp ../README.md "${ARCHIVE_DIR}/" 2>/dev/null || true
cp ../CHANGELOG.md "${ARCHIVE_DIR}/" 2>/dev/null || true
tar czf "../${ARCHIVE_DIR}.tar.gz" "${ARCHIVE_DIR}"

cp LICENSE "${ARCHIVE_DIR}/" 2>/dev/null || true
cp README.md "${ARCHIVE_DIR}/" 2>/dev/null || true
cp CHANGELOG.md "${ARCHIVE_DIR}/" 2>/dev/null || true
tar czf "${ARCHIVE_DIR}.tar.gz" "${ARCHIVE_DIR}"
- name: Install Syft (SBOM)
uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
- name: Generate SBOM
run: |
VERSION="${TAG#v}"
ARCHIVE="codeiq_${VERSION}_darwin_arm64.tar.gz"
syft "$ARCHIVE" --output spdx-json="${ARCHIVE}.sbom.spdx.json"

- name: Install Cosign (signing)
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Sign archive (Sigstore keyless, bundle format)
Expand All @@ -94,7 +83,6 @@ jobs:
--yes \
--bundle "${ARCHIVE}.cosign.bundle" \
"$ARCHIVE"

- name: Upload to GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -116,7 +104,6 @@ jobs:
done
echo "::error::Release $TAG never appeared; release-go.yml may have failed"
exit 1

- name: Attest darwin archive (build provenance)
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
with:
go-version: '1.25.10'
cache: true
cache-dependency-path: go/go.sum
cache-dependency-path: go.sum
- name: Install build deps
run: |
sudo apt-get update -y
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
# go-ci.yml) is the call-graph-aware companion that filters to
# *reachable* vulns — keeping both gives both "have we got it"
# AND "are we exposed".
run: ./osv-scanner --lockfile=go/go.mod
run: ./osv-scanner --lockfile=go.mod

trivy:
name: Trivy (filesystem + container scan)
Expand Down Expand Up @@ -136,8 +136,8 @@ jobs:
node-version: '20'
- run: |
# Scope jscpd to Go production code only:
# - go/cmd — main entry point
# - go/internal — production code (100 detectors + pipeline + MCP)
# - cmd — main entry point
# - internal — production code (100 detectors + pipeline + MCP)
# Tests share fixture/assertion shape by design (parallelism for
# catching contract regressions, not a refactoring target).
#
Expand All @@ -160,7 +160,7 @@ jobs:
--reporters consoleFull \
--format "go" \
--ignore "**/vendor/**,**/testdata/**,**/grammar/**,**/generated/**,**/dist/**,**/coverage/**,**/intelligence/extractor/**/language_extractor.go,**/detector/**/structures.go" \
go/cmd go/internal
cmd internal

sbom:
name: SBOM (SPDX + CycloneDX)
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,11 @@ phase*-plan.md
# ignored directory's contents cannot be re-included by a later pattern.
!docs/superpowers/plans/
!docs/superpowers/plans/*.md

# ---- merged from go/.gitignore on go/ → root hoist ----
/codeiq
/codeiq.exe
/coverage.out
/coverage.html
/dist/
/.cache/
42 changes: 13 additions & 29 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,23 @@
# CGO is required (kuzudb + go-sqlite3 native deps), so we cross-compile
# via per-target runners — see the release workflow matrix. This file
# is consumed once per target OS.

version: 2
project_name: codeiq

env:
- CGO_ENABLED=1
- GO_VERSION=1.25.10

before:
hooks:
# Sanity gate. Failing here aborts the release before any binary
# leaves the runner. Goreleaser runs each hook via exec.Command
# (no shell), so bare `cd go && …` fails — `cd` isn't an executable
# in $PATH. Wrap in `sh -c` to get a working-directory side-effect.
- sh -c "cd go && go mod download"
- sh -c "cd go && go test ./... -count=1"

# leaves the runner. Module lives at repo root since the hoist; no
# subdirectory `cd` is needed. Hooks still go via `sh -c` for parity
# with the build steps and to keep shell features available.
- sh -c "go mod download"
- sh -c "go test ./... -count=1"
builds:
# linux/amd64 — native build on the ubuntu-latest runner.
- id: codeiq-linux-amd64
main: ./cmd/codeiq
dir: go
binary: codeiq
env:
- CGO_ENABLED=1
Expand All @@ -36,17 +31,16 @@ builds:
- -trimpath
ldflags:
- -s -w
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Version={{.Version}}'
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Commit={{.ShortCommit}}'
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Date={{.Date}}'
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Dirty={{.IsGitDirty}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Version={{.Version}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Commit={{.ShortCommit}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Date={{.Date}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Dirty={{.IsGitDirty}}'
goos: [linux]
goarch: [amd64]
# linux/arm64 — cross-compile from the ubuntu-latest runner using
# gcc-aarch64-linux-gnu installed in the release workflow.
- id: codeiq-linux-arm64
main: ./cmd/codeiq
dir: go
binary: codeiq
env:
- CGO_ENABLED=1
Expand All @@ -55,15 +49,14 @@ builds:
- -trimpath
ldflags:
- -s -w
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Version={{.Version}}'
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Commit={{.ShortCommit}}'
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Date={{.Date}}'
- -X 'github.com/randomcodespace/codeiq/go/internal/buildinfo.Dirty={{.IsGitDirty}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Version={{.Version}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Commit={{.ShortCommit}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Date={{.Date}}'
- -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Dirty={{.IsGitDirty}}'
goos: [linux]
goarch: [arm64]
# darwin/arm64 ships from `release-darwin.yml` (macos-14 runner) and
# attaches to the same Release that this config creates.

archives:
- id: codeiq
formats: [tar.gz]
Expand All @@ -73,14 +66,11 @@ archives:
- LICENSE*
- README.md
- CHANGELOG.md

checksum:
name_template: 'checksums.sha256'
algorithm: sha256

snapshot:
version_template: '{{ incpatch .Version }}-next'

# SBOM generation — Plan §5 SBOM signing requirement. Syft is the
# OSS-CLI choice (matches the existing security.yml stack).
sboms:
Expand All @@ -93,7 +83,6 @@ sboms:
- '$artifact'
- --output
- 'spdx-json={{ .ArtifactName }}.sbom.spdx.json'

# Cosign keyless signing of the checksum manifest. The release workflow
# supplies the OIDC token via `id-token: write`; cosign records the
# signature transparency entry in Rekor (public Sigstore log). No
Expand All @@ -113,7 +102,6 @@ signs:
artifacts: checksum
output: true
signature: '${artifact}.cosign.bundle'

release:
github:
owner: RandomCodeSpace
Expand All @@ -124,14 +112,10 @@ release:
name_template: 'v{{ .Version }}'
header: |
## codeiq v{{ .Version }}

Deterministic code knowledge graph — Go single-binary release.

Verify the download:

# Checksum
sha256sum -c checksums.sha256

# Signature (Sigstore keyless, bundle format)
cosign verify-blob \
--bundle checksums.sha256.cosign.bundle \
Expand Down
Loading
Loading