diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 8377aae..c0e8511 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -1,3 +1,7 @@
+# NOTE: The goreleaser job uses `environment: release` to require manual
+# approval before publishing. This only pauses the run if a maintainer has
+# configured an Environment named "release" with Required reviewers under
+# Settings > Environments. Until then, the approval gate is a no-op.
name: Release Workflow
on:
@@ -7,8 +11,14 @@ on:
- '*'
jobs:
+ vulnerability-scan:
+ name: Vulnerability Scan
+ uses: ./.github/workflows/vulnerability-scan.yaml
+
goreleaser:
name: GoReleaser Job
+ needs: vulnerability-scan
+ environment: release
runs-on: ubuntu-latest
timeout-minutes: 60
diff --git a/.github/workflows/vulnerabilities.yaml b/.github/workflows/vulnerabilities.yaml
new file mode 100644
index 0000000..559a7e2
--- /dev/null
+++ b/.github/workflows/vulnerabilities.yaml
@@ -0,0 +1,13 @@
+name: Vulnerability Scan Workflow
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - release/*
+
+jobs:
+ vulnerability-scan:
+ name: Vulnerability Scan
+ uses: ./.github/workflows/vulnerability-scan.yaml
diff --git a/.github/workflows/vulnerability-scan.yaml b/.github/workflows/vulnerability-scan.yaml
new file mode 100644
index 0000000..b99a1a5
--- /dev/null
+++ b/.github/workflows/vulnerability-scan.yaml
@@ -0,0 +1,92 @@
+name: Vulnerability Scan (Reusable)
+
+on:
+ workflow_call:
+
+jobs:
+ vulnerability-scan:
+ name: Vulnerability Scan
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+
+ steps:
+ - name: Clean Up Actions Tools Cache
+ run: rm -rf /opt/hostedtoolcache
+
+ - name: Checkout
+ uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+
+ - name: Configure Git
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+
+ - name: Set Up Go
+ uses: actions/setup-go@v6
+ with:
+ go-version-file: go.mod
+ check-latest: true
+
+ - name: Install Go Releaser
+ uses: goreleaser/goreleaser-action@v6
+ with:
+ install-only: true
+
+ - name: Install Dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y make
+ sudo apt-get install -y build-essential
+
+ - name: Install govulncheck
+ run: go install golang.org/x/vuln/cmd/govulncheck@latest
+
+ - name: Install Trivy
+ uses: aquasecurity/setup-trivy@v0.3.1
+
+ - name: Run Vulnerability Scans
+ run: make vulns
+
+ - name: Display Vulnerability Reports
+ if: always()
+ run: |
+ echo "::group::govulncheck (vulncheck.out)"
+ cat vulncheck.out || echo "vulncheck.out not found"
+ echo "::endgroup::"
+ echo "::group::trivy fs (trivy.out)"
+ cat trivy.out || echo "trivy.out not found"
+ echo "::endgroup::"
+
+ - name: Write Vulnerability Reports to Job Summary
+ if: always()
+ run: |
+ {
+ echo "## Vulnerability Reports"
+ echo ""
+ echo "govulncheck (vulncheck.out)
"
+ echo ""
+ echo '```'
+ cat vulncheck.out 2>/dev/null || echo "vulncheck.out not found"
+ echo '```'
+ echo ""
+ echo " "
+ echo ""
+ echo "trivy fs (trivy.out)
"
+ echo ""
+ echo '```'
+ cat trivy.out 2>/dev/null || echo "trivy.out not found"
+ echo '```'
+ echo ""
+ echo " "
+ } >> "$GITHUB_STEP_SUMMARY"
+
+ - name: Upload Vulnerability Reports
+ uses: actions/upload-artifact@v6
+ if: always()
+ with:
+ name: vulnerability-reports
+ path: |
+ vulncheck.out
+ trivy.out
diff --git a/.gitignore b/.gitignore
index 8060616..a8e7c0c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,5 +17,6 @@ cmd/hauler/binaries
testdata/certs/
coverage.out
vulncheck.out
+trivy.out
CLAUDE.md
**/CLAUDE.*
diff --git a/Makefile b/Makefile
index 677b0e6..1bf7242 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,7 @@ SHELL=/bin/bash
GO_FILES=./...
GO_COVERPROFILE=coverage.out
GO_VULNCHECKS=vulncheck.out
+TRIVY_RESULTS=trivy.out
# set build variables
BIN_DIRECTORY=bin
@@ -48,7 +49,8 @@ test:
# check for vulnerabilities
vulns:
govulncheck $(GO_FILES) > $(GO_VULNCHECKS) 2>&1 || true
+ trivy fs . > $(TRIVY_RESULTS) 2>&1 || true
# cleanup artifacts
clean:
- rm -rf $(BIN_DIRECTORY) $(DIST_DIRECTORY) $(GO_COVERPROFILE) $(GO_VULNCHECKS)
+ rm -rf $(BIN_DIRECTORY) $(DIST_DIRECTORY) $(GO_COVERPROFILE) $(GO_VULNCHECKS) $(TRIVY_RESULTS)