Files
gps-denied-onboard/.cursor/skills/monorepo-cicd/SKILL.md
T
2026-04-18 22:04:19 +03:00

165 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: monorepo-cicd
description: Syncs CI/CD and infrastructure configuration at the monorepo root (compose files, install scripts, env templates, CI service tables) after one or more components changed. Reads `_docs/_repo-config.yaml` (produced by monorepo-discover) to know which CI artifacts are in play and how they're structured. Touches ONLY CI/infra files — never documentation, component directories, or per-component CI configs. Use when a component added/changed a Dockerfile path, port, env var, image tag format, or runtime dependency.
---
# Monorepo CI/CD
Propagates component changes into the repo-level CI/CD and infrastructure artifacts. Strictly scoped — never edits docs, component internals, or per-component CI configs.
## Scope — explicit
| In scope | Out of scope |
| -------- | ------------ |
| `docker-compose.*.yml` at repo root | Unified docs in `_docs/*.md` → use `monorepo-document` |
| `.env.example` / `.env.template` | Root `README.md` documentation → `monorepo-document` |
| Install scripts (`ci-*.sh`, `setup.sh`, etc.) | Per-component CI configs (`<component>/.woodpecker/*`, `<component>/.github/*`) |
| CI service-registry docs (`ci_steps.md` or similar — the human-readable index of pipelines; in scope only if the config says so under `ci.service_registry_doc`) | Component source code, Dockerfiles, or internal docs |
| Kustomization / Helm manifests at repo root | `_docs/_repo-config.yaml` itself (only `monorepo-discover` and `monorepo-onboard` write it) |
If a component change needs doc updates too, tell the user to also run `monorepo-document`.
**Special case**: `ci.service_registry_doc` (e.g., `ci_steps.md`) is a **CI artifact that happens to be markdown**. It's in this skill's scope, not `monorepo-document`'s, because it describes the pipeline/service topology — not user-facing feature docs.
## Preconditions (hard gates)
1. `_docs/_repo-config.yaml` exists.
2. Top-level `confirmed_by_user: true`.
3. `ci.*` section is populated in config (not empty).
4. Components-in-scope have confirmed CI mappings, OR user explicitly approves inferred ones.
If any gate fails, redirect to `monorepo-discover` or ask for confirmation.
## Mitigations (M1M7)
- **M1** Separation: this skill only touches CI/infra files; no docs, no component internals.
- **M3** Factual vs. interpretive: image tag format, port numbers, env var names — FACTUAL, read from code. Doc cross-references — out of scope entirely (belongs to `monorepo-document`).
- **M4** Batch questions at checkpoints.
- **M5** Skip over guess: component with no CI mapping → skip and report.
- **M6** Assumptions footer + append to `_repo-config.yaml` `assumptions_log`.
- **M7** Drift detection: verify every file in `ci.orchestration_files`, `ci.install_scripts`, `ci.env_template` exists; stop if not.
## Workflow
### Phase 1: Drift check (M7)
Verify every CI file listed in config exists on disk. Missing file → stop, ask user:
- Run `monorepo-discover` to refresh, OR
- Skip the missing file (recorded in report)
Do NOT recreate missing infra files automatically.
### Phase 2: Determine scope
Ask the user (unless specified):
> Which components changed? (a) list them, (b) auto-detect, (c) skip detection (I'll apply specific changes).
For **auto-detect**, for each component:
```bash
git -C <path> log --oneline -20 # submodule
# or
git log --oneline -20 -- <path> # monorepo subfolder
```
Flag commits that touch CI-relevant concerns:
- Dockerfile additions, renames, or path changes
- CI pipeline files (`<component>/.woodpecker/*`, `<component>/.github/workflows/*`, etc.)
- New exposed ports
- New environment variables consumed by the component
- Changes to image name / tag format
- New dependency on another service (e.g., new DB, new broker)
Present the flagged list; confirm.
### Phase 3: Classify changes per component
| Change type | Target CI files |
| ----------- | --------------- |
| Dockerfile path moved/renamed | `ci.service_registry_doc` service table; per-component CI is OUT OF SCOPE (tell user to update it) |
| New port exposed | `ci.service_registry_doc` ports section (if infra port); component's service block in orchestration file |
| Registry URL changed | `ci.install_scripts` (all of them); `ci.env_template`; `ci.service_registry_doc` |
| Branch naming convention changed | All `ci.install_scripts`; all `ci.orchestration_files` referencing the branch; `ci.service_registry_doc` |
| New runtime env var | `ci.env_template`; component's service block in orchestration file |
| New infrastructure component (DB, cache, broker) | Relevant `ci.orchestration_files`; `ci.service_registry_doc` architecture section |
| New image tag format | All `ci.orchestration_files`; `ci.install_scripts`; `ci.service_registry_doc` |
| Watchtower/polling config change | Specific `ci.orchestration_files`; `ci.service_registry_doc` |
If a change type isn't covered here or in the config, add to an unresolved list and skip (M5).
### Phase 4: Apply edits
For each (change → target file) pair:
1. Read the target file.
2. Locate the service block / table row / section.
3. Edit carefully:
- **Orchestration files (compose/kustomize/helm)**: YAML; preserve indentation, anchors, and references exactly. Match existing service-block structure. Never reformat unchanged lines.
- **Install scripts (`*.sh`)**: shell; any edit must remain **idempotent**. Re-running the script on an already-configured host must not break it. If an edit cannot be made idempotent, flag for the user and skip.
- **`.env.example`**: append new vars at the appropriate section; never remove user's local customizations (file is in git, so comments may be significant).
- **`ci.service_registry_doc`** (markdown): preserve column widths, ordering (alphabetical or compose-order — whichever existed), ASCII diagrams.
### Phase 5: Skip-and-report (M5)
Skip a component if:
- No `ci_config` in its config entry AND no entry in config's CI mappings
- `confirmed: false` on its mapping and user didn't approve
- Component's Dockerfile path declared in config doesn't exist on disk — surface contradiction
- Change type unrecognized — skip, report for manual handling
### Phase 6: Idempotency / lint check
- Shell: if `shellcheck` available, run on any edited `*.sh`.
- YAML: if `yamllint` or `prettier` available, run on edited `*.yml` / `*.yaml`.
- For edited install scripts, **mentally re-run** the logic: would a second invocation crash, duplicate, or corrupt? Flag anything that might.
Skip linters silently if none configured — don't install tools.
### Phase 7: Report + assumptions footer (M6)
```
monorepo-cicd run complete.
CI files updated (N):
- docker-compose.run.yml — added `loader` service block
- .env.example — added LOADER_BUCKET_NAME placeholder
- ci_steps.md — added `loader` row in service table
Skipped (K):
- satellite-provider: no ci_config in repo-config.yaml
- detections: Dockerfile path in config (admin/src/Dockerfile) does not exist on disk
Manual actions needed (M):
- Update `<submodule>/.woodpecker/*.yml` inside the submodule's own workspace
(per-component CI is not maintained by this skill)
Assumptions used this run:
- image tag format: ${REGISTRY}/${NAME}:${BRANCH}-${ARCH_TAG} (confirmed in config)
- target branch for triggers: [stage, main] (confirmed in config)
Next step: review the diff, then commit with
`<commit_prefix> Sync CI after <components>` (or your own message).
```
Append run entry to `_docs/_repo-config.yaml` `assumptions_log:`.
## What this skill will NEVER do
- Modify files inside component directories
- Edit unified docs under `docs.root`
- Edit per-component CI configs (`.woodpecker/*`, `.github/*`, etc.)
- Auto-generate CI pipeline YAML for components (only provide template guidance)
- Set `confirmed_by_user` or `confirmed:` flags
- Auto-commit
- Install tools (shellcheck, yamllint, etc.) — use if present, skip if absent
## Edge cases
- **Compose file has service blocks for components NOT in config**: note in report; ask user whether to rediscover (`monorepo-discover`) or leave them alone.
- **`.env.example` has entries for removed components**: don't auto-remove; flag to user.
- **Install script edit cannot be made idempotent**: don't save; ask user to handle manually.
- **Branch trigger vs. runtime branch mismatch**: if config says triggers are `[stage, main]` but a compose file references a branch tag `develop`, stop and ask.