sv4git

A command line tool (CLI) to validate commit messages, bump version, create tags and generate changelogs!

Release Go Reference GitHub stars GitHub release (latest by date) GitHub all releases Software License GitHub Actions Status Go Report Card Conventional Commits

## Getting Started ### Pre Requirements - Git 2.17+ ### Installing - Download the latest release and add the binary to your path. - Optional: Set `SV4GIT_HOME` to define user configs. Check the [Config](#config) topic for more information. If you want to install from source using `go install`, just run: ```bash # keep in mind that with this, it will compile from source and won't show the version on cli -h. go install github.com/bvieira/sv4git/v2/cmd/git-sv@latest # if you want to add the version on the binary, run this command instead. SV4GIT_VERSION=$(go list -f '{{ .Version }}' -m github.com/bvieira/sv4git/v2@latest | sed 's/v//') && go install --ldflags "-X main.Version=$SV4GIT_VERSION" github.com/bvieira/sv4git/v2/cmd/git-sv@v$SV4GIT_VERSION ``` ### Config #### YAML There are 3 config levels when using sv4git: [default](#default), [user](#user), [repository](#repository). All of them are merged considering the follow priority: **repository > user > default**. To see the current config, run: ```bash git sv cfg show ``` ##### Configuration Types ###### Default To check the default configuration, run: ```bash git sv cfg default ``` ###### User For user config, it is necessary to define the `SV4GIT_HOME` environment variable, eg.: ```bash SV4GIT_HOME=/home/myuser/.sv4git # myuser is just an example. ``` And create a `config.yml` file inside it, eg.: ```bash .sv4git └── config.yml ``` ###### Repository Create a `.sv4git.yml` file on the root of your repository, eg.: [.sv4git.yml](.sv4git.yml). ##### Configuration format ```yml version: "1.1" #config version versioning: # versioning bump update-major: [] # Commit types used to bump major. update-minor: [feat] # Commit types used to bump minor. update-patch: [build, ci, chore, fix, perf, refactor, test] # Commit types used to bump patch. # When type is not present on update rules and is unknown (not mapped on commit message types); # if ignore-unknown=false bump patch, if ignore-unknown=true do not bump version ignore-unknown: false tag: pattern: '%d.%d.%d' # Pattern used to create git tag. release-notes: # Deprecated!!! please use 'sections' instead! # Headers names for release notes markdown. To disable a section just remove the header # line. It's possible to add other commit types, the release note will be created # respecting the following order: feat, fix, refactor, perf, test, build, ci, chore, docs, style, breaking-change. headers: breaking-change: Breaking Changes feat: Features fix: Bug Fixes sections: # Array with each section of release note. Check template section for more information. - name: Features # Name used on section. section-type: commits # Type of the section, supported types: commits, breaking-changes. commit-types: [feat] # Commit types for commit section-type, one commit type cannot be in more than one section. - name: Bug Fixes section-type: commits commit-types: [fix] - name: Breaking Changes section-type: breaking-changes branches: # Git branches config. prefix: ([a-z]+\/)? # Prefix used on branch name, it should be a regex group. suffix: (-.*)? # Suffix used on branch name, it should be a regex group. disable-issue: false # Set true if there is no need to recover issue id from branch name. skip: [master, main, developer] # List of branch names ignored on commit message validation. skip-detached: false # Set true if a detached branch should be ignored on commit message validation. commit-message: types: [build, ci, chore, docs, feat, fix, perf, refactor, revert, style, test] # Supported commit types. scope: # Define supported scopes, if blank, scope will not be validated, if not, only scope listed will be valid. # Don't forget to add "" on your list if you need to define scopes and keep it optional. values: [] footer: issue: # Use "issue: {}" if you wish to disable issue footer. key: jira # Name used to define an issue on footer metadata. key-synonyms: [Jira, JIRA] # Supported variations for footer metadata. use-hash: false # If false, use : separator. If true, use # separator. add-value-prefix: '' # Add a prefix to issue value. issue: regex: '[A-Z]+-[0-9]+' # Regex for issue id. ``` #### Templates **sv4git** uses *go templates* to format the output for `release-notes` and `changelog`, to see how the default template is configured check [template directory](cmd/git-sv/resources/templates). On v2.7.0+, its possible to overwrite the default configuration by adding `.sv4git/templates` on your repository. The cli expects that at least 2 files exists on your directory: `changelog-md.tpl` and `releasenotes-md.tpl`. ```bash .sv4git └── templates ├── changelog-md.tpl └── releasenotes-md.tpl ``` Everything inside `.sv4git/templates` will be loaded, so it's possible to add more files to be used as needed. ##### Variables To execute the template the `releasenotes-md.tpl` will receive a single **ReleaseNote** and `changelog-md.tpl` will receive a list of **ReleaseNote** as variables. Each **ReleaseNoteSection** will be configured according with `release-notes.section` from config file. The order for each section will be maintained and the **SectionType** is defined according with `section-type` attribute as described on the table below. | section-type | ReleaseNoteSection | | -- | -- | | commits | ReleaseNoteCommitsSection | | breaking-changes | ReleaseNoteBreakingChangeSection | > :warning: currently only `commits` and `breaking-changes` are supported as `section-types`, using a different value for this field will make the section to be removed from the template variables. Check below the variables available: ```go ReleaseNote Release string // 'v' followed by version if present, if not tag will be used instead. Tag string // Current tag, if available. Version *Version // Version from tag or next version according with semver. Date time.Time Sections []ReleaseNoteSection // ReleaseNoteCommitsSection or ReleaseNoteBreakingChangeSection AuthorNames []string // Author names recovered from commit message (user.name from git) Version Major int Minor int Patch int Prerelease string Metadata string Original string ReleaseNoteCommitsSection // SectionType == commits SectionType string SectionName string Types []string Items []GitCommitLog HasMultipleTypes bool ReleaseNoteBreakingChangeSection // SectionType == breaking-changes SectionType string SectionName string Messages []string GitCommitLog Date string Timestamp int AuthorName string Hash string Message CommitMessage CommitMessage Type string Scope string Description string Body string IsBreakingChange bool Metadata map[string]string ``` ##### Functions Beside the [go template functions](https://pkg.go.dev/text/template#hdr-Functions), the folowing functions are availiable to use in the templates. Check [formatter_functions.go](sv/formatter_functions.go) to see the functions implementation. ###### timefmt **Usage:** timefmt time "2006-01-02" Receive a time.Time and a layout string and returns a textual representation of the time according with the layout provided. Check for more information. ###### getsection **Usage:** getsection sections "Features" Receive a list of ReleaseNoteSection and a Section name and returns a section with the provided name. If no section is found, it will return `nil`. ### Running Run `git-sv` to get the list of available parameters: ```bash git-sv ``` #### Run as git command If `git-sv` is configured on your path, you can use it like a git command: ```bash git sv git sv current-version git sv next-version ``` #### Usage Use `--help` or `-h` to get usage information, don't forget that some commands have unique options too: ```bash # sv help git-sv -h # sv release-notes command help git-sv rn -h ``` ##### Available commands | Variable | description | has options or subcommands | | ---------------------------- | -------------------------------------------------------------- | :------------------------: | | config, cfg | Show config information. | :heavy_check_mark: | | current-version, cv | Get last released version from git. | :x: | | next-version, nv | Generate the next version based on git commit messages. | :x: | | commit-log, cl | List all commit logs according to range as jsons. | :heavy_check_mark: | | commit-notes, cn | Generate a commit notes according to range. | :heavy_check_mark: | | release-notes, rn | Generate release notes. | :heavy_check_mark: | | changelog, cgl | Generate changelog. | :heavy_check_mark: | | tag, tg | Generate tag with version based on git commit messages. | :x: | | commit, cmt | Execute git commit with convetional commit message helper. | :heavy_check_mark: | | validate-commit-message, vcm | Use as prepare-commit-message hook to validate commit message. | :heavy_check_mark: | | help, h | Shows a list of commands or help for one command. | :x: | ##### Use range Commands like `commit-log` and `commit-notes` has a range option. Supported range types are: `tag`, `date` and `hash`. By default, it's used [--date=short](https://git-scm.com/docs/git-log#Documentation/git-log.txt---dateltformatgt) at `git log`, all dates returned from it will be in `YYYY-MM-DD` format. Range `tag` will use `git for-each-ref refs/tags` to get the last tag available if `start` is empty, the others types won't use the existing tags. It's recommended to always use a start limit in a old repository with a lot of commits. This behavior was maintained to not break the retrocompatibility. Range `date` use git log `--since` and `--until`. It's possible to use all supported formats from [git log](https://git-scm.com/docs/git-log#Documentation/git-log.txt---sinceltdategt). If `end` is in `YYYY-MM-DD` format, `sv` will add a day on git log command to make the end date inclusive. Range `tag` and `hash` are used on git log [revision range](https://git-scm.com/docs/git-log#Documentation/git-log.txt-ltrevisionrangegt). If `end` is empty, `HEAD` will be used instead. ```bash # get commit log as json using a inclusive range git-sv commit-log --range hash --start 7ea9306~1 --end c444318 # return all commits after last tag git-sv commit-log --range tag ``` ##### Use validate-commit-message as prepare-commit-msg hook Configure your `.git/hooks/prepare-commit-msg`: ```bash #!/bin/sh COMMIT_MSG_FILE=$1 COMMIT_SOURCE=$2 SHA1=$3 git sv vcm --path "$(pwd)" --file "$COMMIT_MSG_FILE" --source "$COMMIT_SOURCE" ``` **Tip**: you can configure a directory as your global git templates using the command below: ```bash git config --global init.templatedir '' ``` Check [git config docs](https://git-scm.com/docs/git-config#Documentation/git-config.txt-inittemplateDir) for more information! ## Development ### Makefile Run `make` to get the list of available actions: ```bash make ``` #### Make configs | Variable | description | | ---------- | ----------------------- | | BUILDOS | Build OS. | | BUILDARCH | Build arch. | | ECHOFLAGS | Flags used on echo. | | BUILDENVS | Var envs used on build. | | BUILDFLAGS | Flags used on build. | | Parameters | description | | ---------- | ------------------------------------ | | args | Parameters that will be used on run. | ```bash #variables BUILDOS="linux" BUILDARCH="amd64" make build #parameters make run args="-h" ``` ### Build ```bash make build ``` The binary will be created on `bin/$BUILDOS_$BUILDARCH/git-sv`. ### Tests ```bash make test ``` ### Run ```bash #without args make run #with args make run args="-h" ```