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
81 changes: 81 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: CI

on:
push:
branches: [main]
pull_request:

# Cancel superseded runs on the same ref to save minutes.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Check formatting (gofmt -s)
run: |
unformatted="$(gofmt -s -l .)"
if [ -n "$unformatted" ]; then
echo "These files are not gofmt -s formatted:"
echo "$unformatted"
exit 1
fi
- name: Vet
run: go vet ./...
- name: Test (race + coverage)
run: go test -race -cover ./...

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- uses: golangci/golangci-lint-action@v6
with:
version: v1.62.2

vulncheck:
name: Govulncheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Run govulncheck
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...

build:
name: Build (${{ matrix.goos }}/${{ matrix.goarch }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
goos: [linux, darwin]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Cross-compile
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0"
run: go build -o /dev/null ./cmd/scanner
16 changes: 16 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# golangci-lint configuration. Mirrors the linters required by CONVENTIONS.md.
run:
timeout: 5m

linters:
enable:
- errcheck # unchecked errors
- govet # suspicious constructs
- staticcheck # static analysis
- revive # style / lint rules
- gosec # security issues

issues:
# Don't cap the number of reported issues per linter/file.
max-issues-per-linter: 0
max-same-issues: 0
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Living document. Tick items off as they land; reorder when priorities change.

## Phase 4 — Project Hygiene

- [ ] **CI pipeline** (GitHub Actions): `go vet`, `go test -race -cover`, `golangci-lint`, `govulncheck`, build matrix for linux/darwin amd64+arm64.
- [x] **CI pipeline** (GitHub Actions): `go vet`, `go test -race -cover`, `golangci-lint`, `govulncheck`, build matrix for linux/darwin amd64+arm64.
- [ ] **Release automation** with `goreleaser` → signed binaries + multi-arch container image.
- [ ] **Integration tests** that scan a curated set of pinned images (`alpine:3.14`, `alpine:3.19`, a known-clean image, a known-vulnerable image) and assert findings.

Expand Down
2 changes: 1 addition & 1 deletion internal/extractor/extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func ExtractImage(imageName string, verbose bool) (string, func(), error) {

// Find the docker binary safely
dockerBinary := getDockerPath()

// 1.5. Pull the image from the registry to ensure it exists locally
if verbose {
fmt.Printf("Pulling image '%s' from registry...\n", imageName)
Expand Down
Loading