015-module-import-boundaries.md 2.3 KB

Module Import Boundaries

Intent

https://github.com/external-secrets/external-secrets/issues/5494 introduced the split of our go module into multiple go modules.

The module structure has been exercised and can now be moved to a design document.

Principles

  • Packages in apis are for CRDs and a limited set of interfaces. They may import the standard library, packages in the apis module and an explicit allowlist of API dependencies (for example, k8s.io modules).
  • Packages in runtime are common utilities. They contain shared code (validation utilities, webhook helpers, metrics/logging tooling, ...). They may import the standard library, packages in apis or runtime, and an explicit allowlist of runtime dependencies. As the dependencies are included in provider modules, the addition of a module into a runtime package needs to be carefully analysed.
  • Packages in pkg are for the core orchestration. It's where the controllers and binary reside. They can depend on apis and runtime.
  • Packages in e2e are for the e2e testing, and can require any of the above packages. They are built in isolation, so they should not leak dependencies everywhere.
  • Transitive dependencies are not evaluated: If some module imports the whole world, then we will have to deal with it.

Enforcement

In a first stage, we use code reviews to highlight discrepancies and preserve the module layout expressed above.

In a second stage, we enable golangci-lint's existing depguard linter for apis and runtime; pkg and e2e remain review-only. It defines strict rules selected by path like **/apis/**/*.go or **/runtime/**/*.go. Each rule allows $gostd, the module's own package prefix, and the package prefixes belonging to its allowed current direct dependencies.

Depguard analyzes import declarations rather than the module graph, so it checks only direct imports. The file globs include tests. An import such as an AWS or Oracle SDK from a runtime test therefore fails the existing make lint and make reviewable gates without constraining dependencies loaded transitively by an allowed package.

The existing go mod tidy and make check-diff flow remains responsible for removing stale go.mod requirements. No new command, dependency, or CI job is needed.