Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
f43914b
ci: document workflow conventions
ArangoGutierrez Apr 23, 2026
417b70d
fix(shell): remove dead pattern __* in case statements
ArangoGutierrez Apr 23, 2026
e52f3a3
ci: add shellcheck workflow for repo shell scripts
ArangoGutierrez Apr 23, 2026
bee820a
ci: add markdownlint config
ArangoGutierrez Apr 23, 2026
ceef971
ci: add .lycheeignore for localhost and template placeholders
ArangoGutierrez Apr 23, 2026
97939b9
ci: add prose-lint workflow (yamllint, markdownlint, lychee)
ArangoGutierrez Apr 23, 2026
88b0dca
ci: tune markdownlint (disable MD034, exclude data/music dirs)
ArangoGutierrez Apr 23, 2026
ed5a593
fix(docs): add blank lines around headings/lists, language tags to co…
ArangoGutierrez Apr 23, 2026
6602c6a
ci: add CodeQL workflow pre-wired for python and javascript-typescript
ArangoGutierrez Apr 23, 2026
45daaa9
ci: add .gitleaks.toml with upstream defaults + generic PII rules
ArangoGutierrez Apr 23, 2026
6325e8e
ci: add gitleaks workflow with optional private-overlay hook
ArangoGutierrez Apr 23, 2026
1dcc77a
docs: document GITLEAKS_PRIVATE_CONFIG format in maintainer setup
ArangoGutierrez Apr 23, 2026
de04666
ci: add OpenSSF Scorecard workflow
ArangoGutierrez Apr 23, 2026
41835a3
fix(ci): repin codeql-action and scorecard-action to commit SHAs
ArangoGutierrez Apr 23, 2026
ef1d3d3
fix(ci): tighten gitleaks test-file allowlist to known subtrees
ArangoGutierrez Apr 23, 2026
f8b85cc
ci: widen lint path filters to trigger on config and workflow edits
ArangoGutierrez Apr 23, 2026
447c158
ci: write gitleaks private overlay to $RUNNER_TEMP, not workspace
ArangoGutierrez Apr 23, 2026
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
53 changes: 53 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# GitHub Actions Workflows

This directory contains the repository's CI workflows. All workflows
follow these conventions.

## Pin every action to a full 40-char SHA

Every `uses:` line pins the action to a commit SHA, with the human
readable version in a trailing comment:

```yaml
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.7
```

This prevents a silent supply-chain swap if an upstream tag is moved.

To bump an action, resolve the new SHA from its tag:

```bash
gh api repos/OWNER/REPO/git/ref/tags/VERSION --jq '.object.sha'
```

Dependabot opens weekly PRs that do this automatically; manual bumps
use the same command.

## Minimize `permissions:`

Every workflow sets `permissions: {}` at the top level and re-grants
only what a job needs at the job or step scope.

## First step is harden-runner (audit mode)

Every job's first step is `step-security/harden-runner` in `audit` mode.
Logs surface at the Actions run page. After the egress baseline is
known, a follow-up PR flips audit → block.

## Where results surface

| Workflow | Results appear in |
|----------------|------------------------------------------------------------------------------|
| shellcheck | Checks tab (PR annotations) |
| lint-prose | Checks tab (yamllint / markdownlint / lychee annotations) |
| codeql | Security tab → Code scanning alerts |
| gitleaks | Checks tab; PR inline summary when `pull-requests: write` is available |
| scorecard | Security tab → Code scanning alerts, plus the public OpenSSF Scorecard report |

## Fork-PR caveat

PRs opened from a fork run with a read-only `GITHUB_TOKEN` and no
repository secrets. The workflows are designed to function under this
constraint: none use `pull_request_target`, and gitleaks degrades its
inline-comment behaviour to workflow annotations when it cannot post
PR comments.
58 changes: 58 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: codeql

on:
pull_request:
branches: [main]
push:
branches: [main]
schedule:
# Weekly Monday 06:00 UTC — independent of scorecard's Tuesday slot.
- cron: '0 6 * * 1'

permissions: {}

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

