Skip to content

fix: decompose high-CRAP functions to reduce complexity#478

Merged
gvauter merged 4 commits intocomplytime:mainfrom
gvauter:fix/crap-export-coverage
Apr 20, 2026
Merged

fix: decompose high-CRAP functions to reduce complexity#478
gvauter merged 4 commits intocomplytime:mainfrom
gvauter:fix/crap-export-coverage

Conversation

@gvauter
Copy link
Copy Markdown
Member

@gvauter gvauter commented Apr 16, 2026

Summary

Decomposes 10 functions on main that exceed the CRAP threshold of 30, bringing all of them well below the limit. The primary strategy is aggressive extraction of focused helper functions to reduce cyclomatic complexity to ≤ 4 (which guarantees CRAP < 30 regardless of coverage), supplemented by targeted unit tests.

Function Before (complexity) After (complexity) After CRAP
(*scanOptions).run 18 4 4.0
(*generateOptions).run 18 3 3.0
(*getOptions).run 8 2 2.0
(*providersOptions).run 8 4 5.3
(*initOptions).run 28.1
(*listOptions).run 6.1
(*Manager).RouteGenerate 8 8 8.2
(*Manager).RouteScan 6 6 6.2
OpenSCAP (*PluginServer).Generate 9 2 2.1
OpenSCAP (*PluginServer).Scan 18 4 11.5

Overall CRAPload: 84 → 56.

Related Issues

  • Addresses CRAP violations flagged by the gaze crap CI check

Review Hints

  • Best reviewed commit-by-commit in order:

    1. 8204be5 — CLI decomposition (scan.go, generate.go, get.go, providers.go, new cli_test.go): This is the largest commit. Each run method now delegates to small, single-purpose helpers. No behavioral changes.
    2. 0f7242e — OpenSCAP plugin decomposition (server.go, server_test.go): Same pattern applied to the OpenSCAP plugin module. Separate Go module, so fully isolated.
    3. 13c0c37 — Plugin manager test injection (manager.go, export_test.go, manager_test.go): Adds a mockPlugin field to LoadedPlugin so tests can inject a mock Plugin without real binaries. Adds table-driven tests for RouteGenerate and RouteScan.
  • All changes are pure refactoring — no behavioral changes, no new features, no API changes.

  • To verify locally:

    go test ./cmd/complyctl/... ./internal/... ./pkg/...
    cd cmd/openscap-plugin && go test ./...

gvauter added 2 commits April 16, 2026 17:04
Reduce cyclomatic complexity of the run methods for scanOptions,
generateOptions, getOptions, and providersOptions by extracting
focused helper functions. This brings their CRAP scores below the
CI threshold of 30.

- scanOptions.run: complexity 18 → 4
- generateOptions.run: complexity 18 → 3
- getOptions.run: complexity 8 → 2
- providersOptions.run: complexity 8 → 4

Add cli_test.go with unit tests covering early-exit paths and
helper functions (filterTargetsForPolicy, extractReqToControlMap).

Signed-off-by: George Vauter <gvauter@redhat.com>
Made-with: Cursor
Extract helper functions from PluginServer.Generate and
PluginServer.Scan to reduce cyclomatic complexity below the
CRAP threshold of 30.

- Generate: complexity 9 → 2
- Scan: complexity 18 → 4

Add tests for parseARFFile, buildAssessmentsFromARF,
findOVALCheckContentRef, and other extracted helpers.

Signed-off-by: George Vauter <gvauter@redhat.com>
Made-with: Cursor
@gvauter gvauter requested review from a team as code owners April 16, 2026 21:13
Add mockPlugin field to LoadedPlugin with GetClient() accessor to
enable test injection without requiring real plugin binaries. Add
NewMockLoadedPlugin helper and comprehensive tests for Manager
RouteGenerate and RouteScan methods covering specific plugin,
broadcast, unknown evaluator, and error scenarios.

- RouteGenerate CRAP: 8.2 (below 30)
- RouteScan CRAP: 6.2 (below 30)

Signed-off-by: George Vauter <gvauter@redhat.com>
Made-with: Cursor
Signed-off-by: George Vauter <gvauter@redhat.com>
Made-with: Cursor
@gvauter gvauter force-pushed the fix/crap-export-coverage branch from 13c0c37 to 74cfca7 Compare April 16, 2026 21:22
Copy link
Copy Markdown
Contributor

@marcusburghardt marcusburghardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-assisted review — two non-blocking nits flagged inline for future consideration.

Comment thread pkg/plugin/manager.go Outdated
Client *Client
Info PluginInfo
Client *Client
mockPlugin Plugin // injected during tests; nil in production
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (non-blocking): This adds a test-only field to a production struct. An alternative would be to define a PluginClient interface at the Manager level and inject mocks through that, keeping LoadedPlugin free of test-only fields. This would better align with Principle II (Simplicity & Isolation) by separating test and production concerns.

Not in scope for this PR — just flagging for a potential follow-up.

Comment thread cmd/complyctl/cli/scan.go Outdated
"slices"
"time"

"github.com/gemaraproj/go-gemara"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (non-blocking): This introduces a direct import of go-gemara in scan.go for the gemara.EvaluationLog type used in the extracted report helpers. Previously, this type was only accessed transitively through the output package. Consider whether the report-writing helpers (writePrettyReport, writeSARIFReport, writeOSCALReport) could accept a narrower interface or remain closer to the output package to avoid spreading the direct dependency.

Not in scope for this PR — just a coupling observation.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @marcusburghardt - I've added an additional commit to address these comments.

…ports

Replace the test-only mockPlugin field in LoadedPlugin with an
interface-typed Client field (Plugin instead of *Client). This
removes the if-branch from GetClient(), eliminating the CRAP
regression (2.148 -> 1.0) and keeping test concerns out of the
production struct.

Remove the direct go-gemara import from scan.go by refactoring
the write helpers (writePrettyReport, writeSARIFReport,
writeOSCALReport) to accept *output.Evaluator and call
GemaraLog() internally, keeping the gemara dependency
encapsulated in the output package.

Signed-off-by: George Vauter <gvauter@redhat.com>
Made-with: Cursor
Signed-off-by: George Vauter <gvauter@redhat.com>
Copy link
Copy Markdown
Contributor

@marcusburghardt marcusburghardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We can update the baseline in a separate PR. Thanks for addressing this @gvauter

Copy link
Copy Markdown
Member

@jpower432 jpower432 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

"github.com/complytime/complyctl/internal/policy"
)

func chdirTemp(t *testing.T) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think testing.T has a function for this t.Chdir()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix in an upcoming PR. TY!

@gvauter gvauter merged commit 6dac951 into complytime:main Apr 20, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants