layout

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package layout builds this module's package import graph so tests can assert the tier boundaries the repository layout claims.

Why

Decision record 0044 arranges packages into tiers and says which tier may import which. A layout that is only a directory arrangement is a comment: nothing stops a future import from pointing the wrong way, and the tree then asserts a boundary the compiler does not enforce, which misleads more than a flat tree would. The boundary needs a gate.

golangci-lint cannot be that gate here. The workflow runs it with --issues-exit-code=0 and only-new-issues, so a depguard rule would report a violation without failing the build. Tests do fail the build, so the rules live in this package's tests instead, and this file supplies them the graph: package edges from go list, the same edges collapsed to the directory units a tier is assigned to, strongly connected components, and transitive reachability.

The package deliberately holds no rules. What may import what is a statement about this repository and belongs in the test beside the list of exceptions it is ratcheting down; this file only answers questions about the graph.

References

  • Decision record 0044: docs/research/decisions/0044-repository-layout.md
  • Decision record 0001: docs/research/decisions/0001-architecture.md
  • Plan of record: docs/research/implementation_plan.md (section 1, package layout)

Index

Constants

This section is empty.

Variables

View Source
var ErrGoList = fmt.Errorf("layout: go list failed")

ErrGoList reports that the go command could not enumerate the module.

Functions

func Cycles

func Cycles(g map[string][]string) [][]string

Cycles returns the strongly connected components of size greater than one in the unit graph, each sorted, outermost sorted for a stable message. A unit in such a component cannot be assigned to a tier, because part of it sits above another part.

func Unit

func Unit(pkg string) string

Unit is the directory a tier is assigned to: the first path element, except under a namespace, where it is the first two.

Types

type Graph

type Graph struct {
	Module  string
	Imports map[string][]string
	// External records imports outside this module, which LoadRepo needs to
	// resolve edges from the server module back into the library.
	External map[string][]string
}

Graph is this module's package import graph, keyed by package path relative to the module path ("mdm", "ddm/predicate"). Only in-module imports are recorded; the standard library and third-party dependencies are not part of a tier question.

func Load

func Load(dir string) (*Graph, error)

Load runs go list in dir and returns the in-module import graph.

func LoadRepo

func LoadRepo(root string) (*Graph, error)

LoadRepo returns one graph spanning every module in the repository. The server is its own module, so a single go list would stop at the library and the tier tests would quietly cover half the tree. Server packages keep their directory as a prefix ("server/service"), so a package's key is its path from the repository root either way.

func (*Graph) Packages

func (g *Graph) Packages() []string

Packages returns every in-module package path, sorted.

func (*Graph) Reaches

func (g *Graph) Reaches(from string) []string

Reaches returns every package transitively imported by from, sorted. A package does not reach itself unless the graph says so.

func (*Graph) UnitGraph

func (g *Graph) UnitGraph() map[string][]string

UnitGraph collapses the package graph onto units, dropping self edges.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL