ci: skip Docker publish for .gitea/.planning-only pushes #16
+13
-11
@@ -16,20 +16,22 @@ jobs:
|
||||
- uses: dorny/paths-filter@v4
|
||||
id: filter
|
||||
with:
|
||||
# 'every' + negation-only globs. dorny combines a filter's patterns with
|
||||
# Array.some by default, and picomatch compiles '!.gitea/**' as "matches any
|
||||
# path NOT under .gitea" — so under 'some' that single line matched EVERY
|
||||
# non-.gitea file (incl. .planning/** and *.md), flipping code=true for
|
||||
# doc-only PRs and silently running the heavy api/harness jobs (regression
|
||||
# introduced by quick task 260613-dmw; the old positive allowlist also never
|
||||
# actually excluded .gitea because '**/*.yml' already matched workflow files).
|
||||
# With predicate-quantifier 'every' a changed file counts as "code" ONLY if it
|
||||
# matches ALL patterns — i.e. it is outside .gitea/, outside .planning/, and is
|
||||
# not Markdown. Verified against representative file sets in quick task 260613-fp9.
|
||||
predicate-quantifier: 'every'
|
||||
filters: |
|
||||
code:
|
||||
- '**/*.ts'
|
||||
- '**/*.tsx'
|
||||
- '**/*.js'
|
||||
- '**/*.json'
|
||||
- '**/*.yaml'
|
||||
- '**/*.yml'
|
||||
- 'apps/**'
|
||||
- 'packages/**'
|
||||
- 'pnpm-lock.yaml'
|
||||
- 'Dockerfile'
|
||||
- 'docker-compose*.yml'
|
||||
- '!.gitea/**'
|
||||
- '!.planning/**'
|
||||
- '!**/*.md'
|
||||
|
||||
fast-checks:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# Publishing / Releases
|
||||
#
|
||||
# Trigger: push to main — i.e. when any PR merges.
|
||||
# Trigger: push to main — i.e. when any PR merges — EXCEPT pushes whose changed
|
||||
# files are confined to .gitea/** (CI/workflow edits) and/or .planning/** (GSD
|
||||
# planning docs, which push straight to main under the unprotected .planning/*
|
||||
# branch-protection pattern). Those never alter the shipped image (.dockerignore
|
||||
# already excludes .planning), so the paths-ignore filter below skips a wasted
|
||||
# build + re-push. A push that also touches code/Dockerfile/manifests still publishes.
|
||||
# Image: git.bergerhouse.net/luckberg/familysync-api
|
||||
# Tags:
|
||||
# :latest — moving pointer for easy pulls
|
||||
@@ -25,6 +30,12 @@ name: Publish
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
# Doc/CI-only pushes produce a byte-identical image — skip the build entirely.
|
||||
# paths-ignore skips the run only when EVERY changed file matches; a mixed
|
||||
# push (code + .planning) still publishes.
|
||||
paths-ignore:
|
||||
- '.gitea/**'
|
||||
- '.planning/**'
|
||||
|
||||
env:
|
||||
MILESTONE: v1.1
|
||||
|
||||
+2
-1
@@ -28,7 +28,7 @@ See: .planning/PROJECT.md (updated 2026-06-10)
|
||||
Phase: 999.1
|
||||
Plan: Not started
|
||||
Status: Phase complete — ready for verification
|
||||
Last activity: 2026-06-13 - Completed quick task 260613-dmw: exclude .gitea/** from CI heavy-job paths-filter
|
||||
Last activity: 2026-06-13 - Completed quick task 260613-fp9: .gitea/.planning-only pushes skip the Docker publish
|
||||
|
||||
### ✅ Resolved Checkpoint — Phase 15 Plan 15-03 Task 2 (human-action)
|
||||
|
||||
@@ -215,6 +215,7 @@ Recent decisions affecting current work:
|
||||
| 260611-ozt | Split publish job into standalone .gitea/workflows/publish.yml (on: push→main only, no redundant event-guard if:; MILESTONE env moved with it) and strip it + the push trigger from ci.yml — kills the orphaned `CI / publish (pull_request)` pending status (phase-8 code-review WR-01). name:CI + fast-checks/api/harness job ids held stable so the required branch-protection contexts stay valid. Documented the release model in README "Publishing / Releases" + publish.yml header. Both YAML validated (yq) | 2026-06-11 | 92353e1 | | [260611-ozt-split-publish-job-into-standalone-gitea-](./quick/260611-ozt-split-publish-job-into-standalone-gitea-/) |
|
||||
| 260611-tfc | Fix WR-01 (13-REVIEW): apps/pwa/src/sw.ts notificationclick openWindow fallback was unreachable when client.focus() rejects (window closed between matchAll/focus) or client.navigate() resolves null — chained a navigate-result check + a .catch, both falling through to self.clients.openWindow(url). lint/format:check/typecheck green, build emits sw.js, 191/191 pwa tests | 2026-06-12 | af78ccc | Verified | [260611-tfc-fix-wr-01-sw-ts-notificationclick-openwi](./quick/260611-tfc-fix-wr-01-sw-ts-notificationclick-openwi/) |
|
||||
| 260613-dmw | Exclude `.gitea/**` from the CI `changes` `code` paths-filter so workflow-only PRs skip the heavy api/harness jobs (treated like docs) while fast-checks + gate still run. Single `- '!.gitea/**'` negation appended after the yml/yaml globs (index 11 vs 5). Rides along on the Phase 16 branch / PR #15. | 2026-06-13 | 2d329a9 | | [260613-dmw-exclude-gitea-workflow-config-changes-fr](./quick/260613-dmw-exclude-gitea-workflow-config-changes-fr/) |
|
||||
| 260613-fp9 | `.gitea`/`.planning`-only pushes to main no longer trigger the Docker publish — added `paths-ignore: ['.gitea/**', '.planning/**']` under `on.push` in `.gitea/workflows/publish.yml` (skips only when EVERY changed file matches; mixed code+docs pushes still publish). `.dockerignore` already excludes `.planning` so the image is byte-identical. Done in isolated worktree (phase-10 agent held main tree). | 2026-06-13 | cd5a88c | | [260613-fp9-gitea-and-planning-pushes-should-not-tri](./quick/260613-fp9-gitea-and-planning-pushes-should-not-tri/) |
|
||||
|
||||
## Deferred Items
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
---
|
||||
quick_id: 260613-fp9
|
||||
title: ".gitea and .planning pushes should not trigger a docker image publish"
|
||||
status: ready
|
||||
---
|
||||
|
||||
# Quick Task 260613-fp9: Skip Docker publish for `.gitea`/`.planning`-only pushes
|
||||
|
||||
## Problem
|
||||
|
||||
`.gitea/workflows/publish.yml` triggers on every `push` to `main` with no path
|
||||
filter. Two classes of push currently fire a full Docker build + publish that
|
||||
produce an identical image:
|
||||
|
||||
- `.planning/**`-only commits, which push straight to `main` (the `.planning/*`
|
||||
branch-protection pattern is unprotected).
|
||||
- `.gitea/**`-only changes (CI/workflow edits) merged via PR.
|
||||
|
||||
Neither changes the shipped artifact — `.dockerignore` already excludes
|
||||
`.planning` (and `apps/api/tests`) from the image — so the rebuild is wasted
|
||||
runner time and a needless `:latest` re-push / new `:vMILESTONE-<sha>` tag.
|
||||
|
||||
## Change
|
||||
|
||||
Add a `paths-ignore` filter to the `push` trigger in `publish.yml`:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- '.gitea/**'
|
||||
- '.planning/**'
|
||||
```
|
||||
|
||||
Gitea Actions follows GitHub-compatible workflow syntax (the repo already relies
|
||||
on the native `branches:` push filter). When every file changed in a push to
|
||||
`main` matches a `paths-ignore` glob, the `publish` job is skipped. A push that
|
||||
also touches code/Dockerfile/manifests still triggers publish — correct.
|
||||
|
||||
Also update the header comment block to document the new skip behavior.
|
||||
|
||||
## Tasks
|
||||
|
||||
1. **Edit `.gitea/workflows/publish.yml`**
|
||||
- files: `.gitea/workflows/publish.yml`
|
||||
- action: Add `paths-ignore: ['.gitea/**', '.planning/**']` under `on.push`;
|
||||
update the top-of-file `# Trigger:` comment to note doc/CI-only pushes skip.
|
||||
- verify: `paths-ignore` present under `on.push`; YAML still parses; the
|
||||
existing `--target production` self-assertion grep still matches.
|
||||
- done: pushes touching only `.gitea/**` and/or `.planning/**` no longer
|
||||
trigger the publish job; mixed pushes (code + docs) still publish.
|
||||
|
||||
## must_haves
|
||||
|
||||
- truths:
|
||||
- publish.yml `on.push` carries a `paths-ignore` listing `.gitea/**` and `.planning/**`
|
||||
- `branches: [main]` is retained
|
||||
- artifacts:
|
||||
- `.gitea/workflows/publish.yml`
|
||||
- key_links:
|
||||
- `.gitea/workflows/publish.yml`
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
---
|
||||
quick_id: 260613-fp9
|
||||
title: ".gitea and .planning pushes should not trigger a docker image publish"
|
||||
status: complete
|
||||
date: 2026-06-13
|
||||
---
|
||||
|
||||
# Quick Task 260613-fp9 — Summary
|
||||
|
||||
## What changed
|
||||
|
||||
Added a `paths-ignore` filter to the `push` trigger in
|
||||
`.gitea/workflows/publish.yml`:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- '.gitea/**'
|
||||
- '.planning/**'
|
||||
```
|
||||
|
||||
Updated the file's header comment to document the new skip behavior.
|
||||
|
||||
## Why
|
||||
|
||||
Every push to `main` previously ran a full Docker build + push. Pushes confined
|
||||
to `.planning/**` (planning docs push straight to main under the unprotected
|
||||
`.planning/*` branch-protection pattern) or `.gitea/**` (CI/workflow edits) never
|
||||
change the shipped image — `.dockerignore` already excludes `.planning`. The
|
||||
rebuild and `:latest` re-push were wasted runner time.
|
||||
|
||||
## Behavior
|
||||
|
||||
- Push touching only `.gitea/**` and/or `.planning/**` → `publish` job skipped.
|
||||
- Push touching code / Dockerfile / manifests (alone or mixed with docs) →
|
||||
`publish` runs as before. `paths-ignore` skips only when **every** changed
|
||||
file matches a glob.
|
||||
|
||||
## Verification
|
||||
|
||||
- `python3 yaml.safe_load` parses the file; `on.push` carries both
|
||||
`branches: [main]` and `paths-ignore: ['.gitea/**', '.planning/**']`; the
|
||||
`publish` job is intact.
|
||||
- The in-workflow `grep "--target production"` self-assertion still matches
|
||||
(D-10 hygiene check unaffected).
|
||||
|
||||
## Isolation note
|
||||
|
||||
Executed in a dedicated worktree (`familysync-wt-fp9`, branch
|
||||
`quick/260613-fp9-publish-paths-ignore` off `origin/main`) because a concurrent
|
||||
phase-10 agent has the main working tree checked out on
|
||||
`gsd/phase-10-admin-role-settings`. No subagents spawned — trivial single-file
|
||||
config edit done inline.
|
||||
|
||||
## Follow-up fix — ci.yml heavy-job paths-filter (added after PR opened)
|
||||
|
||||
Opening PR #16 surfaced a second, related bug: the `api` + `harness` jobs ran on
|
||||
this `.gitea`/`.planning`-only PR. Root cause in `.gitea/workflows/ci.yml`'s
|
||||
`changes` job:
|
||||
|
||||
- dorny/paths-filter combines a filter's patterns with `Array.some`, and
|
||||
picomatch compiles `!.gitea/**` as "matches any path **not** under `.gitea`".
|
||||
- So the `- '!.gitea/**'` line (added by quick task 260613-dmw) matched every
|
||||
non-`.gitea` file — including `.planning/**` and `*.md` — making `code=true`
|
||||
for doc-only PRs and silently running the heavy jobs. It also never excluded
|
||||
`.gitea` (the `**/*.yml` glob already matched workflow files), so dmw's stated
|
||||
goal was never achieved and it regressed the Phase 15 doc-only skip.
|
||||
|
||||
Fix: switched the filter to `predicate-quantifier: 'every'` with negation-only
|
||||
globs so a file counts as `code` ONLY if it is outside `.gitea/`, outside
|
||||
`.planning/`, and not Markdown:
|
||||
|
||||
```yaml
|
||||
predicate-quantifier: 'every'
|
||||
filters: |
|
||||
code:
|
||||
- '!.gitea/**'
|
||||
- '!.planning/**'
|
||||
- '!**/*.md'
|
||||
```
|
||||
|
||||
Verified locally with picomatch against representative file sets: `.gitea`-only,
|
||||
`.planning`-only, `*.md`-only, and this PR's mix all → `code=false` (heavy jobs
|
||||
skip); real code (`.ts`), `pnpm-lock.yaml`, `package.json`, and code+docs mixes
|
||||
all → `code=true` (heavy jobs run).
|
||||
|
||||
## Follow-up
|
||||
|
||||
`publish.yml` and `ci.yml` both live under `.gitea/**`, so merging this PR is a
|
||||
`.gitea`-only push and will (correctly) not publish. PR #16 opened against `main`
|
||||
(protected; code changes require PR).
|
||||
Reference in New Issue
Block a user