chore(repo): initialize hexcheck
- commit
- 996ed79bd25c381ad8cbbb6010691ae8f59978c3
- author
- brice · · 2026-05-30 04:52 UTC
- parent
- none (root commit)
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
6 files · +162 -0
A .github/workflows/ci.yml +21 -0
| @@ -0,0 +1,21 @@ | |||
| 1 | + | name: CI | |
| 2 | + | ||
| 3 | + | on: | |
| 4 | + | push: | |
| 5 | + | branches: [main] | |
| 6 | + | pull_request: | |
| 7 | + | ||
| 8 | + | jobs: | |
| 9 | + | test: | |
| 10 | + | runs-on: ubuntu-latest | |
| 11 | + | steps: | |
| 12 | + | - uses: actions/checkout@v4 | |
| 13 | + | - uses: actions/setup-go@v5 | |
| 14 | + | with: | |
| 15 | + | go-version-file: go.mod | |
| 16 | + | - name: Verify tidy | |
| 17 | + | run: | | |
| 18 | + | go mod tidy | |
| 19 | + | git diff --exit-code -- go.mod go.sum | |
| 20 | + | - name: Test | |
| 21 | + | run: go test ./... | |
| @@ -0,0 +1,21 @@ | |||||
| 1 | + | name: CI | |||
| 2 | + | ||||
| 3 | + | on: | |||
| 4 | + | push: | |||
| 5 | + | branches: [main] | |||
| 6 | + | pull_request: | |||
| 7 | + | ||||
| 8 | + | jobs: | |||
| 9 | + | test: | |||
| 10 | + | runs-on: ubuntu-latest | |||
| 11 | + | steps: | |||
| 12 | + | - uses: actions/checkout@v4 | |||
| 13 | + | - uses: actions/setup-go@v5 | |||
| 14 | + | with: | |||
| 15 | + | go-version-file: go.mod | |||
| 16 | + | - name: Verify tidy | |||
| 17 | + | run: | | |||
| 18 | + | go mod tidy | |||
| 19 | + | git diff --exit-code -- go.mod go.sum | |||
| 20 | + | - name: Test | |||
| 21 | + | run: go test ./... | |||
A .gitignore +4 -0
| @@ -0,0 +1,4 @@ | |||
| 1 | + | bin/ | |
| 2 | + | custom-gcl | |
| 3 | + | coverage.out | |
| 4 | + | .DS_Store | |
| @@ -0,0 +1,4 @@ | |||||
| 1 | + | bin/ | |||
| 2 | + | custom-gcl | |||
| 3 | + | coverage.out | |||
| 4 | + | .DS_Store | |||
A LICENSE +21 -0
| @@ -0,0 +1,21 @@ | |||
| 1 | + | MIT License | |
| 2 | + | ||
| 3 | + | Copyright (c) 2026 | |
| 4 | + | ||
| 5 | + | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | + | of this software and associated documentation files (the "Software"), to deal | |
| 7 | + | in the Software without restriction, including without limitation the rights | |
| 8 | + | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 | + | copies of the Software, and to permit persons to whom the Software is | |
| 10 | + | furnished to do so, subject to the following conditions: | |
| 11 | + | ||
| 12 | + | The above copyright notice and this permission notice shall be included in all | |
| 13 | + | copies or substantial portions of the Software. | |
| 14 | + | ||
| 15 | + | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | + | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | + | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 | + | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 | + | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | + | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 21 | + | SOFTWARE. | |
| @@ -0,0 +1,21 @@ | |||||
| 1 | + | MIT License | |||
| 2 | + | ||||
| 3 | + | Copyright (c) 2026 | |||
| 4 | + | ||||
| 5 | + | Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| 6 | + | of this software and associated documentation files (the "Software"), to deal | |||
| 7 | + | in the Software without restriction, including without limitation the rights | |||
| 8 | + | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| 9 | + | copies of the Software, and to permit persons to whom the Software is | |||
| 10 | + | furnished to do so, subject to the following conditions: | |||
| 11 | + | ||||
| 12 | + | The above copyright notice and this permission notice shall be included in all | |||
| 13 | + | copies or substantial portions of the Software. | |||
| 14 | + | ||||
| 15 | + | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 16 | + | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 17 | + | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| 18 | + | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| 19 | + | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| 20 | + | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| 21 | + | SOFTWARE. | |||
A Makefile +15 -0
| @@ -0,0 +1,15 @@ | |||
| 1 | + | .PHONY: test lint tidy check smoke-dumber | |
| 2 | + | ||
| 3 | + | test: | |
| 4 | + | go test ./... | |
| 5 | + | ||
| 6 | + | lint: | |
| 7 | + | golangci-lint run ./... | |
| 8 | + | ||
| 9 | + | tidy: | |
| 10 | + | go mod tidy | |
| 11 | + | ||
| 12 | + | check: tidy test | |
| 13 | + | ||
| 14 | + | smoke-dumber: | |
| 15 | + | HEXCHECK_DUMBER_PATH=/home/brice/dev/projects/dumber go test ./test/smoke | |
| @@ -0,0 +1,15 @@ | |||||
| 1 | + | .PHONY: test lint tidy check smoke-dumber | |||
| 2 | + | ||||
| 3 | + | test: | |||
| 4 | + | go test ./... | |||
| 5 | + | ||||
| 6 | + | lint: | |||
| 7 | + | golangci-lint run ./... | |||
| 8 | + | ||||
| 9 | + | tidy: | |||
| 10 | + | go mod tidy | |||
| 11 | + | ||||
| 12 | + | check: tidy test | |||
| 13 | + | ||||
| 14 | + | smoke-dumber: | |||
| 15 | + | HEXCHECK_DUMBER_PATH=/home/brice/dev/projects/dumber go test ./test/smoke | |||
A README.md +98 -0
| @@ -0,0 +1,98 @@ | |||
| 1 | + | # hexcheck | |
| 2 | + | ||
| 3 | + | `hexcheck` is a Go architecture linter for hexagonal and clean architecture boundaries. | |
| 4 | + | ||
| 5 | + | It is built on `golang.org/x/tools/go/analysis`, runs as a standalone CLI, and can be embedded in a custom `golangci-lint` binary through the Module Plugin System. | |
| 6 | + | ||
| 7 | + | ## Goals | |
| 8 | + | ||
| 9 | + | - map project packages to configurable architecture components | |
| 10 | + | - catch deterministic boundary violations in CI | |
| 11 | + | - warn about suspicious business logic in adapters and entrypoints | |
| 12 | + | - warn when tests bypass generated interface mocks with local fakes or real adapters | |
| 13 | + | - smoke test the analyzer against real Go repositories such as Dumber | |
| 14 | + | ||
| 15 | + | ## Quick example | |
| 16 | + | ||
| 17 | + | ```yaml | |
| 18 | + | version: 1 | |
| 19 | + | components: | |
| 20 | + | core: | |
| 21 | + | role: core | |
| 22 | + | paths: | |
| 23 | + | - internal/domain/** | |
| 24 | + | usecase: | |
| 25 | + | role: usecase | |
| 26 | + | paths: | |
| 27 | + | - internal/application/usecase/** | |
| 28 | + | ports: | |
| 29 | + | role: ports | |
| 30 | + | paths: | |
| 31 | + | - internal/application/port/** | |
| 32 | + | adapters: | |
| 33 | + | role: adapter | |
| 34 | + | paths: | |
| 35 | + | - internal/infrastructure/** | |
| 36 | + | - internal/ui/** | |
| 37 | + | - internal/cli/** | |
| 38 | + | entrypoints: | |
| 39 | + | role: entrypoint | |
| 40 | + | paths: | |
| 41 | + | - cmd/** | |
| 42 | + | ||
| 43 | + | rules: | |
| 44 | + | no-adapter-imports-in-core: error | |
| 45 | + | no-infra-imports-in-usecase: error | |
| 46 | + | no-framework-types-in-core: error | |
| 47 | + | no-infra-types-in-ports: error | |
| 48 | + | no-adapter-to-adapter-imports: warn | |
| 49 | + | suspicious-business-logic-in-adapter: warn | |
| 50 | + | no-local-fakes-for-ports: warn | |
| 51 | + | prefer-generated-mocks: warn | |
| 52 | + | ``` | |
| 53 | + | ||
| 54 | + | ## Standalone CLI | |
| 55 | + | ||
| 56 | + | ```bash | |
| 57 | + | hexcheck --config .hexcheck.yaml ./... | |
| 58 | + | ``` | |
| 59 | + | ||
| 60 | + | ## golangci-lint module plugin | |
| 61 | + | ||
| 62 | + | Build a custom golangci-lint binary: | |
| 63 | + | ||
| 64 | + | ```yaml | |
| 65 | + | # .custom-gcl.yml | |
| 66 | + | version: v2.12.2 | |
| 67 | + | name: hex-golangci-lint | |
| 68 | + | destination: ./bin | |
| 69 | + | plugins: | |
| 70 | + | - module: github.com/bnema/hexcheck | |
| 71 | + | import: github.com/bnema/hexcheck/golangci | |
| 72 | + | version: v0.1.0 | |
| 73 | + | ``` | |
| 74 | + | ||
| 75 | + | Enable it: | |
| 76 | + | ||
| 77 | + | ```yaml | |
| 78 | + | # .golangci.yml | |
| 79 | + | version: "2" | |
| 80 | + | linters: | |
| 81 | + | enable: | |
| 82 | + | - hexcheck | |
| 83 | + | settings: | |
| 84 | + | custom: | |
| 85 | + | hexcheck: | |
| 86 | + | type: module | |
| 87 | + | description: Checks hexagonal architecture boundaries. | |
| 88 | + | settings: | |
| 89 | + | config: .hexcheck.yaml | |
| 90 | + | ``` | |
| 91 | + | ||
| 92 | + | ## Local development | |
| 93 | + | ||
| 94 | + | ```bash | |
| 95 | + | make test | |
| 96 | + | make check | |
| 97 | + | HEXCHECK_DUMBER_PATH=/home/brice/dev/projects/dumber make smoke-dumber | |
| 98 | + | ``` | |
| @@ -0,0 +1,98 @@ | |||||
| 1 | + | # hexcheck | |||
| 2 | + | ||||
| 3 | + | `hexcheck` is a Go architecture linter for hexagonal and clean architecture boundaries. | |||
| 4 | + | ||||
| 5 | + | It is built on `golang.org/x/tools/go/analysis`, runs as a standalone CLI, and can be embedded in a custom `golangci-lint` binary through the Module Plugin System. | |||
| 6 | + | ||||
| 7 | + | ## Goals | |||
| 8 | + | ||||
| 9 | + | - map project packages to configurable architecture components | |||
| 10 | + | - catch deterministic boundary violations in CI | |||
| 11 | + | - warn about suspicious business logic in adapters and entrypoints | |||
| 12 | + | - warn when tests bypass generated interface mocks with local fakes or real adapters | |||
| 13 | + | - smoke test the analyzer against real Go repositories such as Dumber | |||
| 14 | + | ||||
| 15 | + | ## Quick example | |||
| 16 | + | ||||
| 17 | + | ```yaml | |||
| 18 | + | version: 1 | |||
| 19 | + | components: | |||
| 20 | + | core: | |||
| 21 | + | role: core | |||
| 22 | + | paths: | |||
| 23 | + | - internal/domain/** | |||
| 24 | + | usecase: | |||
| 25 | + | role: usecase | |||
| 26 | + | paths: | |||
| 27 | + | - internal/application/usecase/** | |||
| 28 | + | ports: | |||
| 29 | + | role: ports | |||
| 30 | + | paths: | |||
| 31 | + | - internal/application/port/** | |||
| 32 | + | adapters: | |||
| 33 | + | role: adapter | |||
| 34 | + | paths: | |||
| 35 | + | - internal/infrastructure/** | |||
| 36 | + | - internal/ui/** | |||
| 37 | + | - internal/cli/** | |||
| 38 | + | entrypoints: | |||
| 39 | + | role: entrypoint | |||
| 40 | + | paths: | |||
| 41 | + | - cmd/** | |||
| 42 | + | ||||
| 43 | + | rules: | |||
| 44 | + | no-adapter-imports-in-core: error | |||
| 45 | + | no-infra-imports-in-usecase: error | |||
| 46 | + | no-framework-types-in-core: error | |||
| 47 | + | no-infra-types-in-ports: error | |||
| 48 | + | no-adapter-to-adapter-imports: warn | |||
| 49 | + | suspicious-business-logic-in-adapter: warn | |||
| 50 | + | no-local-fakes-for-ports: warn | |||
| 51 | + | prefer-generated-mocks: warn | |||
| 52 | + | ``` | |||
| 53 | + | ||||
| 54 | + | ## Standalone CLI | |||
| 55 | + | ||||
| 56 | + | ```bash | |||
| 57 | + | hexcheck --config .hexcheck.yaml ./... | |||
| 58 | + | ``` | |||
| 59 | + | ||||
| 60 | + | ## golangci-lint module plugin | |||
| 61 | + | ||||
| 62 | + | Build a custom golangci-lint binary: | |||
| 63 | + | ||||
| 64 | + | ```yaml | |||
| 65 | + | # .custom-gcl.yml | |||
| 66 | + | version: v2.12.2 | |||
| 67 | + | name: hex-golangci-lint | |||
| 68 | + | destination: ./bin | |||
| 69 | + | plugins: | |||
| 70 | + | - module: github.com/bnema/hexcheck | |||
| 71 | + | import: github.com/bnema/hexcheck/golangci | |||
| 72 | + | version: v0.1.0 | |||
| 73 | + | ``` | |||
| 74 | + | ||||
| 75 | + | Enable it: | |||
| 76 | + | ||||
| 77 | + | ```yaml | |||
| 78 | + | # .golangci.yml | |||
| 79 | + | version: "2" | |||
| 80 | + | linters: | |||
| 81 | + | enable: | |||
| 82 | + | - hexcheck | |||
| 83 | + | settings: | |||
| 84 | + | custom: | |||
| 85 | + | hexcheck: | |||
| 86 | + | type: module | |||
| 87 | + | description: Checks hexagonal architecture boundaries. | |||
| 88 | + | settings: | |||
| 89 | + | config: .hexcheck.yaml | |||
| 90 | + | ``` | |||
| 91 | + | ||||
| 92 | + | ## Local development | |||
| 93 | + | ||||
| 94 | + | ```bash | |||
| 95 | + | make test | |||
| 96 | + | make check | |||
| 97 | + | HEXCHECK_DUMBER_PATH=/home/brice/dev/projects/dumber make smoke-dumber | |||
| 98 | + | ``` | |||
A go.mod +3 -0
| @@ -0,0 +1,3 @@ | |||
| 1 | + | module github.com/bnema/hexcheck | |
| 2 | + | ||
| 3 | + | go 1.24 | |
| @@ -0,0 +1,3 @@ | |||||
| 1 | + | module github.com/bnema/hexcheck | |||
| 2 | + | ||||
| 3 | + | go 1.24 | |||