Skip to content

Commit 313a9c3

Browse files
authored
Merge pull request #107 from eqrm/feat/issues-100-105
feat: coverage, bulk grant adoption, per-instance catalog, honest pagination
2 parents 35c1fbf + 62835b0 commit 313a9c3

110 files changed

Lines changed: 7378 additions & 2563 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020
node-version: 22
2121
cache: npm
2222
- run: npm ci
23+
- run: npm run format:check
2324
- run: npm run lint
2425
- run: npm run typecheck
2526
- run: npm test

‎.github/workflows/release.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ jobs:
3838
cache: npm
3939

4040
- run: npm ci
41+
- run: npm run format:check
4142
- run: npm run lint
4243
- run: npm run typecheck
4344
- run: npm test

‎.gitignore‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ ct-state.json
1515
# Generated typed client (regenerated from the live OpenAPI spec)
1616
src/api/schema.d.ts
1717

18-
# Test/coverage output
19-
coverage/
18+
# Test/coverage output — ROOT-anchored: a bare `coverage/` also matches `src/coverage/`
19+
# (the `ct coverage` report module, #103) and would silently drop it from every commit.
20+
/coverage/
2021
.vitest/
2122

2223
# MkDocs output for docs/handbuch/ (built by .github/workflows/docs.yml, never committed)
2324
site/
25+
# …and the venv docs/README.md tells you to create here to build the section locally
26+
.venv-docs/

‎README.md‎

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ code, and reconcile it against the ChurchTools API with Terraform-style
1515
A ChurchTools instance's structure is normally maintained by clicking. That
1616
works — until you need to answer questions clicking cannot:
1717

18-
| Clicking | With `ct` |
19-
| --- | --- |
20-
| "Who changed this group's rights, and why?" | `git log`, and the PR that changed it |
21-
| "Set up the next campus like the last one" | Call the same blueprint function again |
22-
| "Try it somewhere safe first" | `ct plan --env dev` → `ct apply --env dev` → promote |
23-
| "Has anyone edited this by hand?" | `ct plan` reports drift against the last known state |
24-
| "What will this actually change?" | `ct plan` prints it before anything is written |
18+
| Clicking | With `ct` |
19+
| ------------------------------------------- | ---------------------------------------------------- |
20+
| "Who changed this group's rights, and why?" | `git log`, and the PR that changed it |
21+
| "Set up the next campus like the last one" | Call the same blueprint function again |
22+
| "Try it somewhere safe first" | `ct plan --env dev` → `ct apply --env dev` → promote |
23+
| "Has anyone edited this by hand?" | `ct plan` reports drift against the last known state |
24+
| "What will this actually change?" | `ct plan` prints it before anything is written |
2525

2626
## Show me
2727

@@ -101,11 +101,13 @@ commands.
101101
ct auth login --host https://mychurch.church.tools --token <personal-login-token>
102102
ct auth status # who am I?
103103

