diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9e5000b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,18 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + - package-ecosystem: gomod + directory: / + schedule: + interval: weekly + - package-ecosystem: gomod + directory: /docs + schedule: + interval: weekly + - package-ecosystem: gomod + directory: /examples + schedule: + interval: weekly diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..14a1655 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,46 @@ +name: Security + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: "0 6 * * 1" + workflow_dispatch: + +permissions: + contents: read + +jobs: + scan: + runs-on: ubuntu-latest + steps: + - name: Checkout full history + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version: stable + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@v1.7.0 + - name: Scan analyzable Go modules + shell: bash + run: | + while IFS= read -r -d '' module; do + module_dir="${module%/go.mod}" + if ! packages="$(cd -- "$module_dir" && go list ./...)"; then + exit 1 + fi + if [[ -z "$packages" ]]; then + printf 'Skipping empty Go module: %s\n' "$module_dir" + continue + fi + (cd -- "$module_dir" && govulncheck -test -scan=package ./...) + done < <(find . \( -path './.git' -o -path './node_modules' \) -prune -o -name go.mod -type f -print0) + - name: Scan Git history for secrets + run: | + go install github.com/zricethezav/gitleaks/v8@v8.30.1 + gitleaks git . --redact --no-banner diff --git a/.github/workflows/supply-chain.yml b/.github/workflows/supply-chain.yml new file mode 100644 index 0000000..7982dcd --- /dev/null +++ b/.github/workflows/supply-chain.yml @@ -0,0 +1,59 @@ +name: Supply Chain + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: "0 6 * * 1" + workflow_dispatch: + +jobs: + dependency-review: + if: github.event_name == 'pull_request' + permissions: + contents: read + runs-on: ubuntu-latest + steps: + - name: Review dependency changes + uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 + + sbom: + permissions: + contents: read + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Set up Go + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version: stable + - name: Install CycloneDX generator + run: go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@v1.10.0 + - name: Generate module SBOMs + shell: bash + run: | + mkdir -p sbom + discovered=0 + generated=0 + while IFS= read -r -d '' module; do + module_dir="${module%/go.mod}" + discovered=$((discovered + 1)) + output="$GITHUB_WORKSPACE/sbom/module-$discovered.cdx.json" + (cd -- "$module_dir" && cyclonedx-gomod mod -json -type library -test -output "$output") + jq -e '.bomFormat == "CycloneDX" and .metadata.component.type == "library" and all(.components[]?; .name != "..")' "$output" >/dev/null + generated=$((generated + 1)) + done < <(find . \( -path './.git' -o -path './node_modules' \) -prune -o -name go.mod -type f -print0) + test "$discovered" -gt 0 + test "$discovered" -eq "$generated" + printf 'discovered=%s\ngenerated=%s\n' "$discovered" "$generated" > sbom/coverage.txt + - name: Upload SBOMs + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: cycloneDX-sboms + path: sbom + if-no-files-found: error + +# This repository publishes source modules and builds no release artifact, so artifact attestation is not applicable. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dc90775..8cbe5f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [ main ] +permissions: + contents: read + jobs: test: name: Go ${{ matrix.go-version }} @@ -17,10 +20,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: ${{ matrix.go-version }} @@ -67,7 +70,7 @@ jobs: - name: Upload results to Codecov if: matrix.go-version == 'stable' - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: files: coverage.txt env: diff --git a/examples/go.mod b/examples/go.mod index 50112ca..d1f7cb9 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -5,9 +5,9 @@ go 1.27.0 require github.com/goforj/execx v1.1.0 require ( - golang.org/x/sys v0.41.0 // indirect + golang.org/x/sys v0.44.0 // indirect golang.org/x/term v0.40.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/goforj/execx => .. +replace github.com/goforj/execx => ./.. diff --git a/examples/go.sum b/examples/go.sum index 0cc80d5..2602f54 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1,5 +1,5 @@ -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/go.mod b/go.mod index e6fe658..4ae88e9 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/goforj/execx go 1.27.0 require ( - golang.org/x/sys v0.41.0 + golang.org/x/sys v0.44.0 golang.org/x/term v0.40.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 0cc80d5..2602f54 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=