## 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) --------- Co-authored-by: mhoennig <michael@hoennig.de> Reviewed-on: #115
5.2 KiB
WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
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 — 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).