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
34 changes: 29 additions & 5 deletions .github/actions/dependency-review/action.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
name: "Dependency Review"
description: "Blocks PRs that introduce dependencies with known vulnerabilities or denied licenses; posts a summary comment on the PR."
description: "Blocks PRs that introduce dependencies with known vulnerabilities or non-permitted licenses; posts a summary comment on the PR."
inputs:
fail-on-severity:
description: "Minimum vulnerability severity to fail: critical|high|moderate|low"
default: "high"
deny-licenses:
description: "Comma-separated list of SPDX license identifiers to deny"
default: "GPL-2.0,GPL-3.0,AGPL-3.0"
allow-licenses:
description: "Comma-separated list of SPDX license identifiers that are permitted. Dependencies using any other license will fail the check."
default: "MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Unlicense, CC0-1.0"
Comment on lines +7 to +9
comment-summary-in-pr:
description: "Post a summary comment on the PR: always|on-failure|never"
default: "on-failure"
base-ref:
description: "Base commit SHA for non-PR events (e.g. github.event.before on push). Leave empty on pull_request — the action reads PR context automatically."
default: ""
head-ref:
description: "Head commit SHA for non-PR events (e.g. github.sha on push). Leave empty on pull_request."
default: ""
runs:
using: "composite"
steps:
- name: Validate ref inputs
if: ${{ (inputs.base-ref != '' && inputs.head-ref == '') || (inputs.base-ref == '' && inputs.head-ref != '') }}
shell: bash
env:
BASE_REF: ${{ inputs.base-ref }}
HEAD_REF: ${{ inputs.head-ref }}
run: |
echo "::error::dependency-review: base-ref and head-ref must both be set or both be empty. Got base-ref='${BASE_REF}' head-ref='${HEAD_REF}'."
exit 1
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
if: ${{ inputs.base-ref == '' }}
with:
fail-on-severity: ${{ inputs.fail-on-severity }}
deny-licenses: ${{ inputs.deny-licenses }}
allow-licenses: ${{ inputs.allow-licenses }}
comment-summary-in-pr: ${{ inputs.comment-summary-in-pr }}
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
if: ${{ inputs.base-ref != '' }}
with:
base-ref: ${{ inputs.base-ref }}
head-ref: ${{ inputs.head-ref }}
fail-on-severity: ${{ inputs.fail-on-severity }}
allow-licenses: ${{ inputs.allow-licenses }}
comment-summary-in-pr: ${{ inputs.comment-summary-in-pr }}
Comment on lines 31 to 44
20 changes: 20 additions & 0 deletions .github/actions/scorecard/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ runs:
retention-days: 5
if-no-files-found: ignore

- name: Print scorecard summary
if: always() && hashFiles('scorecard-results.sarif') != ''
shell: bash
run: |
set -euo pipefail
if ! command -v jq &>/dev/null; then
echo "::warning::jq not found — skipping scorecard summary"
exit 0
fi
echo "=== OpenSSF Scorecard Results ==="
findings=$(jq -r '
.runs[].results[]? |
" [\(.ruleId | gsub("ID$";""))] \(.message.text | split("\n")[0])"
' scorecard-results.sarif)
if [[ -z "$findings" ]]; then
echo " All checks passed (no findings in SARIF)"
else
echo "$findings"
fi
Comment on lines +40 to +55

- uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
if: always() && hashFiles('scorecard-results.sarif') != ''
with:
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,14 @@ jobs:
- uses: ./.github/actions/scorecard

# Review dependency changes for vulnerabilities and license issues.
# Only meaningful on pull_request — requires PR base/head context.
# On pull_request: compares PR base/head via built-in event context.
# On push to main: compares the pushed range (event.before → sha) so maintainers
# can see the action work end-to-end without opening a PR.
# Skipped on first push to a branch (event.before = zero SHA) — no base to compare.
dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.before != '0000000000000000000000000000000000000000')
permissions:
contents: read
pull-requests: write
Expand All @@ -78,6 +81,9 @@ jobs:
persist-credentials: false

- uses: ./.github/actions/dependency-review
with:
base-ref: ${{ github.event_name == 'push' && github.event.before || '' }}
head-ref: ${{ github.event_name == 'push' && github.sha || '' }}

# Verify Terramate and OpenTofu are installed correctly.
# Terramate stack steps are no-ops in this repo (no stacks defined).
Expand All @@ -95,12 +101,11 @@ jobs:
- uses: ./.github/actions/terramate-opentofu-setup

