Home

Awesome

Logo image

Linter used to enforce some good project structure and validate top level architecture (code layers)

Go Report Card go-recipes

Quick start

What exactly is project architecture?

You can imagine some simple architecture, for example classic onion part from "clean architecture":

Layouts example

And describe/declare it as semantic yaml linter config:

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

see config syntax for details.

And now linter will check all project code inside internal workdir and show warnings, when code violate this rules.

For best experience you can add linter into CI workflow

Example of broken code

Imagine some main.go, when we provide repository into handler and get some bad flow:

func main() {
  // ..
  repository := booksRepository.NewRepository()
  handler := booksHandler.NewHandler(
    service,
    repository, // !!!
  )
  // ..
}

Linter will easily found this issue:

Check stdout example

Install/Run

Wia Docker

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

other docker tags and versions

From sources

It require go 1.20+

go install github.com/fe3dback/go-arch-lint@latest
go-arch-lint check --project-path ~/code/my-project
# or
cd ~/code/my-project
go-arch-lint check

Precompiled binaries

see on releases page

IDE plugin for autocompletion and other help

<img src="https://user-images.githubusercontent.com/2073883/104641610-0f453900-56bb-11eb-8419-6d94fbcb4d2f.png" alt="jetbrains goland logo" align="left" width="80px" height="80px">

https://plugins.jetbrains.com/plugin/15423-goarchlint-file-support

Usage

How to add linter to existing project?

Adding linter steps

Adding a linter to a project takes several steps:

  1. Current state of the project
  2. Create a .go-arch-lint.yml file describing the ideal project architecture
  3. Linter find some issues in the project. Don’t fix them right now, but “legalize” them by adding them to the config and marking todo with the label
  4. In your free time, technical debt, etc. fix the code
  5. After fixes, clean up config to target state

Execute

Usage:
  go-arch-lint check [flags]

Flags:
      --arch-file string      arch file path (default ".go-arch-lint.yml")
  -h, --help                  help for check
      --max-warnings int      max number of warnings to output (default 512)
      --project-path string   absolute path to project directory (where '.go-arch-lint.yml' is located) (default "./")

Global Flags:
      --json                   (alias for --output-type=json)
      --output-color           use ANSI colors in terminal output (default true)
      --output-json-one-line   format JSON as single line payload (without line breaks), only for json output type
      --output-type string     type of command output, variants: [ascii, json] (default "default")

This linter will return:

Status CodeDescription
0Project has correct architecture
1Found warnings

How is working?

How is working

Linter will:

Graph

Example config of this repository: .go-arch-lint.yml

graph

You can generate dependencies graph with command graph:

go-arch-lint graph

See full graph documentation for details.

Pre-Commit

go-arch-lint can also be used as a pre-commit hook, acting before each commit is made.
This is useful to always check that your new code still respects your repo architecture, and to always update your graph SVG.

  1. Install pre-commit from https://pre-commit.com/#install
  2. Create a .pre-commit-config.yaml file at the root of your repository with the following content:
repos:
  - repo: https://github.com/fe3dback/go-arch-lint
    rev: master
    hooks:
      - id: go-arch-lint-check
      - id: go-arch-lint-graph
        args: ['--include-vendors=true', '--out=go-arch-lint-graph.svg']
  1. If needed, add any flags you need in args.
  2. Auto-update the config to the latest repos' versions by executing pre-commit autoupdate
  3. Install with pre-commit install
  4. Now you're all set! Try a commit, and see the logs (passing or failing).