|
| 1 | +# Dynamic Setup Redesign (Two‑File CircleCI Architecture) |
| 2 | + |
| 3 | +This note summarizes the new direction for CIGen’s CircleCI dynamic setup, aligning with DocSpring’s production needs and replacing the previous per‑workflow split approach. |
| 4 | + |
| 5 | +## Goals |
| 6 | + |
| 7 | +- Use exactly two CircleCI configs: |
| 8 | + - `.circleci/config.yml` — entrypoint. Contains: |
| 9 | + - workflow `package_updates`: runs immediately when `pipeline.parameters.check_package_versions == true`. |
| 10 | + - workflow `staging_postman_tests`: runs immediately when `pipeline.parameters.run_staging_postman_tests == true`. |
| 11 | + - workflow `setup`: runs only when neither param is true; performs skip‑gating and posts a filtered continuation. |
| 12 | + - `.circleci/main.yml` — CI/CD workflow (tests/build/deploy). Designed for dynamic skip. |
| 13 | +- No per‑job runtime skip on CircleCI when `dynamic=true`. Setup is the gate. |
| 14 | +- Skip gating in setup uses CircleCI’s cache save/restore only (no Redis). |
| 15 | +- Use a dedicated `docspringcom/cigen` runtime image (no Ruby dependency) for setup. |
| 16 | +- On CI, ensure `.circleci/config.yml` is up‑to‑date (self‑check), optionally auto‑commit+push and fail if drift is detected (opt‑in). |
| 17 | + |
| 18 | +## Behavior |
| 19 | + |
| 20 | +1. Immediate workflows (in `.circleci/config.yml`) |
| 21 | + |
| 22 | +- `package_updates` runs immediately if `check_package_versions` param is true. |
| 23 | +- `staging_postman_tests` runs immediately if `run_staging_postman_tests` param is true. |
| 24 | +- Otherwise, neither runs. |
| 25 | + |
| 26 | +2. Dynamic setup workflow (in `.circleci/config.yml`) |
| 27 | + |
| 28 | +- Image: `docspringcom/cigen:latest` (fallback curl installer for cigen until published). |
| 29 | +- Steps: |
| 30 | + - `checkout` |
| 31 | + - `cigen generate` → writes `.circleci/main.yml` (and re‑renders `.circleci/config.yml` for self‑check). |
| 32 | + - Self‑check (opt‑in): verify current `.circleci/config.yml` matches what `cigen generate` would produce. If not: |
| 33 | + - Optionally `git add && git commit && git push` (opt‑in), then fail the build to force a new run on the updated entrypoint. |
| 34 | + - Skip analysis for `main` only: |
| 35 | + - For each job+arch in `main` with `source_files`: |
| 36 | + - Compute `JOB_HASH` in setup (same hashing logic as jobs). |
| 37 | + - Write a variant job‑key: `/tmp/setup_keys/<job_arch>/job-key` (`${JOB_NAME}-${DOCKER_ARCH}-${JOB_HASH}`). |
| 38 | + - `restore_cache` with key `job_status-exists-v1-{{ checksum "/tmp/setup_keys/<job_arch>/job-key" }}` |
| 39 | + - If `/tmp/cigen_job_exists/done_${JOB_HASH}` exists, append `<job_arch>` to `/tmp/skip/main.txt`. |
| 40 | + - Clear `/tmp/cigen_job_exists` before the next restore. |
| 41 | + - `cigen generate --workflow main` with `CIGEN_SKIP_JOBS_FILE=/tmp/skip/main.txt` to prune jobs and transitive dependents; write filtered continuation. |
| 42 | + - Continue with the filtered `.circleci/main.yml` via the Continuation API. |
| 43 | + |
| 44 | +3. Jobs (CircleCI with dynamic=true) |
| 45 | + |
| 46 | +- Do NOT inject per‑job runtime `restore_cache + halt`. Setup is the gate. |
| 47 | +- Still record an “exists” marker at end of job: |
| 48 | + - touch `/tmp/cigen_job_exists/done_${JOB_HASH}` |
| 49 | + - `save_cache` with key `job_status-exists-v1-{{ checksum "/tmp/cigen_job_status/job-key" }}`; paths `/tmp/cigen_job_exists` |
| 50 | +- Keep the job-status cache write if desired, but runtime halt is disabled for CircleCI dynamic. |
| 51 | + |
| 52 | +## CIGen Implementation Outline |
| 53 | + |
| 54 | +- Add `workflows_meta` (internal) to drive generation; but final shape is two files only: |
| 55 | + - `config.yml` — contains param‑guarded `package_updates` and `staging_postman_tests`, and a synthesized `setup` workflow. |
| 56 | + - `main.yml` — the CI/CD workflow. |
| 57 | +- Generator changes: |
| 58 | + - Always emit `main.yml` for CircleCI dynamic. |
| 59 | + - Synthesize `config.yml` with three workflows as above (no split files for package updates or staging). |
| 60 | + - Disable per‑job runtime skip injection when `dynamic=true` and `provider=circleci`; still add exists‑cache save step at end of jobs with `source_files`. |
| 61 | + - Add `CIGEN_SKIP_JOBS_FILE` support for `cigen generate --workflow main` to prune jobs and transitive dependents (already implemented). |
| 62 | +- Setup generation: |
| 63 | + - Uses `docspring/cigen:latest`; fallback curl installer in case the image isn’t on the runner yet. |
| 64 | + - Emits a deterministic loop of `restore_cache` probes (one per job variant in `main`) and collects a skip list. |
| 65 | + - Emits a self‑check step (opt‑in) that regenerates `config.yml` and verifies drift. |
| 66 | + |
| 67 | +## Self‑Check (Opt‑In) |
| 68 | + |
| 69 | +- Config key (to be added): |
| 70 | + |
| 71 | +```yaml |
| 72 | +setup: |
| 73 | + self_check: |
| 74 | + enabled: true |
| 75 | + commit_on_diff: true # optional: add+commit+push then fail |
| 76 | +``` |
| 77 | +
|
| 78 | +- If enabled, setup: |
| 79 | + - Regenerates `.circleci/config.yml` into a temp path. |
| 80 | + - If different from the existing entrypoint, optionally commit/push and fail the build. |
| 81 | + - This ensures the dynamic entrypoint is always up‑to‑date. |
| 82 | + |
| 83 | +## Notes |
| 84 | + |
| 85 | +- This design avoids per‑job runtime halts in CircleCI and does all skip‑gating up front, matching DocSpring’s Ruby implementation goals. |
| 86 | +- “Immediate” workflows (package updates, staging postman) run right away via parameters; no hand‑off to setup. |
| 87 | +- Scheduled workflows are handled by setting the parameter on the schedule. |
| 88 | +- BASE_HASH/file hashing is anchored and cached at the file/content level and is millisecond‑fast. |
| 89 | + |
| 90 | +## Next Steps |
| 91 | + |
| 92 | +- Implement generation of combined `.circleci/config.yml` (package_updates + staging_postman_tests + setup) and `.circleci/main.yml` only. |
| 93 | +- Emit the skip‑probe loop in setup with static `restore_cache` steps per job variant in `main`. |
| 94 | +- Add setup self‑check (opt‑in) with optional auto‑commit+push. |
| 95 | +- Publish `docspring/cigen` and switch setup to use it without fallback. |
| 96 | +- Validate end‑to‑end on DocSpring: push branch, confirm pipeline behavior (immediate workflows via params, setup gating, minimal continuation). |
0 commit comments