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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: lint
name: feature

on:
push:
Expand All @@ -12,7 +12,7 @@ permissions:
jobs:
hadolint:
name: hadolint
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@v7
Expand All @@ -24,7 +24,7 @@ jobs:

trivy-scan:
name: trivy-scan
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@v7
Expand All @@ -39,7 +39,7 @@ jobs:

actionlint:
name: actionlint
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@v7
Expand All @@ -48,3 +48,21 @@ jobs:
uses: raven-actions/actionlint@v2
with:
fail-on-error: true

gitguardian-scan:
name: gitguardian-scan
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- name: checkout
uses: actions/checkout@v7
with:
fetch-depth: 0 # fetch all history so multiple commits can be scanned
- name: scan
uses: GitGuardian/ggshield-action@v1
env:
GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }}
GITHUB_PUSH_BASE_SHA: ${{ github.event.base }}
GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}
27 changes: 0 additions & 27 deletions .github/workflows/gitguardian.yml

This file was deleted.

36 changes: 34 additions & 2 deletions .github/workflows/docker.pr.yml → .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: pr-build-and-scan-docker-image
name: pr

on:
pull_request:
Expand All @@ -20,9 +20,40 @@ permissions:
contents: read

jobs:
claude-review:
name: claude-review
if: github.event.action == 'opened'
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: write # post the review as a PR comment
id-token: write
steps:
- name: checkout
uses: actions/checkout@v7
with:
fetch-depth: 1

- name: run-claude-review
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.OPENROUTER_API_KEY }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request for correctness bugs, security issues, and
simplification opportunities.
Use `gh pr comment` for top-level feedback.
Use `mcp__github_inline_comment__create_inline_comment` for line comments.
claude_args: |
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
env:
ANTHROPIC_BASE_URL: https://openrouter.ai/api
ANTHROPIC_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}

scan:
name: build-and-scan
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
contents: read
security-events: write # upload Trivy SARIF to Code Scanning
Expand Down Expand Up @@ -164,3 +195,4 @@ jobs:
echo "| SARIF | Security › Code scanning alerts |"
echo "| Push | skipped (PR gate) |"
} >> "$GITHUB_STEP_SUMMARY"

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: release-docker-image
name: release

on:
push:
Expand Down Expand Up @@ -28,7 +28,7 @@ jobs:
# off-main tags (the tag ref itself still exists in Git; nothing is released).
tag-ref-gate:
name: tag-ref-gate
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
Expand All @@ -51,7 +51,7 @@ jobs:
push:
name: build-and-push
needs: tag-ref-gate
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
contents: read
id-token: write # OIDC for cosign keyless signing
Expand Down
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,11 @@ ARG XDG_DATA_HOME=${HOME}/.local/share

WORKDIR ${DOTFILES_DIR}

COPY ./stow-packages /tmp/stow-packages

RUN git clone -q --depth=1 -b "main" --single-branch "${DOTFILES_REPO_URL}" "${DOTFILES_DIR}" \
&& eval "$(mise hook-env)" \
&& cat ./stow/linux-essential | xargs -I {} stow {} \
&& cat /tmp/stow-packages | xargs -I {} stow {} \
&& nvim --headless "+Lazy! restore" +qa \
&& pi install git:github.com/leonidgrishenkov/pi-extensions \
&& npx -y github:leonidgrishenkov/agent-skills install --target pi --target claude \
Expand Down
28 changes: 20 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ workflows are self-contained in this repository under `.github/workflows/`.

### Workflow Triggers

