23.10-init
Initial project decisions
Project goal
- Simple cli tool for PR validation automation
- Become simpler to integrate, well documented and faster alternative to Danger
Context
Commit history
Commit messages quality matters
Examples:
- Message format checks
- Issue actual status check
- Change log generation
- Author email domain
PR changes
Simple automation using changes info can encourage developers to spend little time now to save more time on code review and tech debt in future.
Examples:
- Config files editor whitelist
- Whitelist libraries
- Is docs edited with code
Danger
Danger is a great project for PR automation. But I think it’s overcomplicated.
I can do alternative with:
- More friendly documentation site
- Yaml/Toml configuration with batteries included checks for easy start
- Config UX is similar to linters and other tools
- No Ruby/JS knowledge required
- Validation and type-safety => config autoupdate
- Faster computation by Go multithreading and go-git
- Plain text output
- Simpler
- Can be used with other tools (post Slack or PR message)
Conventional commits
Is great way of declare changes. It goes with commitlint and changelog tool. But i think It can be single tool with more customisation for easy integration.
I can do commit message format template that can be used for validation and generation at same time.
Same idea, simple yaml config. But lack of configuration options and no documentation.
Design draft
Usage
Project has .changes.yml/toml config file.
Validation:
changes lint -last 10
for last 10 commitschanges lint pr
for PR new commits
Result:
INFO sdfdhfsald12 message bla bla bla
ERROR sdfdhfsald12 message bla bla bla
ERROR history message bla bla bla
Where sdfdhfsald12
is commit sha.
Change log generation:
changes log -last 10
changes log -pr
Config
MVP config - code
r := runner.New()
r.AddChecker(checkers.TotalChange{
MaxLines: 200,
})
r.AddChecker(checkers.ProtectedFiles{
Paths: []string{".golangci-lint", "git-checks.go"},
})
result := r.Run()
// result.PrintJson()
result.Print()
Yaml
version: "0.1"
local_run_last_commits: 10
output_format: "json"
checks:
- name: "branch_name"
format: "^\(fix|feature)\*"
- name: "total_change"
max-lines: 200
- name: "protected_files"
paths: [ ".golangci-lint", "git-checks.go" ]
Package design
https://go.dev/doc/modules/layout
- runner - linter pipeline interface and implementation
- config - different configuration sources
- git - git abstraction using go-git
- checker - interface, checks DTO
- rule - batteries included chesks
- cmd/main.go - cli cmd
Repository can be used as library.
sequenceDiagram Runner ->>+ Config: Get onfig Config ->> Config: unmarshal Config ->> Config: validate Config -->- Runner: checkers onfig Runner ->>+ Git: Get git diff Git ->> Git: Read git DB Git -->- Runner: branch, commits, changes loop Every checker Runner ->>+ Checker: Run checks Checker ->> Checker: Do checks Checker -->>- Runner: logs end Runner ->> Out: Print logs
Interfaces
Checker is an interface which implements different lint rules.
Program:
- Collects a list of registered checks and their configuration
- Validates the configuration of each check (Validate())
- Gets the history from Git
For each commit, it runs CheckCommit checks and collects TotalChange.
type Logger interface {
Debug(message string)
Info(message string)
Warning(message string)
Error(message string)
}
type Checker interface {
Type() CheckerType
Validate() error
CheckCommit(ctx CommitCheckerContext)
CheckHistory(ctx HistoryCheckerContext)
}
type HistoryCheckerContext interface {
Logger
Branch() Branch
Total() TotalChange
}
type Branch struct {
Name string
}
type CommitCheckerContext interface {
Logger
Commit
}
type TotalChange struct {
Commits uint
Changes []FileChange
}
type Commit interface {
Message() CommitMessage
Changes() []FileChange
}
type CommitMessage struct {
Title, Body, Footer string
}
type FileChange struct {
Path string
Add, Del int
}
type CheckerType struct {
Name string
// OnlyCI sets checker runnable only in CI environment
// not runnable locally
OnlyCI bool
}
First rules
- PR changes max lines
- Commit changes max lines
- Commit format: max length and title regex
- Footer regex or footer words
- Conventional commits (check + changelog)
- Emoji ban, symbol set whitelist
- Rebase forcing