Skip to content

test(core): guard the framework against plugin imports - #9277

Merged
Startrekzky merged 3 commits into
mainfrom
feat/single-binary
Oct 30, 2026
Merged

Startrekzky merged 3 commits into
mainfrom
feat/single-binary

Conversation

@klesh

@klesh klesh commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Nothing enforced the dependency direction between the framework and the plugins, and two test files had already crossed it:

  • helpers/e2ehelper/data_flow_tester_test.go imported plugins/gitlab/{models,tasks}
  • server/services/blueprint_makeplan_v200_test.go imported plugins/org/tasks

This adds backend/core/layering_test.go, which reads the import graph of core/..., helpers/... and server/... — including _test.go files — with go list and fails on any plugins/ edge.

The only tolerated edge is the composition root: server may import the generated plugins/all registry, never an individual plugin. That is one explicit map entry, so any new exception has to be argued for in review.

The rule becomes load-bearing once plugins are compiled into the server binary by default (#9276): a single framework→plugin import links that plugin and its whole dependency tree into the core payload and defeats subset builds.

The two offending tests are made plugin-agnostic rather than allowlisted:

  • the e2ehelper example now uses local fixtures instead of gitlab's
  • the blueprint test builds its mocked org task option locally (the plugin is mocked, so the value only has to round-trip)

A third, long-failing assertion in the same package is corrected in the second commit.

Does this close any open issues?

Does not close #9276; it is the first prerequisite of it.

Refs #9276.

Screenshots

N/A

Other Information

Two deliberate choices worth a reviewer's attention:

  1. A Go test rather than a depguard rule. .golangci.yaml sets run.tests: false, so lint would not have seen either violation that actually existed — both were in _test.go files.
  2. The test opens every framework source file at the end so the Go test cache invalidates when an import is added elsewhere. Without that, a plain go test ./core would replay a cached PASS: I verified that adding a violation under helpers/ still reported (cached) ok for the core package before this was added.

The guard runs as part of make unit-test, because scripts/unit-test-go.sh already includes the core package.

The second commit fixes TestGetTableMetaData/dal_get_pk_column_names: GetPrimarykeyColumnNames has returned qualified table.column names since 8e915cd, and callers strip the prefix themselves (helpers/e2ehelper/data_flow_tester.go:316, helpers/srvhelper/scope_config_service_helper.go:74). The stale assertion went unnoticed because scripts/unit-test-go.sh filters out every package path matching e2e, which covers helpers/e2ehelper; that package needs a live E2E_DB_URL and therefore stays out of the DB-less unit-test job.

Verification:

go test ./core/ ./helpers/e2ehelper/ ./server/services/   # ok
go test ./core/... ./helpers/... ./server/...              # exit 0, no failures
gofmt -l                                                   # clean

klesh added 2 commits October 29, 2026 14:48
The dependency direction is plugins -> core/helpers, never the reverse.
Nothing enforced it, and two test files had already crossed the line:
helpers/e2ehelper imported plugins/gitlab and server/services imported
plugins/org.

Compiling plugins into the server binary makes the rule load-bearing: a
single framework->plugin import links that plugin and its whole dependency
tree into the core payload and defeats subset builds.

Add TestFrameworkDoesNotImportPlugins, which reads the import graph of
core/, helpers/ and server/ (including _test.go files) via `go list` and
fails on any plugins/ edge. server/ may only link the generated
plugins/all registry, which is encoded as one explicit exception.

Make the two offending tests plugin-agnostic: the e2ehelper example now
uses local fixtures, and the blueprint test builds its mocked org task
option locally.
GetPrimarykeyColumnNames has qualified every column with its table name
since 8e915cd ("feat: set project mapping by plugin org"), so the result
can be dropped into a join condition without colliding with a reserved
identifier. Callers that want the bare name strip the prefix themselves
(helpers/e2ehelper/data_flow_tester.go:316, and
helpers/srvhelper/scope_config_service_helper.go:74 checks the suffix).

The test still expected the unqualified names, so it had been failing. It
went unnoticed because scripts/unit-test-go.sh filters out every package
path matching `e2e`, which covers helpers/e2ehelper; the package needs a
live E2E_DB_URL, so it stays out of the DB-less unit-test job.

@Startrekzky Startrekzky left a comment

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.

LGTM

@Startrekzky
Startrekzky merged commit 2f3d07e into main Oct 30, 2026
11 checks passed
@Startrekzky
Startrekzky deleted the feat/single-binary branch October 30, 2026 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor][Build] Build the core and all plugins into a single binary by default

2 participants