The Forgejo workflow export (RFC 0006) held three methods above the Mutation-CRAP limit of 15, all by complexity:
Method
Mutation-CRAP
Complexity
What it did in one body
ForgejoWorkflowExporter.settingNotes
31.63
27
thirteen checks of what a workflow cannot carry over, from the container to $branch
ExportForgejoCommand.call
21.13
13
found the repository, converted, reported, and wrote, each with its own exit
ForgejoWorkflowExporter.job
19.15
19
collected the notes, wrote the job's header, and wrote its steps
A score is never below the complexity, so no test could bring them under 15.
This is one of seven groups the methods above 15 fall into; each group gets its own PR.
Non-Goals
No change in the exported workflows, the notes and their order, or the command's output and exit codes.
The Scenarios
Feature: What a workflow cannot carry over is named
Scenario#115.01: The werkdock notes name the sandbox's rootfs and its env, and a shared Gradle home only while it is enabled
So that a disabled sandbox is not reported as something to move to a runner.
Given a definition with an enabled werkdock sandbox, a rootfs URL, a Gradle home and an env, and one with only a Gradle home
When the configuration is exported
Then the first names the rootfs file, the env keys, and the Gradle home, in this order
job collects the notes and writes jobHeader — runner, predecessor, branches, container, env, time limit — and jobSteps — checkout, clean, build, artifacts.
ExportForgejoCommand.call reads as its steps: repositoryRoot, exportOf, refusedAsStrict, then printAll or write.
A usage error is one UsageError thrown where it is found and answered in one place, with exit 2 as before.
Measured with PIT as the nightly build runs it, before Scenario#115.01 was added:
Method
Before
After
ForgejoWorkflowExporter.settingNotes
31.63
1
ExportForgejoCommand.call
21.13
3
ForgejoWorkflowExporter.job
19.15
4.37
ForgejoWorkflowExporter.werkdockNotes
—
10.86
ForgejoWorkflowExporter.jobHeader
—
10.01
ForgejoWorkflowExporter.dockerNotes
—
9
ForgejoWorkflowExporter.stepNotes
—
8
ForgejoWorkflowExporter.jobSteps
—
7
ForgejoWorkflowExporter.hostNotes
—
5
ExportForgejoCommand.exportOf
—
4.25
The highest score left in the export is ForgejoWorkflowExporter.scalar at 14.17, unchanged; none is INCONCLUSIVE.
The gate maxMutationCrap stays at 32: the highest score left in Werkator is SystemHealth.assess$diskUtilization at 31.28.
Additional Changes
Version 1.35.1 with its release note.
Follow-up PRs
The other six groups above 15, one PR each:
Health verdict and System page view: SystemHealth.assess$diskUtilization (31.28), SystemMetricsView.from (25.28), HistoryPeaks.of (16.38).
Git and Gitea access: GitService.authenticated (30.12), GiteaClient.readOpenPullRequests (20.78).
Sizing advice: CapacitySizing.ram (26.87), column (26.83), disk (21.19), UiFormats.adviceLabel (15.55).
## The Problem
The Forgejo workflow export (RFC 0006) held three methods above the Mutation-CRAP limit of 15, all by complexity:
| Method | Mutation-CRAP | Complexity | What it did in one body |
| -------------------------------------- | ------------- | ---------- | ------------------------------------------------------------------------------------- |
| `ForgejoWorkflowExporter.settingNotes` | 31.63 | 27 | thirteen checks of what a workflow cannot carry over, from the container to `$branch` |
| `ExportForgejoCommand.call` | 21.13 | 13 | found the repository, converted, reported, and wrote, each with its own exit |
| `ForgejoWorkflowExporter.job` | 19.15 | 19 | collected the notes, wrote the job's header, and wrote its steps |
A score is never below the complexity, so no test could bring them under 15.
This is one of seven groups the methods above 15 fall into; each group gets its own PR.
## Non-Goals
- No change in the exported workflows, the notes and their order, or the command's output and exit codes.
## The Scenarios
### Feature: What a workflow cannot carry over is named
#### Scenario#115.01: The werkdock notes name the sandbox's rootfs and its env, and a shared Gradle home only while it is enabled
So that a disabled sandbox is not reported as something to move to a runner.
- **Given** a definition with an enabled werkdock sandbox, a rootfs URL, a Gradle home and an env, and one with only a Gradle home
- **When** the configuration is exported
- **Then** the first names the rootfs file, the env keys, and the Gradle home, in this order
- **And** the second names nothing
##### Verified by
- [ForgejoWorkflowExporterUnitTest](../../src/test/kotlin/de/hoennig/werkator/forgejo/ForgejoWorkflowExporterUnitTest.kt) — Scenario#115.01
- Everything else of the export keeps its tests of PR#92 and PR#114, unchanged.
## The Solution
`settingNotes` asks topic by topic, in the order of the configuration reference, so the notes keep their order:
| Topic | Notes |
| --------------- | --------------------------------------------------------- |
| `dockerNotes` | `dockerfile`, `network`, `socket` |
| `werkdockNotes` | the sandbox's rootfs, `env`, `gradleHome` |
| `logNotes` | `stdoutLog`/`stderrLog` |
| `hostNotes` | `requirePullRequest`, `statusContext`, `restartsInstance` |
| `stepNotes` | `timeout`, a multi-line command, `$branch` |
`job` collects the notes and writes `jobHeader` — runner, predecessor, branches, container, env, time limit — and `jobSteps` — checkout, clean, build, artifacts.
`ExportForgejoCommand.call` reads as its steps: `repositoryRoot`, `exportOf`, `refusedAsStrict`, then `printAll` or `write`.
A usage error is one `UsageError` thrown where it is found and answered in one place, with exit 2 as before.
Measured with PIT as the nightly build runs it, before Scenario#115.01 was added:
| Method | Before | After |
| --------------------------------------- | ------ | ----- |
| `ForgejoWorkflowExporter.settingNotes` | 31.63 | 1 |
| `ExportForgejoCommand.call` | 21.13 | 3 |
| `ForgejoWorkflowExporter.job` | 19.15 | 4.37 |
| `ForgejoWorkflowExporter.werkdockNotes` | — | 10.86 |
| `ForgejoWorkflowExporter.jobHeader` | — | 10.01 |
| `ForgejoWorkflowExporter.dockerNotes` | — | 9 |
| `ForgejoWorkflowExporter.stepNotes` | — | 8 |
| `ForgejoWorkflowExporter.jobSteps` | — | 7 |
| `ForgejoWorkflowExporter.hostNotes` | — | 5 |
| `ExportForgejoCommand.exportOf` | — | 4.25 |
The highest score left in the export is `ForgejoWorkflowExporter.scalar` at 14.17, unchanged; none is `INCONCLUSIVE`.
The gate `maxMutationCrap` stays at 32: the highest score left in Werkator is `SystemHealth.assess$diskUtilization` at 31.28.
## Additional Changes
- Version 1.35.1 with its release note.
## Follow-up PRs
The other six groups above 15, one PR each:
- Health verdict and System page view: `SystemHealth.assess$diskUtilization` (31.28), `SystemMetricsView.from` (25.28), `HistoryPeaks.of` (16.38).
- Git and Gitea access: `GitService.authenticated` (30.12), `GiteaClient.readOpenPullRequests` (20.78).
- Sizing advice: `CapacitySizing.ram` (26.87), `column` (26.83), `disk` (21.19), `UiFormats.adviceLabel` (15.55).
- Installation: `NginxProxyManager.resolveSettings` (27.44), `InitCommand.createSystemdFiles` (17.40).
- The watcher's triggering and retention: `ConfigLoader.isTriggered` (26.16), `FileArtifactStore.prune` (23.50).
- Build lists and the repository line: `BuildsApiController.current` (22.15), `UiFormats.repoStatusLine` (16.03), `UiController.baseModel` (15.69).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
mi
changed title from WIP: Forgejo export notes, job and command split by topic (v1.35.1) to Forgejo export notes asked topic by topic, a job written as header and steps, export:forgejo in steps (v1.35.1)2026-10-04 21:13:55 +02:00
settingNotes (31.63), ExportForgejoCommand.call (21.13) and job (19.15)
were above the Mutation-CRAP limit of 15 by complexity alone.
- settingNotes: dockerNotes, werkdockNotes, logNotes, hostNotes,
stepNotes, in the order of the configuration reference.
- job: jobHeader and jobSteps.
- export:forgejo: repositoryRoot, exportOf, refusedAsStrict, printAll or
write; usage errors answered in one place.
- Scenario#115.01 for the werkdock notes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi
merged commit 81ab917e64 into main2026-10-04 21:22:22 +02:00
mi
deleted branch mihoe/forgejo-export-by-topic2026-10-04 21:22:22 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The Problem
The Forgejo workflow export (RFC 0006) held three methods above the Mutation-CRAP limit of 15, all by complexity:
ForgejoWorkflowExporter.settingNotes$branchExportForgejoCommand.callForgejoWorkflowExporter.jobA score is never below the complexity, so no test could bring them under 15.
This is one of seven groups the methods above 15 fall into; each group gets its own PR.
Non-Goals
The Scenarios
Feature: What a workflow cannot carry over is named
Scenario#115.01: The werkdock notes name the sandbox's rootfs and its env, and a shared Gradle home only while it is enabled
So that a disabled sandbox is not reported as something to move to a runner.
Verified by
The Solution
settingNotesasks topic by topic, in the order of the configuration reference, so the notes keep their order:dockerNotesdockerfile,network,socketwerkdockNotesenv,gradleHomelogNotesstdoutLog/stderrLoghostNotesrequirePullRequest,statusContext,restartsInstancestepNotestimeout, a multi-line command,$branchjobcollects the notes and writesjobHeader— runner, predecessor, branches, container, env, time limit — andjobSteps— checkout, clean, build, artifacts.ExportForgejoCommand.callreads as its steps:repositoryRoot,exportOf,refusedAsStrict, thenprintAllorwrite.A usage error is one
UsageErrorthrown where it is found and answered in one place, with exit 2 as before.Measured with PIT as the nightly build runs it, before Scenario#115.01 was added:
ForgejoWorkflowExporter.settingNotesExportForgejoCommand.callForgejoWorkflowExporter.jobForgejoWorkflowExporter.werkdockNotesForgejoWorkflowExporter.jobHeaderForgejoWorkflowExporter.dockerNotesForgejoWorkflowExporter.stepNotesForgejoWorkflowExporter.jobStepsForgejoWorkflowExporter.hostNotesExportForgejoCommand.exportOfThe highest score left in the export is
ForgejoWorkflowExporter.scalarat 14.17, unchanged; none isINCONCLUSIVE.The gate
maxMutationCrapstays at 32: the highest score left in Werkator isSystemHealth.assess$diskUtilizationat 31.28.Additional Changes
Follow-up PRs
The other six groups above 15, one PR each:
SystemHealth.assess$diskUtilization(31.28),SystemMetricsView.from(25.28),HistoryPeaks.of(16.38).GitService.authenticated(30.12),GiteaClient.readOpenPullRequests(20.78).CapacitySizing.ram(26.87),column(26.83),disk(21.19),UiFormats.adviceLabel(15.55).NginxProxyManager.resolveSettings(27.44),InitCommand.createSystemdFiles(17.40).ConfigLoader.isTriggered(26.16),FileArtifactStore.prune(23.50).BuildsApiController.current(22.15),UiFormats.repoStatusLine(16.03),UiController.baseModel(15.69).🤖 Generated with Claude Code
WIP: Forgejo export notes, job and command split by topic (v1.35.1)to Forgejo export notes asked topic by topic, a job written as header and steps, export:forgejo in steps (v1.35.1)