diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c7892b..2beab86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,21 +7,21 @@ on: branches: [master] jobs: - changes: # flag doc-only pushes so we can skip publish for them + changes: # flag doc/CI-only pushes (md, .claude/, .github/) so we can skip publish for them runs-on: ubuntu-latest outputs: code: ${{ steps.filter.outputs.code }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - id: filter - name: Did anything outside docs change? + name: Did anything outside docs/CI config change? run: | base="${{ github.event.before }}" if [ "${{ github.event_name }}" != "push" ] || ! git cat-file -e "${base}^{commit}" 2>/dev/null; then echo "code=true" >> "$GITHUB_OUTPUT" - elif git diff --name-only "$base" "${{ github.sha }}" | grep -qvE '(\.md$|^\.claude/)'; then + elif git diff --name-only "$base" "${{ github.sha }}" | grep -qvE '(\.md$|^\.claude/|^\.github/)'; then echo "code=true" >> "$GITHUB_OUTPUT" else echo "code=false" >> "$GITHUB_OUTPUT" @@ -30,8 +30,8 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: "3.12" cache: pip @@ -49,8 +49,8 @@ jobs: audit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: "3.12" cache: pip @@ -67,9 +67,9 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@v4 - - uses: docker/setup-buildx-action@v3 - - uses: docker/login-action@v3 + - uses: actions/checkout@v6 + - uses: docker/setup-buildx-action@v4 + - uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.actor }} @@ -77,7 +77,7 @@ jobs: - id: vars run: echo "sha=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" - name: Build & push API image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . file: ./Dockerfile.api @@ -90,7 +90,7 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max - name: Build & push web app image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . file: ./Dockerfile.app diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index 4dd0dc2..6e50e12 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -12,7 +12,7 @@ name: Claude Code Review # Honors CLAUDE.md. Comments only; never approves or blocks the PR. on: pull_request: - types: [opened, synchronize] + types: [opened, synchronize, ready_for_review] # One review per PR at a time; a fresh push cancels an in-flight review (saves usage). concurrency: @@ -27,6 +27,8 @@ permissions: jobs: review: + # Skip draft PRs (saves Pro usage on WIP); a review runs when the PR is marked ready for review. + if: ${{ !github.event.pull_request.draft }} runs-on: ubuntu-latest timeout-minutes: 20 steps: diff --git a/CLAUDE.md b/CLAUDE.md index 0c70c88..b342e40 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -175,8 +175,15 @@ anymore (GPUH now deploys only GBot). - **Build (CI):** on push to `master`, the `publish` job in `.github/workflows/ci.yml` builds native **arm64** images and pushes them to **GHCR** — `ghcr.io/cgoulart35/halloweenevent-{api,webapp}` (`:latest` + `:`). Packages are **public**, so the Pi pulls anonymously (no `docker login`). - A `changes` job gates `publish`: pushes touching only docs (`**.md` / `.claude/`) still run - `test`+`audit` but skip the build, so docs/skills changes don't publish or redeploy. + A `changes` job gates `publish`: pushes touching only docs/CI config (`**.md` / `.claude/` / + `.github/`) still run `test`+`audit` but skip the build, so docs/skills/CI-config changes don't + publish or redeploy. +- **PR review (CI):** `.github/workflows/claude-review.yml` runs Claude (`anthropics/claude-code-action@v1`) + on every non-draft PR (drafts get reviewed once marked ready), posting inline findings; authed by the `CLAUDE_CODE_OAUTH_TOKEN` repo secret (a Claude + **Pro** subscription, not API billing). Comments only — never approves or blocks. Editing this + workflow makes a PR fail its own review — the action's **backend** rejects a PR whose workflow + differs from `master`'s (`401 Workflow validation failed`, not a GitHub-side rule) — so merge + workflow changes on their own first. - **Deploy (Pi):** `scripts/deploy-watcher.sh`, started at boot from `/etc/rc.local` via `scripts/start.sh`, polls GHCR every `DEPLOY_POLL_INTERVAL`s (default 120) and — when a new image digest appears — runs `scripts/deploy.sh`: `git fetch` + `git checkout -f master` + diff --git a/README.md b/README.md index 05d137f..519bf8b 100644 --- a/README.md +++ b/README.md @@ -218,8 +218,8 @@ CI/CD is **self-contained** (no external deploy service). On push to `master`, G (`ghcr.io/cgoulart35/halloweenevent-{api,webapp}`). On the Pi, `scripts/deploy-watcher.sh` (started at boot from `/etc/rc.local`) polls GHCR and, when a new image is published, runs `scripts/deploy.sh` — `git reset --hard origin/master` then `docker compose -f docker-compose-prod.yml pull && up -d`. The -trigger is the **published image, not the commit**, so a deploy never races the build. Doc-only pushes -(`**.md` / `.claude/`) are skipped by a `changes` gate, so they don't build or deploy. +trigger is the **published image, not the commit**, so a deploy never races the build. Doc/CI-config-only +pushes (`**.md` / `.claude/` / `.github/`) are skipped by a `changes` gate, so they don't build or deploy. `api.env` / `app.env` / `serviceAccountKey.json` are gitignored and live **persistently in the repo dir on the Pi** — injected at runtime (`env_file:` + a volume mount), never baked into the image, and