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
37 changes: 31 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ jobs:
- name: Run golangci-lint
run: |
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.0
golangci-lint run --timeout=5m --disable=noctx
golangci-lint run --timeout=5m

# -------------------------------------------------------------------------
# 5. Tests — race detector, coverage threshold, test shuffling.
Expand All @@ -155,8 +155,8 @@ jobs:
echo "COVERAGE=${coverage}" >> "$GITHUB_ENV"
- name: Coverage threshold (minimum 50%)
run: |
if (( $(echo "${COVERAGE} < 50" | bc -l) )); then
echo "::error::Coverage ${COVERAGE}% is below minimum 50%"
if (( $(echo "${COVERAGE} < 60" | bc -l) )); then
echo "::error::Coverage ${COVERAGE}% is below minimum 60%"
exit 1
fi
- name: Upload coverage
Expand Down Expand Up @@ -216,12 +216,12 @@ jobs:
cache: true
- name: govulncheck
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
go install golang.org/x/vuln/cmd/govulncheck@v1.1.4
govulncheck ./...
- name: gosec (report only)
continue-on-error: true
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
go install github.com/securego/gosec/v2/cmd/gosec@v2.22.4
gosec -exclude=G104,G703,G704,G101,G107,G112,G114,G115,G201,G202,G203,G204,G301,G302,G304,G305,G306,G307,G401,G402,G403,G404,G501,G502,G503,G504,G505,G601,G602 -confidence=medium -severity=high ./...

# -------------------------------------------------------------------------
Expand Down Expand Up @@ -264,7 +264,7 @@ jobs:
cache: true
- name: deadcode
run: |
go install golang.org/x/tools/cmd/deadcode@latest
go install golang.org/x/tools/cmd/deadcode@v0.30.0
deadcode ./... 2>&1 | head -50

# -------------------------------------------------------------------------
Expand Down Expand Up @@ -323,6 +323,31 @@ jobs:
fi
rm -f /tmp/hawk-bin

# -------------------------------------------------------------------------
# Fuzz — short corpus runs to catch panics in fuzz targets.
# -------------------------------------------------------------------------
fuzz:
name: fuzz (60s)
runs-on: ubuntu-latest
needs: [test]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/actions/checkout-eyrie
with:
ref: ${{ github.head_ref || github.ref_name }}
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Run fuzz targets
run: |
go test -fuzz=FuzzScanForAIComments -fuzztime=60s ./cmd/... || true
go test -fuzz=FuzzValidateSettings -fuzztime=60s ./internal/config/... || true
go test -fuzz=FuzzIsSuspicious -fuzztime=60s ./internal/tool/... || true
go test -fuzz=FuzzIsSafeGitCommit -fuzztime=60s ./internal/tool/... || true
go test -fuzz=FuzzParseMessage -fuzztime=60s ./internal/session/... || true
go test -fuzz=FuzzParseSessionMeta -fuzztime=60s ./internal/session/... || true

# -------------------------------------------------------------------------
# 10. Smoke — build hawk and verify ecosystem CLI wiring.
# -------------------------------------------------------------------------
Expand Down
28 changes: 24 additions & 4 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,23 @@ jobs:
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

- name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0

- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
Expand All @@ -49,9 +52,10 @@ jobs:
type=sha,prefix=sha-

- name: Build and push
uses: docker/build-push-action@v6
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Expand All @@ -61,3 +65,19 @@ jobs:
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
BUILD_DATE=${{ github.event.head_commit.timestamp }}

- name: Scan image with Trivy
if: github.event_name != 'pull_request'
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}
format: sarif
output: trivy-image.sarif
severity: CRITICAL,HIGH
exit-code: '0'

- name: Upload Trivy image scan results
if: github.event_name != 'pull_request' && always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-image.sarif
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7.2.1
with:
distribution: goreleaser
version: "~> v2"
version: "v6.3.0"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
42 changes: 42 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Scorecard

on:
branch_protection_rule:
schedule:
- cron: '37 9 * * 1'
push:
branches: [main]

permissions:
security-events: write
id-token: write
contents: read

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Run analysis
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75b098e755 # v2.4.1
with:
results_file: scorecard-results.sarif
results_format: sarif
publish_results: true

- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: scorecard-results.sarif
retention-days: 5

- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: scorecard-results.sarif
5 changes: 5 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ changelog:
# Release — auto-detect prereleases (rc/beta tags). Created on the repo
# itself (not a separate release repo).
# ---------------------------------------------------------------------------
sboms:
- artifacts: archive
documents:
- "${artifact}.spdx.sbom.json"

release:
draft: false
prerelease: auto
Expand Down
11 changes: 5 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ COPY go.mod go.sum ./
RUN go mod download

COPY . .
# Add replace after source copy so it doesn't get overwritten
RUN echo "" >> go.mod && echo "replace github.com/GrayCodeAI/eyrie => /eyrie" >> go.mod && go mod tidy

RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -mod=mod \
# Use go.work to resolve the local eyrie checkout — avoids mutating go.mod at build time.
RUN go work init . /eyrie && \
CGO_ENABLED=0 GOOS=linux go build -trimpath \
-ldflags="-s -w -X main.Version=$(git describe --tags --always 2>/dev/null || echo dev)" \
-o hawk ./cmd/hawk

# Runtime stage — minimal image
FROM alpine:3.20
# Runtime stage — Alpine (hawk requires git + bash for workspace operations; distroless excluded)
FROM alpine:3.21

RUN apk add --no-cache ca-certificates git bash tini && \
adduser -D -u 1000 -h /home/hawk hawk
Expand Down
4 changes: 2 additions & 2 deletions cmd/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func panicRecovery(saveFn func()) {
_, _ = fmt.Fprintf(os.Stderr, "Details logged to ~/.hawk/crash.log\n")
_, _ = fmt.Fprintf(os.Stderr, "Please report this at: https://github.com/GrayCodeAI/hawk/issues\n\n")
_, _ = fmt.Fprintf(os.Stderr, "panic: %v\n", r)
os.Exit(1)
os.Exit(1) // os.Exit intentional: panic recovery, defer already unwound
}
}

Expand Down Expand Up @@ -269,7 +269,7 @@ func signalHandler(saveFn func()) {
}

_, _ = fmt.Fprintf(os.Stderr, "Goodbye.\n")
os.Exit(0)
os.Exit(0) // os.Exit intentional: signal handler, must terminate process
}()
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Examples:
}

if report.Failed() {
os.Exit(1)
return fmt.Errorf("inspect: one or more checks failed")
}
return nil
},
Expand Down
2 changes: 1 addition & 1 deletion cmd/sight.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func runSightReview(ctx context.Context, bridge *hawkSight.Bridge, diff string)
}

if result.Failed() {
os.Exit(1)
return fmt.Errorf("sight: one or more checks failed")
}
return nil
}
Expand Down
Loading
Loading