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
10 changes: 3 additions & 7 deletions .github/workflows/ai-claude-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
name: AI - Code Review

on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]
workflow_call:
inputs:
cancel-in-progress:
Expand All @@ -27,16 +25,14 @@ on:
secrets:
CLAUDE_CODE_OAUTH_TOKEN:
required: true
# Note: for pull_request trigger, secrets.CLAUDE_CODE_OAUTH_TOKEN resolves
# directly from the repo's secrets context — no caller needed.

permissions:
contents: read

concurrency:
# Dual-trigger workflow: `inputs.*` is undefined on `pull_request:` and
# only populated under `workflow_call:`. Expressions below fall back to
# the original hardcoded behaviour when inputs are missing.
# `github.event.pull_request.number` is the caller's event context, so it is
# set whenever the calling workflow runs on `pull_request`; `github.run_id`
# keeps the group unique for any other calling event.
group: >-
claude-review-${{ github.event.pull_request.number || github.run_id }}${{
inputs.concurrency-suffix && format('-{0}', inputs.concurrency-suffix) || ''
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/self-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: Merge to Main

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: write # Tag-Push

# The tag move is read-modify-write on a single ref, so two runs must never
# overlap. Queue them instead of cancelling: a cancelled run would skip the
# tag move for a commit that is already on main.
concurrency:
group: date-tag
cancel-in-progress: false

jobs:
date-tag:
name: Move Date Tag
# A dispatch from another branch would otherwise force the day's tag onto
# that branch, and consumer repos pin these tags.
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: true

- name: Move date tag to this commit
run: |
set -euo pipefail
TAG=$(date -u +%Y-%m-%d)
# The tag tracks the day's latest merge, not its first. Skipping when
# the tag already existed left every merge after the first one
# unreachable by any tag until the next day's first merge.
git fetch origin --tags --quiet
# Only ever move the tag forward. Runs are serialised, but a queued
# run still checks out its own commit, so without this an older one
# finishing last would drag the tag backwards.
if OLD=$(git rev-parse -q --verify "refs/tags/$TAG^{commit}"); then
if [ "$OLD" = "$(git rev-parse HEAD)" ]; then
echo "Tag $TAG already points at HEAD, nothing to do."
exit 0
fi
if ! git merge-base --is-ancestor "$OLD" HEAD; then
echo "Tag $TAG points at $OLD, which is not an ancestor of HEAD — leaving it alone."
exit 0
fi
fi
git tag -f "$TAG"
git push -f origin "refs/tags/$TAG"
echo "Tag $TAG now points at $(git rev-parse --short HEAD)."
58 changes: 58 additions & 0 deletions .github/workflows/self-pull-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
name: Pull Request

on:
pull_request:
branches: [main]
types: [opened, synchronize, reopened, ready_for_review]

permissions:
contents: read

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

jobs:
# This repository ships workflows and configuration rather than application
# code, so the gate is lint plus code scanning. Each job calls this repo's own
# reusable via a local `./` path: the workflows consumers depend on are the
# same ones exercised here, and a break shows up before it reaches them.
lint:
name: Lint
permissions:
contents: read
pull-requests: write
uses: ./.github/workflows/ci-lint.yml
with:
enable_actionlint: true
# The embedded `run:` scripts in these workflows are only checked when
# shellcheck runs alongside actionlint.
enable_shellcheck: true
# Off for now: `ai-claude-review.yml` carries a 515-char `--allowedTools`
# line that trips the 500-char limit in templates/.yamllint.yml. The list
# is comma-separated and cannot be folded — YAML block folding inserts a
# space after each newline, which would corrupt the tool names. Enable
# once that line is restructured or the template's limit is revisited.
enable_yamllint: false

review:
name: Code Review
permissions:
contents: read
pull-requests: write
issues: read
id-token: write
uses: ./.github/workflows/ai-claude-review.yml
secrets:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

code-scan:
name: Code Analysis
permissions:
contents: read
security-events: write
actions: read
uses: ./.github/workflows/security-code.yml
with:
languages: '["actions"]'
30 changes: 30 additions & 0 deletions .github/workflows/self-weekly-security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: Weekly Security

on:
schedule:
- cron: '0 2 * * 1'
workflow_dispatch:

permissions:
contents: read

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

jobs:
config:
name: Config Security
permissions:
contents: read
security-events: write
actions: read
uses: ./.github/workflows/security-config.yml

secrets:
name: Secret Scanning
permissions:
contents: read
actions: read
uses: ./.github/workflows/security-secrets.yml
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,29 @@ This is a rolling release - changes are deployed continuously to `main`.

## 2026-08-07

### Added

- **self-pull-request.yml**, **self-merge.yml**, **self-weekly-security.yml**:
This repository now runs its own CI, mirroring `sbaerlocher/.github`. Until
now every workflow here was `workflow_call`-only and nothing verified the
repository itself. Each new workflow calls this repo's own reusables through
a local `./` path, so the workflows consumers depend on are exercised before
they ship.
- **self-merge.yml**: Moves the `YYYY-MM-DD` date tag to the newest commit on
`main`, forward-only and serialised via `concurrency: date-tag`. Tagging was
manual before; the newest tag was `2026-06-18`, which is exactly what the
consumer repositories pin — so fixes merged after that date never reached
them without a hand-cut tag.

### Changed

- **ai-claude-review.yml**: Dropped the `pull_request:` trigger; the workflow is
now `workflow_call`-only like every other reusable here, and
`self-pull-request.yml` invokes it. Note that this does not change the
`claude-code-action` workflow-validation guard: it checks every workflow file
taking part in a run against the default branch, so a PR modifying this file
still has its review skipped regardless of where the trigger lives.

### Fixed

- **workflows/security-code.yml**: Caller inputs (`paths-ignore`,
Expand Down
Loading