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
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Changes to workflow and action files require security team review.
.github/workflows/ @sparkgeo/security-team
.github/actions/ @sparkgeo/security-team
20 changes: 20 additions & 0 deletions .github/actions/dependency-review/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: "Dependency Review"
description: "Blocks PRs that introduce dependencies with known vulnerabilities or denied 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"
comment-summary-in-pr:
description: "Post a summary comment on the PR: always|on-failure|never"
default: "on-failure"
runs:
using: "composite"
steps:
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
fail-on-severity: ${{ inputs.fail-on-severity }}
deny-licenses: ${{ inputs.deny-licenses }}
comment-summary-in-pr: ${{ inputs.comment-summary-in-pr }}
10 changes: 10 additions & 0 deletions .github/actions/github-actionlint/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: "Actionlint"
description: "Lints GitHub Actions workflow and composite action YAML files using actionlint via reviewdog."
runs:
using: "composite"
steps:
- uses: reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d # v1.72.0
with:
github_token: ${{ github.token }}
reporter: github-check
fail_level: error
31 changes: 31 additions & 0 deletions .github/actions/scorecard/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: "OpenSSF Scorecard"
description: |
Runs OpenSSF Scorecard checks, uploads SARIF to the GitHub Security tab, and publishes results to the OpenSSF database.
Required permissions on calling job: id-token: write, security-events: write, actions: read, contents: read
inputs:
publish_results:
description: "Publish results to the public OpenSSF Scorecard database and generate the Scorecard badge. Set to false for private repositories."
default: "true"
runs:
using: "composite"
steps:
- uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: scorecard-results.sarif
results_format: sarif
repo_token: ${{ github.token }}
publish_results: ${{ inputs.publish_results }}

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: scorecard-results
path: scorecard-results.sarif
retention-days: 5
if-no-files-found: ignore

- uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
if: always() && hashFiles('scorecard-results.sarif') != ''
with:
sarif_file: scorecard-results.sarif
category: scorecard
40 changes: 15 additions & 25 deletions .github/actions/storage-optimizer/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,19 @@ runs:
- name: Cleanup
shell: bash
run: |
# Remove Java (JDKs)
sudo rm -rf /usr/lib/jvm
# Remove .NET SDKs
sudo rm -rf /usr/share/dotnet
# Remove Swift toolchain
sudo rm -rf /usr/share/swift
# Remove Haskell (GHC)
sudo rm -rf /usr/local/.ghcup
# Remove Julia
sudo rm -rf /usr/local/julia*
# Remove Android SDK
sudo rm -rf /usr/local/lib/android
# Remove Chromium
sudo rm -rf /usr/local/share/chromium
# Remove Microsoft and Google tools
sudo rm -rf /opt/microsoft /opt/google
# Remove Azure CLI
sudo rm -rf /opt/az
# Remove PowerShell
sudo rm -rf /usr/local/share/powershell
# Remove cached tools
sudo rm -rf /opt/hostedtoolcache
# Clean up Docker
docker system prune -af || true
docker builder prune -af || true
sudo rm -rf \
/usr/lib/jvm \
/usr/share/dotnet \
/usr/share/swift \
/usr/local/.ghcup \
/usr/local/julia* \
/usr/local/lib/android \
/usr/local/share/chromium \
/opt/microsoft /opt/google \
/opt/az \
/usr/local/share/powershell \
/opt/hostedtoolcache &
docker system prune -af || true &
docker builder prune -af || true &
wait
df -h
4 changes: 2 additions & 2 deletions .github/actions/terramate-opentofu-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ runs:
- name: Setup OpenTofu
uses: opentofu/setup-opentofu@847eaa4afeb791b06daa46e8eafa8b1b68d7cfb4 # v2.0.1
with:
tofu_version: ${{ env.OPENTOFU_VERSION }}
tofu_version: ${{ inputs.opentofu_version }}
tofu_wrapper: false

- name: Setup Terramate
uses: terramate-io/terramate-action@c5a1375801a3fac44d29fc7e0ebb3757ea0db3e0 # v3.0.0
with:
version: ${{ env.TERRAMATE_VERSION }}
version: ${{ inputs.terramate_version }}

