go-arch-lint Documentation

repository·master·Indexed 19 days ago

https://github.com/fe3dback/go-arch-lint

A tool for enforcing project structure and validating top-level architectural layers in Go projects. It maps Go packages to semantic components and checks dependencies against a user-defined configuration file (.go-arch-lint.yml). Features include architectural violation checks, generation of flow and dependency injection (DI) graphs, mapping of components to source files, and JSON schema export for configuration validation.

Tokens
3.1K
Snippets
14
Records
15
Agent score
68%

What's inside go-arch-lint

  1. Generate architecture graphs with `go-arch-lint graph`

    master

    You can generate visual architecture overviews of your project's dependencies using the graph command. The tool supports two primary graph types: flow (default) and di.

    • flow graph: Represents a reverse dependency injection model, which closely approximates the code execution flow.
    • di graph: Shows actual component dependencies (the opposite of the flow graph).
    # Generate a default flow graph
    go-arch-lint graph
    
    # Generate a dependency injection (DI) graph
    go-arch-lint graph --type di
  2. Install and run go-arch-lint

    master

    You can install and run the linter using Docker, Go source, or precompiled binaries.

    Via Docker

    Run the linter using a Docker container, mounting your current directory to /app:

    docker run --rm -v ${PWD}:/app fe3dback/go-arch-lint:latest-stable-release check --project-path /app

    From source

    Requires Go 1.25 or higher:

    go install github.com/fe3dback/go-arch-lint@latest
    
    # Run the check on a specific path
    go-arch-lint check --project-path ~/code/my-project
    
    # Or run it from within the project directory
    cd ~/code/my-project
    go-arch-lint check

    Precompiled binaries

    Download binaries from the official releases page.

    go install github.com/fe3dback/go-arch-lint@latest
  3. Workflow for adding the linter to an existing project

    master

    When introducing go-arch-lint to a legacy codebase, follow these steps to manage technical debt:

    1. Assess current state: Observe the existing package structure.
    2. Define ideal state: Create a .go-arch-lint.yml file describing how the architecture should look.
    3. Legalize existing issues: The linter will likely find many violations. Instead of fixing them immediately, add them to your config and mark them with a todo label to prevent them from blocking CI.
    4. Refactor: Gradually fix the code violations during regular maintenance or technical debt sprints.
    5. Clean up: Once the code matches the desired architecture, remove the todo labels from the config.
  4. Configure project architecture with YAML

    master

    Define your project's architectural layers (components) and their allowed dependencies in a .go-arch-lint.yml file. The linter uses these rules to validate that code dependencies follow your intended design (e.g., Clean Architecture).

    Key configuration concepts:

    • workdir: The directory where the linter should scan.
    • components: Maps Go packages to semantic names using glob patterns (e.g., * for one level, ** for many levels).
    • commonComponents: A list of components that are shared or available globally.
    • deps: Defines the allowed dependency flow using mayDependOn for each component.

    Example configuration:

    version: 3
    workdir: internal
    components:
      handler:    { in: handlers/* }           # wildcard one level
      service:    { in: services/** }          # wildcard many levels
      repository: { in: domain/*/repository }  # wildcard DDD repositories
      model:      { in: models }               # match exactly one package
    
    commonComponents:
      - models
    
    deps:
      handler:
        mayDependOn:
          - service
      service:
        mayDependOn:
          - repository
    version: 3
    workdir: internal
    components:
      handler:    { in: handlers/* }
      service:    { in: services/** }
      repository: { in: domain/*/repository }
      model:      { in: models }
    
    commonComponents:
      - models
    
    deps:
      handler:
        mayDependOn:
          - service
      service:
        mayDependOn:
          - repository
  5. Focus a graph on a specific component

    master

    To avoid visual clutter in large projects, use the --focus flag to display only a single component and all of its recursive dependencies. The string provided must match a component name defined in your architecture file exactly.

    go-arch-lint graph --focus operations
  6. Reference the `go-arch-lint graph` CLI flags

    master

    The graph command (aliases: g) accepts the following flags to customize the output:

    FlagDescription
    --arch-file stringPath to the architecture configuration file (default: .go-arch-lint.yml)
    --focus stringRender only the specified component and its recursive dependencies (must match component name exactly)
    --include-vendorsInclude vendor dependencies (from the canUse block) in the graph
    --out stringPath to the output SVG file (default: ./go-arch-lint-graph.svg)
    --project-path stringAbsolute path to the project directory containing the .go-arch-lint.yml file (default: ./)
    --type stringThe type of graph to render: flow or di (default: flow)
    Usage:
      go-arch-lint graph [flags]
    
    Aliases:
      graph, g
    
    Flags:
          --arch-file string      arch file path (default ".go-arch-lint.yml")
          --focus string          render only specified component (should match component name exactly)
      -h, --help                  help for graph
          -r, --include-vendors       include vendor dependencies (from "canUse" block)?
          --out string            svg graph output file (default "./go-arch-lint-graph.svg")
          --project-path string   absolute path to project directory (where '.go-arch-lint.yml' is located) (default "./")
          -t, --type string           render graph type [flow,di] (default "flow")
  7. Configure global allow rules and analysis settings

    master

    The allow section provides global configuration for the linter's behavior across the entire project.

    Global Settings

    • . depOnAnyVendor: (bool) If true, allows any project file to import any vendor code.
    • . deepScan: (bool) Enables advanced AST code analysis. Defaults to true in v3+.
    • . ignoreNotFoundComponents: (bool) If true, ignores components that are not found. Defaults to false.

    Project Scope

    • workdir: (str) The relative directory to start the analysis.
    • exclude: ([]str) A list of relative directory paths to exclude from analysis.
    • excludeFiles: ([]str) A list of regular expression rules for file names. Files matching these patterns and their associated packages will be excluded from analysis.
    version: 3
    
    workdir: .
    
    allow:
      deepScan: true
      depOnAnyVendor: false
    
    exclude: ["vendor", "testdata"]
    excludeFiles: ["_test\.go$"]
    
    commonComponents: ["shared_utils"]
    commonVendors: ["standard_lib"]
  8. Define components and vendor libraries in the archfile

    master

    The archfile organizes your Go project into logical abstractions called components and identifies external dependencies via vendors.

    Components

    components is a required map where each entry defines a logical layer of your application. One component can represent one or more Go packages.

    • %name%: The unique name of the component.
    • . in: A string or list of strings specifying the relative directory names where the component's code resides. Supports glob masking (e.g., src/*/engine/**).

    Vendors

    vendors is a map used to define external libraries (from go.mod).

    • %name%: The name of the vendor component.
    • . in: A string or list of strings specifying the import paths of the vendor libraries. Supports glob masking (e.g., github.com/abc/*/engine/**).
    version: 3
    
    components:
      engine:
        in: src/engine/**
    
    vendors:
      external_lib:
        in: github.com/external/lib
  9. Set dependency rules and allow-lists

    master

    The deps section is a required map used to enforce architectural boundaries between components and vendors.

    For each component name defined in the components section, you can specify:

    • . anyVendorDeps: (bool) If true, this component can import any vendor code.
    • . anyProjectDeps: (bool) If true, this component can import any other project code (useful for DI or main components).
    • . mayDependOn: ([]str) A list of component names that this component is allowed to import.
    • . canUse: ([]str) A list of vendor names that this component is allowed to import.
    • . deepScan: (bool) Overrides the global allow.deepScan setting for this specific component.
    version: 3
    
    components:
      api:
        in: cmd/api
      service:
        in: internal/service
    
    deps:
      api:
        mayDependOn: ["service"]
        canUse: ["external_lib"]
      service:
        anyVendorDeps: true
  10. View archfile mapping to source files

    master

    The mapping command shows how the packages defined in your archfile map to actual source files in your project.

    There are two available modes:

    1. list (default): A flat list of package names and their corresponding paths.
    2. grouped (via --scheme grouped): Groups the source paths under their respective component names.

    You can also output this mapping data in JSON format using the --json flag.

    # Default list mode
    go-arch-lint mapping
    
    # Grouped mode
    go-arch-lint mapping --scheme grouped
    
    # JSON output
    go-arch-lint mapping --json