104-
ct get groups # JSON to stdout — pipe into jq
104+
ct get groups # JSON to stdout — pipe into jq (every page, not just the first)
105105
ct adopt campus 0 # bring ONE existing resource under management
106+
ct coverage # what the instance has that the config does not manage
106107
ct state list # what is managed
107108
ct plan # diff the config against ChurchTools (read-only)
108109
ct apply # create + update in dependency order (confirm + backup first)
110+
ct refresh --group <key> # make ChurchTools re-evaluate one auto-group now
109111
```
110112

111113
`apply` reconciles **creates and updates** only, saving state after each action
@@ -116,23 +118,29 @@ confirmation — and a declaration marked `preventDestroy: true` blocks even tha
116118

117119
## What it manages
118120

119-
| Resource | DSL | Guide |
120-
| --- | --- | --- |
121-
| Campuses | `ct.campus` | [config guide](docs/configuration.md) |
122-
| Groups (fields, campus, multi-parent hierarchy) | `ct.group` | [config guide](docs/configuration.md) |
123-
| Group types, roles, age/target groups, relationship types, person statuses | `ct.groupType`, `ct.roleDefinition`, `ct.ageGroup`, `ct.targetGroup`, `ct.relationshipType`, `ct.personStatus` | reusable building blocks |
124-
| Permissions (group-role, group-type-role, person-status) | `ct.groupRole`, `ct.groupTypeRole`, `ct.status` | [permissions](docs/handbuch/permissions.md) |
125-
| Auto-groups (dynamic groups) | the `dynamic` block on a group | [dynamic groups](docs/handbuch/dynamic-groups.md) |
126-
| Repeated structure, parametrized | a plain function over the DSL | [blueprints](docs/handbuch/blueprints.md) |
121+
| Resource | DSL | Guide |
122+
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
123+
| Campuses | `ct.campus` | [config guide](docs/configuration.md) |
124+
| Groups (fields, campus, multi-parent hierarchy) | `ct.group` | [config guide](docs/configuration.md) |
125+
| Group types, roles, age/target groups, relationship types, person statuses | `ct.groupType`, `ct.roleDefinition`, `ct.ageGroup`, `ct.targetGroup`, `ct.relationshipType`, `ct.personStatus` | reusable building blocks |
126+
| Permissions (group-role, group-type-role, person-status) | `ct.groupRole`, `ct.groupTypeRole`, `ct.status` | [permissions](docs/handbuch/permissions.md) |
127+
| Auto-groups (dynamic groups) | the `dynamic` block on a group | [dynamic groups](docs/handbuch/dynamic-groups.md) |
128+
| Repeated structure, parametrized | a plain function over the DSL | [blueprints](docs/handbuch/blueprints.md) |
127129

128130
Read-only by design: the person master-data model, security levels and
129-
custom-field *definitions* (`ct get person-masterdata`, `ct get data-fields`) —
131+
custom-field _definitions_ (`ct get person-masterdata`, `ct get data-fields`) —
130132
schema in scope, per-record values never. See
131133
[field definitions](docs/handbuch/field-definitions.md).
132134

133135
References are logical throughout: `groupType: "ministry_team"` resolves to that
134136
instance's id at plan time, so the same config drives a dev and a prod instance
135-
unchanged. Numeric ids remain an escape hatch everywhere.
137+
unchanged. Numeric ids remain an escape hatch everywhere — and where one is left
138+
in place, `ct` says so rather than letting a host-specific id travel silently to
139+
another instance.
140+
141+
`ct coverage` answers the other direction: what exists on the instance that the
142+
config does not manage, and which of it could be declared today (per group _and_
143+
role, with the blocking scope dimension named). `--json` makes it a CI gate.
136144

137145
## Environments and CI
138146

@@ -166,10 +174,10 @@ ct apply --env prod # protected env: type the env name to confirm
166174

167175
## Two-repo model
168176

169-
| Repo | Contents |
170-
| --- | --- |
171-
| **`eqrm/ct-cli`** (this repo) | The tool: CLI, API client, plan/apply engine. Generic, reusable. |
172-
| *your config repo* (private) | Your instance's desired-state config + state files. Depends on this tool. |
177+
| Repo | Contents |
178+
| ----------------------------- | ------------------------------------------------------------------------- |
179+
| **`eqrm/ct-cli`** (this repo) | The tool: CLI, API client, plan/apply engine. Generic, reusable. |
180+
| _your config repo_ (private) | Your instance's desired-state config + state files. Depends on this tool. |
173181

174182
Like Terraform, the tool never lives in the same repo as the infra config — the config
175183
repo holds an organisation's actual structure and stays private. This repo is the tool

‎docs/README.md‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ dynamic groups and field definitions behave, independent of any one instance.
99
These pages are published into a wider ChurchTools Handbuch, so they carry
1010
`sources:` frontmatter and are gated by the staleness checker (#89).
1111

12-
| Page | About |
13-
| --- | --- |
14-
| [`handbuch/index.md`](handbuch/index.md) | Section overview |
15-
| [`handbuch/permissions.md`](handbuch/permissions.md) | Grant domains, `domainId` semantics, scope resolution |
16-
| [`handbuch/dynamic-groups.md`](handbuch/dynamic-groups.md) | Auto-groups, the ChurchQuery DSL, portable rulesets |
12+
| Page | About |
13+
| ---------------------------------------------------------------- | ------------------------------------------------------------- |
14+
| [`handbuch/index.md`](handbuch/index.md) | Section overview |
15+
| [`handbuch/permissions.md`](handbuch/permissions.md) | Grant domains, `domainId` semantics, scope resolution |
16+
| [`handbuch/dynamic-groups.md`](handbuch/dynamic-groups.md) | Auto-groups, the ChurchQuery DSL, portable rulesets |
1717
| [`handbuch/field-definitions.md`](handbuch/field-definitions.md) | Person master data, security levels, custom-field definitions |
18-
| [`handbuch/blueprints.md`](handbuch/blueprints.md) | Parametrized, reusable structure |
18+
| [`handbuch/blueprints.md`](handbuch/blueprints.md) | Parametrized, reusable structure |
1919

2020
**A page publishes only if it lives under `handbuch/` and is reachable from
2121
`handbuch/mkdocs.yml`'s nav.** Everything else in `docs/` stays invisible.
@@ -48,9 +48,9 @@ A page with no code behaviour to track declares `sources: []` plus a
4848

4949
## Everything else — developer- and operator-facing, unpublished
5050

51-
| Page | About |
52-
| --- | --- |
53-
| [`api-coverage.md`](api-coverage.md) | Which ChurchTools endpoints support which CRUD verbs |
54-
| [`group-field-decisions.md`](group-field-decisions.md) | Which group fields are managed vs. left to the CT UI, and why |
51+
| Page | About |
52+
| -------------------------------------------------------- | --------------------------------------------------------------------- |
53+
| [`api-coverage.md`](api-coverage.md) | Which ChurchTools endpoints support which CRUD verbs |
54+
| [`group-field-decisions.md`](group-field-decisions.md) | Which group fields are managed vs. left to the CT UI, and why |
5555
| [`runbook-manual-surface.md`](runbook-manual-surface.md) | What `ct` cannot automate — API gaps and the manual steps around them |
56-
| `superpowers/` | Historical implementation plans; kept as a record, never published |
56+
| `superpowers/` | Historical implementation plans; kept as a record, never published |

0 commit comments

Comments
 (0)