- name: Check Terramate configurations are up to date
shell: bash
Expand Down
11 changes: 11 additions & 0 deletions .github/actions/zizmor/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: "Zizmor"
description: "Runs zizmor static security analysis against GitHub Actions workflow and action YAML files; uploads findings as SARIF to the GitHub Security tab."
runs:
using: "composite"
steps:
- uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
with:
version: "1.25.2"
advanced-security: "true"
env:
GITHUB_TOKEN: ${{ github.token }}
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
commit-message:
prefix: "ci"
114 changes: 114 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: CI
# Dogfoods this repo's own composite actions on every push and PR.
# Serves as a live reference implementation for consuming repos.

on:
push:
branches: [main]
paths:
- '.github/**'
pull_request:
schedule:
- cron: '0 6 * * 1' # weekly Monday 06:00 UTC — for scorecard
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# Lint workflow and action YAML files with actionlint.
actionlint:
name: Actionlint
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: ./.github/actions/github-actionlint

# Security-scan workflow and action YAML files with zizmor.
zizmor:
name: Zizmor
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: ./.github/actions/zizmor

# Run OpenSSF Scorecard on push to main and schedule only.
# Scorecard hard-requires the default branch; skipped on PRs and feature branches.
scorecard:
name: OpenSSF Scorecard
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
permissions:
contents: read
actions: read
security-events: write
id-token: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: ./.github/actions/scorecard

# Review dependency changes for vulnerabilities and license issues.
# Only meaningful on pull_request — requires PR base/head context.
dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: ./.github/actions/dependency-review

# Verify Terramate and OpenTofu are installed correctly.
# Terramate stack steps are no-ops in this repo (no stacks defined).
terramate-opentofu-setup:
name: Terramate + OpenTofu Setup
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 0 # terramate --changed requires full git history

- 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.
storage-optimizer:
name: Storage Optimizer
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: ./.github/actions/storage-optimizer
54 changes: 0 additions & 54 deletions .github/workflows/workflow-lint.yml

This file was deleted.

56 changes: 51 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing

This repo is the central library of reusable GitHub Actions workflows for the Sparkgeo organisation. All contributions must meet the security standards below before a PR can be merged.
This repo is the central library of reusable GitHub Actions composite actions for the Sparkgeo organisation. All contributions must meet the security standards below before a PR can be merged.

## Workflow authoring checklist

Expand Down Expand Up @@ -57,14 +57,60 @@ gh api repos/actions/checkout/commits/v6 --jq '.sha'

Once configured, Renovate (issue #8) will keep pinned SHAs current automatically via automated PRs — do not update SHAs manually unless fixing a security incident.

## Adding a new workflow
## Adding a new action

1. Create a GitHub issue (parent + context sub-issues where applicable)
2. Assign to the relevant team or individual, type: Feature, labels: `security`, `enhancement`, `documentation`, `priority: high`
3. Branch from `main`: `git checkout -b issue-<number>-<short-description>`
4. Implement the workflow — satisfy all checklist items above
5. Update the workflow index table in `README.md`
6. Open a PR referencing the issue: `Closes #<number>`
4. Create the composite action under `.github/actions/<name>/action.yml` — satisfy all checklist items above
5. Add a job for it in `.github/workflows/ci.yml` with minimum required permissions
6. Update the composite actions table in `README.md` with a usage example
7. Open a PR referencing the issue: `Closes #<number>`

## Migrating from the reusable workflow pattern

Prior to issue #29, this repo exposed an `Actions Quality Gate` reusable workflow
(`workflow-lint.yml`) callable via `workflow_call`. That file has been deleted.

If your repo references it:

```yaml
# OLD — no longer works
jobs:
lint:
uses: sparkgeo/github-actions/.github/workflows/workflow-lint.yml@<SHA>
```

Replace with direct composite action calls:

```yaml
# NEW
jobs:
actionlint:
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
steps:
- uses: actions/checkout@<SHA>
with:
persist-credentials: false
- uses: sparkgeo/github-actions/.github/actions/github-actionlint@<SHA>

zizmor:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@<SHA>
with:
persist-credentials: false
- uses: sparkgeo/github-actions/.github/actions/zizmor@<SHA>
```

The composite actions are individually callable and require explicit job shells with
correct permissions (see README for full usage examples).

## Security pillars reference

Expand Down
Loading