chore(ci): run CI on push to feature branches #195

Merged
lekss361 merged 2 commits from chore/ci-on-feature-branches into main 2026-05-16 08:26:05 +00:00
Owner

Summary

CI gates сейчас триггерятся только на:

  • push: main
  • pull_request: → main

При push в feat/** etc до PR open — CI не запускается, ошибки находятся поздно. User asked: «настрой чтобы в ветках собирался ci».

Change

.github/workflows/ci.yml — расширил on.push.branches:

on:
  push:
    branches:
      - main
      - 'feat/**'
      - 'fix/**'
      - 'refactor/**'
      - 'chore/**'
      - 'docs/**'
      - 'perf/**'
      - 'test/**'
      - 'hotfix/**'
  pull_request:
    branches: [main]

Conventional prefixes onlyexperiment/, wip/, temp/ ветки не triggers (intentional — saves runner capacity).

Side effects

  • Double-run при PR: push event на feature branch → CI run 1; pull_request event → CI run 2. Acceptable при runner capacity=2 (queued). Если станет проблемой → remove pull_request trigger.
  • Self-referential: при push этого PR в chore/ci-on-feature-branches → CI триггернётся уже по новому правилу (ветка matches chore/** после merge).

Test plan

  • YAML syntax: indentation 2 spaces, quoted '**' globs (required), structure list-of-strings
  • No deploy.yml duplication
  • Post-merge: следующий push в feat/** ветку → CI run появляется в Forgejo Actions

Forgejo Actions compatibility

'feat/**' glob patterns поддерживаются Forgejo Actions per Gitea-compat (тот же синтаксис что GHA). Если runner v6.3.1 не resolve'ит — fallback на branches-ignore: [main] + job-level filter.

Closes none (нет issue, user feedback inline).

## Summary CI gates сейчас триггерятся только на: - `push: main` - `pull_request: → main` При push в `feat/**` etc до PR open — CI **не запускается**, ошибки находятся поздно. User asked: «настрой чтобы в ветках собирался ci». ## Change `.github/workflows/ci.yml` — расширил `on.push.branches`: ```yaml on: push: branches: - main - 'feat/**' - 'fix/**' - 'refactor/**' - 'chore/**' - 'docs/**' - 'perf/**' - 'test/**' - 'hotfix/**' pull_request: branches: [main] ``` **Conventional prefixes only** — `experiment/`, `wip/`, `temp/` ветки не triggers (intentional — saves runner capacity). ## Side effects - **Double-run при PR**: `push` event на feature branch → CI run 1; `pull_request` event → CI run 2. Acceptable при runner capacity=2 (queued). Если станет проблемой → remove `pull_request` trigger. - Self-referential: при push этого PR в `chore/ci-on-feature-branches` → CI триггернётся **уже по новому правилу** (ветка matches `chore/**` после merge). ## Test plan - [x] YAML syntax: indentation 2 spaces, quoted `'**'` globs (required), structure list-of-strings - [x] No deploy.yml duplication - [ ] Post-merge: следующий push в feat/** ветку → CI run появляется в Forgejo Actions ## Forgejo Actions compatibility `'feat/**'` glob patterns поддерживаются Forgejo Actions per Gitea-compat (тот же синтаксис что GHA). Если runner v6.3.1 не resolve'ит — fallback на `branches-ignore: [main]` + job-level filter. Closes none (нет issue, user feedback inline).
lekss361 added 1 commit 2026-05-16 08:02:54 +00:00
Add conventional-prefix branch patterns to on.push.branches so
CI triggers immediately on feat/**, fix/**, refactor/**, chore/**,
docs/**, perf/**, test/**, hotfix/** pushes без waiting for PR.

Side effects:
- Double-run при PR (push + pull_request events) — acceptable, capacity=2
- Не trigger'ит на experimental/wip/temp branches (no prefix) — intentional
Author
Owner

Deep Code Review — verdict

Status: 🟡 MEDIUM (2 🟡, no blockers)
Reviewer: deep-code-reviewer (opus) · Head SHA: bf7f12f · Lines: +10 / -1

🟡 Medium

  • .github/workflows/ci.yml:3-16 — double-run без concurrency: group → удвоение нагрузки на single Beget runner (v6.3.1, capacity≈2). Каждый push в feature branch до PR-open + push после PR-open → 2 CI run (~7-10 min с postgis service + uv sync + mypy + pytest). PR body признаёт ("Acceptable при capacity=2"), но fix копеечный:

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

    Автоматически кенселит in-flight run при новом push, снимает заодно cache-thrash. Без этого capacity-2 runner может заблокировать .forgejo/workflows/deploy.yml (тоже шарит runner). Рекомендую добавить тем же PR — 4 строки.

  • Cache contention — uv-cache и npm-cache пишутся в shared runner cache; параллельные runs на разных ветках → episodic mtime-конфликты / partial hit. С concurrency: cancel-in-progress: true (выше) автоматически снимается.

🟢 Low / nits

  • hotfix/** glob есть в PR, но не упомянут в git-pr.md "Conventional prefixes" list (feat/fix/refactor/chore/docs/perf/test) — синхронизировать post-merge
  • PR body claim "ветка matches chore/** после merge" слегка вводит в заблуждение (ветка удалится после merge — self-reference moot)

Cross-file impact

  • .forgejo/workflows/deploy.ymlpush: main only, не пересекается с feature-branch триггером. Никакого конфликта.
  • .github/workflows/deploy-obsidian.ymlpush: main + paths:, не пересекается.
  • Vault infra/Self_Hosted_Git_Forgejo_Architecture.md §6 — подтверждает что Forgejo Runner читает И .github/workflows/, И .forgejo/workflows/. .github/workflows/ci.yml НЕ dead code, действительно исполняется.
  • Vault fixes/Bug_Forgejo_Runner_v6.4_YAML_Parse.md — runner pinned v6.3.1; 'feat/**' globs supported с v3+; v6.4.0 regression была про runs-on parsing, не branch globs. Compat OK.

Vault cross-check

  • ⚠️ Нет vault entry про expanded branch triggers / feature-branch CI — post-merge добавить либо в infra/Self_Hosted_Git_Forgejo_Architecture.md (раздел "CI conventions"), либо новым decisions/2026-05-16-ci-on-feature-branches.md
  • ⚠️ .claude/rules/deploy.md упоминает только .github/workflows/** под path-triggers — после полной migration нужен апдейт на .forgejo/workflows/** (отдельный PR)

Pre-flight

  • Не на main (chore/ci-on-feature-branches)
  • Нет --no-verify / --amend / --force в git log ветки
  • Diff 1-в-1 с PR body (10 added, 1 deleted, единственный файл)
  • Private repo → нет fork-PR risk
  • mergeable=true, no conflicts

Security

  • Никаких новых secret exposure paths — workflow только расширяет триггеры
  • pull_request (не pull_request_target — fork-attack-safe)
  • GHCR_PAT / DEPLOY_SSH_KEY используются только в deploy.yml, не в ci.yml

Performance findings

  • Runner load: single runner на Beget (v6.3.1, capacity≈2). После merge — обслуживает push на все feature ветки. При активной разработке (3-4 ветки одновременно) + double-run без concurrency → очередь 6-8 runs (~30-50 min backlog). Может заблокировать deploy.yml на main. Mitigation — concurrency group выше.

Positive observations

  • Quoted globs 'feat/**' корректно (unquoted ** в YAML = ошибка парсера)
  • Conventional prefixes only — разумная экономия capacity
  • pull_request: branches: [main] сохранён — contributors flow не сломан
  • Минимальный diff (1 файл, +10/-1), без piggyback изменений
  • Author явно идентифицировал double-run side effect в PR body

Blast radius

  • Risk: Low — workflow-level, max fail = пустые runs / capacity exhaustion
  • Reversibility: Easy — revert single commit
  • Merge window: anytime — но scope policy (.github/workflows/**) BLOCKS auto-merge — human approval required

Next steps

  1. Worker (devops-engineer): добавить 4 строки concurrency: group → fixup commit
  2. Re-push → re-poll
  3. Post-merge: vault entry в infra/Self_Hosted_Git_Forgejo_Architecture.md
  4. Post-merge: update .claude/rules/deploy.md на .forgejo/workflows/** (отдельный PR)
## Deep Code Review — verdict **Status**: 🟡 MEDIUM (2 🟡, no blockers) **Reviewer**: deep-code-reviewer (opus) · **Head SHA**: `bf7f12f` · **Lines**: +10 / -1 ### 🟡 Medium - [ ] **`.github/workflows/ci.yml:3-16` — double-run без `concurrency:` group → удвоение нагрузки на single Beget runner** (v6.3.1, capacity≈2). Каждый push в feature branch до PR-open + push после PR-open → 2 CI run (~7-10 min с postgis service + uv sync + mypy + pytest). PR body признаёт ("Acceptable при capacity=2"), но fix копеечный: ```yaml concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true ``` Автоматически кенселит in-flight run при новом push, снимает заодно cache-thrash. Без этого capacity-2 runner может заблокировать `.forgejo/workflows/deploy.yml` (тоже шарит runner). **Рекомендую добавить тем же PR — 4 строки.** - [ ] **Cache contention** — uv-cache и npm-cache пишутся в shared runner cache; параллельные runs на разных ветках → episodic mtime-конфликты / partial hit. С `concurrency: cancel-in-progress: true` (выше) автоматически снимается. ### 🟢 Low / nits - `hotfix/**` glob есть в PR, но не упомянут в `git-pr.md` "Conventional prefixes" list (`feat/fix/refactor/chore/docs/perf/test`) — синхронизировать post-merge - PR body claim "ветка matches `chore/**` после merge" слегка вводит в заблуждение (ветка удалится после merge — self-reference moot) ### Cross-file impact - **`.forgejo/workflows/deploy.yml`** — `push: main` only, не пересекается с feature-branch триггером. Никакого конфликта. - **`.github/workflows/deploy-obsidian.yml`** — `push: main + paths:`, не пересекается. - **Vault `infra/Self_Hosted_Git_Forgejo_Architecture.md` §6** — подтверждает что Forgejo Runner читает И `.github/workflows/`, И `.forgejo/workflows/`. **`.github/workflows/ci.yml` НЕ dead code**, действительно исполняется. - **Vault `fixes/Bug_Forgejo_Runner_v6.4_YAML_Parse.md`** — runner pinned v6.3.1; `'feat/**'` globs supported с v3+; v6.4.0 regression была про `runs-on` parsing, не branch globs. **Compat OK.** ### Vault cross-check - ⚠️ Нет vault entry про expanded branch triggers / feature-branch CI — post-merge добавить либо в `infra/Self_Hosted_Git_Forgejo_Architecture.md` (раздел "CI conventions"), либо новым `decisions/2026-05-16-ci-on-feature-branches.md` - ⚠️ `.claude/rules/deploy.md` упоминает только `.github/workflows/**` под path-triggers — после полной migration нужен апдейт на `.forgejo/workflows/**` (отдельный PR) ### Pre-flight - ✅ Не на main (`chore/ci-on-feature-branches`) - ✅ Нет `--no-verify` / `--amend` / `--force` в `git log` ветки - ✅ Diff 1-в-1 с PR body (10 added, 1 deleted, единственный файл) - ✅ Private repo → нет fork-PR risk - ✅ `mergeable=true`, no conflicts ### Security - ✅ Никаких новых secret exposure paths — workflow только расширяет триггеры - ✅ `pull_request` (не `pull_request_target` — fork-attack-safe) - ✅ GHCR_PAT / DEPLOY_SSH_KEY используются только в `deploy.yml`, не в `ci.yml` ### Performance findings - **Runner load**: single runner на Beget (v6.3.1, capacity≈2). После merge — обслуживает push на все feature ветки. При активной разработке (3-4 ветки одновременно) + double-run без concurrency → очередь 6-8 runs (~30-50 min backlog). Может заблокировать `deploy.yml` на main. **Mitigation — `concurrency` group выше.** ### Positive observations - ✅ Quoted globs `'feat/**'` корректно (unquoted `**` в YAML = ошибка парсера) - ✅ Conventional prefixes only — разумная экономия capacity - ✅ `pull_request: branches: [main]` сохранён — contributors flow не сломан - ✅ Минимальный diff (1 файл, +10/-1), без piggyback изменений - ✅ Author явно идентифицировал double-run side effect в PR body ### Blast radius - **Risk**: Low — workflow-level, max fail = пустые runs / capacity exhaustion - **Reversibility**: Easy — revert single commit - **Merge window**: anytime — но **scope policy (`.github/workflows/**`) BLOCKS auto-merge** — human approval required ### Next steps 1. Worker (devops-engineer): добавить 4 строки `concurrency:` group → fixup commit 2. Re-push → re-poll 3. Post-merge: vault entry в `infra/Self_Hosted_Git_Forgejo_Architecture.md` 4. Post-merge: update `.claude/rules/deploy.md` на `.forgejo/workflows/**` (отдельный PR)
lekss361 added 1 commit 2026-05-16 08:18:50 +00:00
Prevents double-run on PR (push + pull_request events), eliminates
cache contention, and frees runner capacity from queued feature-branch jobs.
Author
Owner

Deep Code Review — re-review verdict (head d1e2de0)

Summary

  • Status: APPROVE
  • Previous verdict: 🟡 MEDIUM at bf7f12f (2x 🟡 concurrency findings)
  • Files reviewed: 1 (P2: .github/workflows/ci.yml)
  • Lines: +14 / -1 (fixup +4 / -0)
  • Mergeable: true · State: open

What was fixed in fixup commit d1e2de0

Added top-level concurrency: block exactly per recommendation:

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

Semantics verified:

  • ${{ github.ref }} — per-branch isolation (parallel ветки не cancel'ят друг друга)
  • ${{ github.workflow }} — namespace prevents collision с deploy.yml / future workflows
  • ci- prefix — extra explicit namespace
  • cancel-in-progress: true — stale runs cancelled при новом push
  • YAML placement (after on:, before jobs:) — correct

Both previous 🟡 findings resolved

# Issue Resolution
1 Double-run на PR (push + pull_request события одновременно для одного SHA) Concurrency group cancel'ит первый run когда второй стартует на том же github.ref
2 Cache contention при concurrent runs (uv/npm пишут в same cache key) cancel-in-progress: true гарантирует один active run per branch — никакого write conflict

🟢 Nits (post-merge, не блокирует)

  • hotfix/** не в списке prefixes в .claude/rules/git-pr.md (PR добавил его в CI, но git-pr.md его не documents). Optional follow-up: либо добавить в git-pr.md, либо убрать из ci.yml для consistency.

Auto-merge decision

Per Auto-merge policy (deep-code-reviewer.md L340 + .claude/rules/git-pr.md):

.github/workflows/** BLOCKED для auto-merge даже при APPROVE.

Approved, but needs human merge per scope policy (touches .github/workflows/ci.yml).

Recommended merge: squash + delete branch chore/ci-on-feature-branches. Self-referential trigger expected — push of merge commit в main matches push.branches: [main] → новый CI run будет первой validation нового правила.

Risk / blast radius

  • Risk: Low (CI-only, no runtime/data impact)
  • Reversibility: Trivial revert (single-file workflow change)
  • Merge window: anytime
## Deep Code Review — re-review verdict (head `d1e2de0`) ### Summary - **Status**: ✅ APPROVE - **Previous verdict**: 🟡 MEDIUM at `bf7f12f` (2x 🟡 concurrency findings) - **Files reviewed**: 1 (P2: `.github/workflows/ci.yml`) - **Lines**: +14 / -1 (fixup +4 / -0) - **Mergeable**: true · **State**: open ### What was fixed in fixup commit `d1e2de0` Added top-level `concurrency:` block exactly per recommendation: ```yaml concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true ``` Semantics verified: - `${{ github.ref }}` — per-branch isolation (parallel ветки не cancel'ят друг друга) ✅ - `${{ github.workflow }}` — namespace prevents collision с deploy.yml / future workflows ✅ - `ci-` prefix — extra explicit namespace ✅ - `cancel-in-progress: true` — stale runs cancelled при новом push ✅ - YAML placement (after `on:`, before `jobs:`) — correct ✅ ### Both previous 🟡 findings resolved | # | Issue | Resolution | |---|---|---| | 1 | Double-run на PR (`push` + `pull_request` события одновременно для одного SHA) | Concurrency group cancel'ит первый run когда второй стартует на том же `github.ref` | | 2 | Cache contention при concurrent runs (uv/npm пишут в same cache key) | `cancel-in-progress: true` гарантирует один active run per branch — никакого write conflict | ### 🟢 Nits (post-merge, не блокирует) - [ ] `hotfix/**` не в списке prefixes в `.claude/rules/git-pr.md` (PR добавил его в CI, но git-pr.md его не documents). Optional follow-up: либо добавить в git-pr.md, либо убрать из ci.yml для consistency. ### Auto-merge decision Per Auto-merge policy (deep-code-reviewer.md L340 + `.claude/rules/git-pr.md`): > `.github/workflows/**` → ❌ BLOCKED для auto-merge даже при ✅ APPROVE. **✅ Approved, but needs human merge per scope policy** (touches `.github/workflows/ci.yml`). Recommended merge: squash + delete branch `chore/ci-on-feature-branches`. Self-referential trigger expected — push of merge commit в `main` matches `push.branches: [main]` → новый CI run будет первой validation нового правила. ### Risk / blast radius - **Risk**: Low (CI-only, no runtime/data impact) - **Reversibility**: Trivial revert (single-file workflow change) - **Merge window**: anytime
lekss361 merged commit 5455d57bed into main 2026-05-16 08:26:05 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#195
No description provided.