| Trigger | Workflow | What runs | Purpose |
| -------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| Push to any branch except `main` | `docker.lint.yml` | `hadolint` Dockerfile lint | Fast feedback during development |
| PR into `main` | `docker.pr.yml` | Build amd64 image, Trivy scan (HIGH/CRITICAL), SARIF upload, smoke test | Gate — must pass before merge |
| Push tag `*.*` | `docker.release.yml` | Verify tag is on `main`, build multi-arch (`linux/amd64`, `linux/arm64`), push to YC CR, SBOM + SLSA provenance, cosign sign | Release |
| Trigger | Workflow | What runs | Purpose |
| -------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| Push to any branch except `main` | `feature.yml` | `hadolint` Dockerfile lint, Trivy config scan, `actionlint`, GitGuardian secret scan | Fast feedback during development |
| PR into `main` | `pr.yml` | Build amd64 image, Trivy scan (HIGH/CRITICAL), SARIF upload, smoke test, Claude code review (on open) | Gate — must pass before merge |
| Push tag `*.*` | `release.yml` | Verify tag is on `main`, build multi-arch (`linux/amd64`, `linux/arm64`), push to YC CR, SBOM + SLSA provenance, cosign sign | Release |

### Design Goals

Expand All @@ -29,28 +29,40 @@ workflows are self-contained in this repository under `.github/workflows/`.

### Security Checks

- **GitGuardian Scan** (`gitguardian.yml`) — runs on every push to `main` and every PR into `main` to detect leaked
- **GitGuardian Scan** (part of `feature.yml`) — runs on every push to any branch except `main` to detect leaked
secrets.
- **Trivy Image Scan** — runs during PR gate with severity `HIGH,CRITICAL` and `ignore-unfixed: true`. Findings are
uploaded to GitHub Code Scanning alerts.
- **Tag Origin Verification** — the release workflow verifies that the pushed tag points to a commit that is an ancestor
of `main`, preventing releases from arbitrary branches.
- **Image Signing** — every release image is signed with **cosign** using keyless OIDC via GitHub Actions.

### Claude Code Review

- **`claude-review`** (part of `pr.yml`) — runs once, when a PR into `main` is **opened**, and posts an automated
code review (top-level + inline comments via `gh pr comment` / inline PR comments) using
[`anthropics/claude-code-action`](https://github.com/anthropics/claude-code-action).
- Authenticates through **OpenRouter** rather than a direct Anthropic API key: the action's `ANTHROPIC_BASE_URL` is
redirected to `https://openrouter.ai/api`, using `OPENROUTER_API_KEY` as the credential. This is an unofficial but
working setup (OpenRouter exposes an Anthropic-compatible endpoint) — not a first-class integration, so it can break
on action/CLI updates.
- Does **not** gate the merge — it's advisory feedback only, separate from the `build-and-scan` job.

### Secrets & Variables

| Name | Type | Source | Purpose |
| -------------------- | -------- | ---------------------------- | -------------------------------------------------------------- |
| `YC_REGISTRY_ID` | variable | `vars.YC_REGISTRY_ID` | Yandex Container Registry ID |
| `YC_CR_SA_AUTH_JSON` | secret | `secrets.YC_CR_SA_AUTH_JSON` | YC service account JSON key for registry login |
| `GITHUB_TOKEN` | secret | auto-provided | Authenticated GitHub API requests for `mise` package downloads |
| `OPENROUTER_API_KEY` | secret | `secrets.OPENROUTER_API_KEY` | OpenRouter token used to authenticate the Claude PR review |

### Cache Strategy

PR and release builds share a **registry cache** stored in YC CR at `cr.yandex/<id>/github/personal/cache/devcr:latest`.

- **PR build** (`docker.pr.yml`) writes cache after scanning.
- **Release build** (`docker.release.yml`) reads the same cache before building multi-arch, significantly reducing
- **PR build** (`pr.yml`) writes cache after scanning.
- **Release build** (`release.yml`) reads the same cache before building multi-arch, significantly reducing
redundant layer builds.

This avoids the limitations of GHA cache (`type=gha`), where PR caches are isolated to the merge ref and invisible to
Expand Down
24 changes: 24 additions & 0 deletions stow-packages
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
atuin
bat
btop
delta
editorconfig
fish
fsh
ghostty
glow
markdownlint-cli2
nvim
prettier
ruff
sqlfluff
sqlite
starship
yamlfmt
yazi
zsh
pi
tealdeer
direnv
lazygit
claude
Loading