# Verify the storage optimizer composite action runs without error.
# Gated to workflow_dispatch: storage-optimizer is only useful when a job does
# heavy disk work on the same runner; running it on a throwaway CI runner wastes minutes.
# Runs on push to main (demonstration) and workflow_dispatch (on-demand).
storage-optimizer:
name: Storage Optimizer
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
permissions:
contents: read
steps:
Expand Down
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# sparkgeo/github-actions

[![CI](https://github.com/sparkgeo/github-actions/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/sparkgeo/github-actions/actions/workflows/ci.yml)

Reusable GitHub Actions composite actions and CI workflow for the Sparkgeo organisation.

All action references in this repo are pinned to full commit SHAs. See [CONTRIBUTING.md](CONTRIBUTING.md) for authoring standards and how to add new actions.
Expand All @@ -24,7 +26,7 @@ gh api repos/sparkgeo/github-actions/commits/main --jq '.sha'
| GitHub Actionlint | [`github-actionlint`](.github/actions/github-actionlint/action.yml) | Lints workflow and action YAML files using actionlint via reviewdog; posts annotations as GitHub Checks | None |
| Zizmor | [`zizmor`](.github/actions/zizmor/action.yml) | Runs zizmor static security analysis against workflow and action YAML files; uploads findings as SARIF to the Security tab | None |
| OpenSSF Scorecard | [`scorecard`](.github/actions/scorecard/action.yml) | Runs OpenSSF Scorecard checks; uploads SARIF to the Security tab | `publish_results` (default: `false` — always fails with HTTP 400 if set to `true`; see action description) |
| Dependency Review | [`dependency-review`](.github/actions/dependency-review/action.yml) | Blocks PRs introducing dependencies with known vulnerabilities or denied licenses; posts a summary comment | `fail-on-severity` (default: `high`), `deny-licenses` (default: `GPL-2.0,GPL-3.0,AGPL-3.0`), `comment-summary-in-pr` (default: `on-failure`) |
| Dependency Review | [`dependency-review`](.github/actions/dependency-review/action.yml) | Blocks PRs introducing dependencies with known vulnerabilities or non-permitted licenses; posts a summary comment. Also supports non-PR invocation via `base-ref`/`head-ref`. | `fail-on-severity` (default: `high`), `allow-licenses` (default: `MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Unlicense, CC0-1.0`), `comment-summary-in-pr` (default: `on-failure`), `base-ref` (default: `""`), `head-ref` (default: `""`) |
| Storage Optimizer | [`storage-optimizer`](.github/actions/storage-optimizer/action.yml) | Frees disk space on GitHub-hosted runners by removing unused toolchains (JDK, .NET, Swift, Android SDK, etc.) and pruning Docker | None |
Comment on lines 28 to 30
| Terramate + OpenTofu Setup | [`terramate-opentofu-setup`](.github/actions/terramate-opentofu-setup/action.yml) | Installs Terramate and OpenTofu, validates generated files are up to date, initialises changed stacks, and lists changed stacks | `opentofu_version` (default: `1.10.0`), `terramate_version` (default: `0.14.7`) |

Expand Down Expand Up @@ -84,13 +86,13 @@ jobs:

### Dependency Review

Only meaningful on `pull_request` events — requires PR base/head context.
Works on `pull_request` events (automatic base/head from PR context) and on push/non-PR events by passing `base-ref`/`head-ref` explicitly. Skip on initial branch push (`event.before` = zero SHA — no base to compare).

```yaml
jobs:
dependency-review:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.before != '0000000000000000000000000000000000000000')
permissions:
contents: read
pull-requests: write
Expand All @@ -100,9 +102,11 @@ jobs:
persist-credentials: false
- uses: sparkgeo/github-actions/.github/actions/dependency-review@<SHA>
with:
fail-on-severity: high # critical | high | moderate | low
deny-licenses: GPL-2.0,AGPL-3.0 # SPDX identifiers
comment-summary-in-pr: always # always | on-failure | never
fail-on-severity: high # critical | high | moderate | low
allow-licenses: MIT, Apache-2.0, BSD-2-Clause # SPDX identifiers; deps with other licenses fail
comment-summary-in-pr: always # always | on-failure | never
base-ref: ${{ github.event_name == 'push' && github.event.before || '' }} # leave empty on pull_request
head-ref: ${{ github.event_name == 'push' && github.sha || '' }} # leave empty on pull_request
```

### Storage Optimizer
Expand Down