jobs:
analyze:
name: analyze (${{ matrix.language }})
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
# Pre-wired for the languages skill code is most likely to arrive
# in. Today both legs find zero source files and exit quickly;
# the first .py / .ts PR activates real analysis automatically.
language: [python, javascript-typescript]
# Python became a first-class language in upstream PR #5 (2026-04-21):
# maya/, skills/*/main.py, evals/, tests/. The javascript-typescript
# leg finds zero sources today and exits quickly; it's kept to
# auto-activate when the first TS skill or UI lands.
steps:
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Initialize CodeQL
uses: github/codeql-action/init@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
with:
languages: ${{ matrix.language }}
paths-ignore: |
docs/**
**/*.md
.worktrees/**
**/fixtures/**
evals/**/scenarios/**
skills/_skeleton/**
- name: Autobuild
uses: github/codeql-action/autobuild@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
- name: Analyze
uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
with:
category: "/language:${{ matrix.language }}"
63 changes: 63 additions & 0 deletions .github/workflows/gitleaks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: gitleaks

on:
pull_request:
push:
branches: [main]

permissions: {}

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

jobs:
gitleaks:
name: gitleaks
runs-on: ubuntu-latest
permissions:
contents: read
# pull-requests: write is granted only for same-repo PRs;
# fork PRs automatically degrade to read-only and gitleaks
# falls back to workflow annotations.
pull-requests: write
steps:
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit

- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0

# Private-overlay hook. If the GITLEAKS_PRIVATE_CONFIG secret is
# set, write it to a runner-local file and append its contents
# onto .gitleaks.toml; gitleaks merges [[rules]] tables across
# the single resulting config file. No-op when the secret is
# unset. The appended file never leaves the runner.
- name: Merge private gitleaks overlay (if provided)
env:
PRIVATE_CONFIG: ${{ secrets.GITLEAKS_PRIVATE_CONFIG }}
run: |
set -euo pipefail
if [ -n "${PRIVATE_CONFIG:-}" ]; then
# Write overlay to $RUNNER_TEMP (auto-wiped, never in workspace
# so it cannot leak via artifact upload). trap cleans up on any
# exit path. gitleaks deduplicates rules by id, so duplicated
# ids in the overlay just refine the public config.
TMP_OVERLAY="$(mktemp)"
trap 'rm -f "$TMP_OVERLAY"' EXIT
printf '%s\n' "$PRIVATE_CONFIG" > "$TMP_OVERLAY"
printf '\n# --- Private overlay (appended at CI time) ---\n' >> .gitleaks.toml
cat "$TMP_OVERLAY" >> .gitleaks.toml
echo "Merged private overlay ($(wc -l < "$TMP_OVERLAY") lines)."
else
echo "No private overlay configured."
fi

- uses: gitleaks/gitleaks-action@83373cf2f8c4db6e24b41c1a9b086bb9619e9cd3 # v2.3.7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Free for personal accounts; license only needed under orgs.
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
GITLEAKS_CONFIG: .gitleaks.toml
85 changes: 85 additions & 0 deletions .github/workflows/lint-prose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: lint-prose

on:
pull_request:
paths:
- '**/*.md'
- '**/*.yml'
- '**/*.yaml'
- '.lycheeignore'
- '.markdownlint.yaml'
- '.yamllint.yaml'
- '.github/workflows/lint-prose.yml'
push:
branches: [main]
paths:
- '**/*.md'
- '**/*.yml'
- '**/*.yaml'
- '.lycheeignore'
- '.markdownlint.yaml'
- '.yamllint.yaml'
- '.github/workflows/lint-prose.yml'

permissions: {}

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

jobs:
yamllint:
name: yamllint
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: karancode/yamllint-github-action@fdef6bc189425ecc84cc4543b2674566c0827053 # v2.1.1
with:
yamllint_file_or_dir: '.'
yamllint_config_filepath: '.yamllint.yaml'
yamllint_strict: true
yamllint_comment: false

markdownlint:
name: markdownlint
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: DavidAnson/markdownlint-cli2-action@b4c9feab76d8025d1e83c653fa3990936df0e6c8 # v16.0.0
with:
globs: |
**/*.md
!**/fixtures/**
!.worktrees/**
!docs/plans/**
!docs/music/**
!data/**

lychee:
name: lychee (link-check)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: lycheeverse/lychee-action@2b973e86fc7b1f6b36a93795fe2c9c6ae1118621 # v1.10.0
with:
args: >-
--no-progress
--exclude-path .worktrees
--exclude-path .git
'**/*.md'
fail: false
45 changes: 45 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: scorecard

on:
branch_protection_rule:
push:
branches: [main]
schedule:
# Weekly Tuesday 06:00 UTC — independent of CodeQL's Monday slot.
- cron: '0 6 * * 2'

permissions: {}

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

jobs:
analysis:
name: scorecard analysis
runs-on: ubuntu-latest
permissions:
security-events: write
id-token: write
contents: read
actions: read
steps:
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit

- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false

- name: Run scorecard analysis
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with:
results_file: results.sarif
results_format: sarif
publish_results: true

- name: Upload SARIF to code scanning
uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
with:
sarif_file: results.sarif
45 changes: 45 additions & 0 deletions .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: shellcheck

on:
pull_request:
paths:
- '**/*.sh'
- '**/*.bash'
- 'skills/**'
- 'setup.sh'
- 'bin/**'
- '.github/workflows/shellcheck.yml'
push:
branches: [main]
paths:
- '**/*.sh'
- '**/*.bash'
- 'skills/**'
- 'setup.sh'
- 'bin/**'
- '.github/workflows/shellcheck.yml'

permissions: {}

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

jobs:
shellcheck:
name: shellcheck
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
with:
severity: warning
scandir: '.'
ignore_paths: >-
.git
.worktrees
Loading