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
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
# This repo ships markdown + JSON manifests + shell install scripts and has no
# application package manager, so the only ecosystem to keep current is the
# pinned GitHub Actions in .github/workflows.
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
actions:
patterns: ["*"]
34 changes: 34 additions & 0 deletions .github/workflows/actions-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Actions Security

on:
push:
branches: [main]
paths: [".github/workflows/**"]
pull_request:
branches: [main]
paths: [".github/workflows/**"]

permissions:
contents: read

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

jobs:
zizmor:
name: zizmor (workflow audit)
runs-on: ubuntu-latest
steps:
- uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Run zizmor
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
pipx install zizmor
zizmor --min-severity=medium .github/workflows/
74 changes: 74 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

# Cancel superseded runs on the same ref so rapid pushes don't pile up runners.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# ── Config / manifest validation ─────────────────────────────────────────
# This repo has no build system: it's markdown + JSON manifests + shell
# install scripts. The gate lints the shell and parses every JSON file.
validate:
name: Validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

# shellcheck is preinstalled on ubuntu-latest runners. Scope to error
# severity: this gate catches real bugs (unset vars, bad quoting that
# changes behavior) without failing on stylistic SC2086-class notes.
- name: Shellcheck (severity=error)
run: |
set -euo pipefail
shellcheck --version
mapfile -d '' files < <(find . -name '*.sh' \
-not -path './.git/*' -not -path '*/node_modules/*' -print0)
if [ ${#files[@]} -eq 0 ]; then
echo "no shell scripts found"; exit 0
fi
printf 'checking: %s\n' "${files[@]}"
shellcheck --severity=error "${files[@]}"

# Validate that every committed JSON manifest parses. node is preinstalled
# on ubuntu-latest. node_modules/dist/.git are excluded.
- name: Validate JSON
run: |
set -euo pipefail
fail=0
while IFS= read -r -d '' f; do
if node -e "JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'))" "$f"; then
echo " [ok] $f"
else
echo " [FAIL] invalid JSON: $f"
fail=1
fi
done < <(find . -name '*.json' \
-not -path './.git/*' -not -path '*/node_modules/*' -not -path '*/dist/*' -print0)
exit $fail

# ── Aggregate gate ───────────────────────────────────────────────────────
# One stable required-status-check context. Fails if validate failed OR was
# skipped/cancelled, so the job graph can be reshaped without orphaning the
# required check.
ci-success:
name: CI Passed
if: always()
needs: [validate]
runs-on: ubuntu-latest
steps:
- name: Verify all required jobs succeeded
run: |
echo "validate=${{ needs.validate.result }}"
[ "${{ needs.validate.result }}" = "success" ]
38 changes: 38 additions & 0 deletions .github/workflows/secret-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Secret Scan

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

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

jobs:
gitleaks:
name: gitleaks
runs-on: ubuntu-latest
steps:
- uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0 # scan full history
persist-credentials: false
# The gitleaks GitHub Action requires a paid license for org accounts, but
# the gitleaks binary itself is free (MIT). Run it directly.
- name: Install gitleaks
env:
GITLEAKS_VERSION: "8.30.1"
run: |
curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
gitleaks version
- name: Scan repository
run: gitleaks dir . --redact --verbose --exit-code 1
4 changes: 4 additions & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# zizmor configuration. All findings are fixed in-place (least-privilege
# permissions + persist-credentials: false on every checkout), so there are
# currently no accepted exceptions to record here.
rules: {}