diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff12bd80..1306d3f0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,40 +149,6 @@ jobs: - name: Run smoke benchmarks run: go test -bench . -benchtime 1x -timeout 5m -run '^$' ./... - deadcode: - name: Dead Code - runs-on: ubuntu-latest - concurrency: - group: ci-deadcode-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - persist-credentials: false - - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6 - with: - go-version: "1.25" - - - name: Check for dead code - run: go run golang.org/x/tools/cmd/deadcode@v0.42.0 -test ./... - - pre-commit: - name: Pre-commit - runs-on: ubuntu-latest - concurrency: - group: ci-pre-commit-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - persist-credentials: false - - - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31 - - - name: Run pre-commit hooks - run: nix run '.#pre-commit' - nix-build: name: Nix Build runs-on: ubuntu-latest @@ -224,29 +190,13 @@ jobs: - name: Build docs run: nix run '.#docs' - secrets: - name: Secret Scan - runs-on: ubuntu-latest - concurrency: - group: ci-secrets-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - fetch-depth: 0 - persist-credentials: false - - - uses: trufflesecurity/trufflehog@7635b24fd512a2e817dd3e9dd661caaf035a079d # v3.93.1 - with: - extra_args: --only-verified - # --------------------------------------------------------------------------- # Semantic Release (dry-run on PRs, publish on main push) # --------------------------------------------------------------------------- semantic-release: name: Semantic Release - needs: [test, deadcode, pre-commit, nix-build, docs, secrets] + needs: [test, nix-build, docs] runs-on: ubuntu-latest concurrency: group: semantic-release-${{ github.ref }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 29a76e65..00000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2026 Phillip Cloud -# Licensed under the Apache License, Version 2.0 - -name: CodeQL - -on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - # Run weekly on Monday at 06:00 UTC - - cron: "0 6 * * 1" - -permissions: - contents: read - -env: - CGO_ENABLED: "0" - -jobs: - analyze: - name: Analyze (Go) - runs-on: ubuntu-latest - concurrency: - group: codeql-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - permissions: - security-events: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - persist-credentials: false - - - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6 - with: - go-version: "1.25" - - - name: Initialize CodeQL - uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 - with: - languages: go - build-mode: manual - - - name: Build - run: go build ./... - - - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..a4273f27 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,63 @@ +# Copyright 2026 Phillip Cloud +# Licensed under the Apache License, Version 2.0 + +name: Lint + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + deadcode: + name: Dead Code + runs-on: ubuntu-latest + concurrency: + group: lint-deadcode-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31 + + - name: Run deadcode + run: nix run '.#deadcode' + + golangci-lint: + name: Lint + runs-on: ubuntu-latest + concurrency: + group: lint-golangci-lint-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31 + + - name: Run golangci-lint + run: nix run '.#golangci-lint' + + pre-commit: + name: Pre-commit + runs-on: ubuntu-latest + concurrency: + group: lint-pre-commit-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 + persist-credentials: false + + - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31 + + - name: Run pre-commit hooks + run: nix run '.#pre-commit' -- --from-ref 'origin/${{ github.base_ref || 'main' }}' --to-ref HEAD diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 00000000..103a1ba9 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,93 @@ +# Copyright 2026 Phillip Cloud +# Licensed under the Apache License, Version 2.0 + +name: Security + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + govulncheck: + name: Vulnerability Check + runs-on: ubuntu-latest + concurrency: + group: security-govulncheck-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31 + + - name: Run govulncheck + run: nix run '.#govulncheck' + + osv-scanner: + name: OSV Scan + runs-on: ubuntu-latest + concurrency: + group: security-osv-scanner-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31 + + - name: Run osv-scanner + run: nix run '.#osv-scanner' + + secrets: + name: Secret Scan + runs-on: ubuntu-latest + concurrency: + group: security-secrets-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + fetch-depth: 0 + persist-credentials: false + + - uses: trufflesecurity/trufflehog@7635b24fd512a2e817dd3e9dd661caaf035a079d # v3.93.1 + with: + extra_args: --only-verified + + codeql: + name: CodeQL (Go) + runs-on: ubuntu-latest + concurrency: + group: security-codeql-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + permissions: + security-events: write + env: + CGO_ENABLED: "0" + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6 + with: + go-version: "1.25" + + - name: Initialize CodeQL + uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + with: + languages: go + build-mode: manual + + - name: Build + run: go build ./... + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 diff --git a/flake.nix b/flake.nix index c10e6870..cddd6c9e 100644 --- a/flake.nix +++ b/flake.nix @@ -125,7 +125,7 @@ }; nixfmt.enable = true; golangci-lint = { - enable = true; + enable = false; # CI-only job stages = [ "pre-push" ]; }; actionlint.enable = true; @@ -160,7 +160,7 @@ pass_filenames = false; }; deadcode-check = { - enable = true; + enable = false; # CI-only job name = "deadcode"; entry = "${run-deadcode}/bin/run-deadcode"; files = "\\.go$"; @@ -169,7 +169,7 @@ stages = [ "pre-push" ]; }; govulncheck = { - enable = true; + enable = false; # CI-only job name = "govulncheck"; entry = "${run-govulncheck}/bin/run-govulncheck"; files = "^go\\.(mod|sum)$"; @@ -178,7 +178,7 @@ stages = [ "pre-push" ]; }; osv-scanner = { - enable = true; + enable = false; # CI-only job name = "osv-scanner"; entry = "${run-osv-scanner}/bin/run-osv-scanner"; files = "^go\\.(mod|sum)$"; @@ -292,6 +292,22 @@ ''; }; + run-golangci-lint = pkgs.writeShellApplication { + name = "run-golangci-lint"; + runtimeInputs = [ + pkgs.golangci-lint + pkgs.go + ]; + runtimeEnv.CGO_ENABLED = "0"; + text = '' + _tmpdir=$(mktemp -d -t micasa-golangci-lint-XXXXXX) + trap 'chmod -R u+w "$_tmpdir" 2>/dev/null; rm -rf "$_tmpdir"' EXIT + export GOCACHE="''${GOCACHE:-$_tmpdir/gocache}" + export GOMODCACHE="''${GOMODCACHE:-$_tmpdir/gomodcache}" + golangci-lint run ./... + ''; + }; + goModTidyCheck = pkgs.writeShellApplication { name = "go-mod-tidy-check"; runtimeInputs = [ @@ -596,7 +612,12 @@ gen-mixed-pdf ''; }; - inherit run-deadcode run-govulncheck run-osv-scanner; + inherit + run-deadcode + run-govulncheck + run-osv-scanner + run-golangci-lint + ; run-pre-commit = pkgs.writeShellApplication { name = "run-pre-commit"; runtimeInputs = [ @@ -617,8 +638,11 @@ ]; text = '' ${preCommit.shellHook} - pre-commit run --all-files - pre-commit run --all-files --hook-stage pre-push + if [ $# -eq 0 ]; then + set -- --all-files + fi + pre-commit run "$@" + pre-commit run "$@" --hook-stage pre-push ''; }; @@ -646,6 +670,7 @@ deadcode = app (pkg "run-deadcode") "Run whole-program dead code analysis"; govulncheck = app (pkg "run-govulncheck") "Check for known Go vulnerabilities with call-graph analysis"; osv-scanner = app (pkg "run-osv-scanner") "Scan for known vulnerabilities"; + golangci-lint = app (pkg "run-golangci-lint") "Run golangci-lint"; pre-commit = app (pkg "run-pre-commit") "Run all pre-commit hooks"; };