Compare commits

..

No commits in common. "master" and "v0.11.2" have entirely different histories.

55 changed files with 558 additions and 1863 deletions

21
.appveyor.yml Normal file
View file

@ -0,0 +1,21 @@
version: "{build}"
clone_depth: 1
clone_folder: c:\gopath\src\github.com\git-chglog\git-chglog
environment:
GOPATH: c:\gopath
install:
- echo %PATH%
- echo %GOPATH%
- go version
- go env
- set PATH=%PATH%;%GOPATH%\bin
test_script:
- go build github.com/git-chglog/git-chglog/cmd/git-chglog
- for /f "" %%G in ('go list github.com/git-chglog/git-chglog/...') do ( go test -v %%G & IF ERRORLEVEL == 1 EXIT 1)
build: off
deploy: off

View file

@ -29,13 +29,6 @@
{{ end }}
{{ end -}}
{{- if .MergeCommits -}}
### Pull Requests
{{ range .MergeCommits -}}
- {{ .Header }}
{{ end }}
{{ end -}}
{{- if .NoteGroups -}}
{{ range .NoteGroups -}}
### {{ .Title }}

View file

@ -11,19 +11,16 @@ options:
- fix
- perf
- refactor
- chore
commit_groups:
title_maps:
feat: Features
fix: Bug Fixes
perf: Performance Improvements
refactor: Code Refactoring
chore: Chores
header:
pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$"
pattern: "^(\\w*)\\:\\s(.*)$"
pattern_maps:
- Type
- Scope
- Subject
notes:
keywords:

View file

@ -1,105 +0,0 @@
name: ci
on:
pull_request:
types: ["opened", "synchronize"]
paths-ignore:
- "README.md"
push:
branches:
- master
paths-ignore:
- "README.md"
env:
GO_VERSION: "1.24"
GOLANGCI_VERSION: "v1.64.8"
jobs:
tests:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run tests
run: make test
- name: Install goveralls
run: |
go install github.com/mattn/goveralls@latest
echo $GOPATH
ls -lash $GOPATH
which goveralls
working-directory: /tmp
- name: Send coverage
run: goveralls -coverprofile=cover.out -service=github
env:
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
lint:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: ${{ env.GOLANGCI_VERSION }}
docker-image-tests:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run tests
run: make build
- name: Test docker image
run: |
docker build -t git-chglog:ci-build .
docker run -v ${GITHUB_WORKSPACE}:/workdir -w /workdir git-chglog:ci-build > ${GITHUB_WORKSPACE}/ci-build.md
head ${GITHUB_WORKSPACE}/ci-build.md
goreleaser-test:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
with:
version: latest
args: release --clean --skip=publish --snapshot

View file

@ -1,34 +0,0 @@
name: publish
on:
push:
branches:
- master
env:
GO_VERSION: "1.24"
DOCKER_REGISTRY: "quay.io"
jobs:
docker:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Login to Docker Registry
uses: docker/login-action@v2
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ secrets.QUAY_IO_USER }}
password: ${{ secrets.QUAY_IO_TOKEN }}
- name: Build and Push docker image
run: DOCKER_TAG=edge make docker push

View file

@ -1,39 +1,26 @@
name: release
name: goreleaser
on:
push:
tags:
- "*"
env:
GO_VERSION: "1.24"
DOCKER_REGISTRY: "quay.io"
- '*'
jobs:
goreleaser:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
uses: actions/setup-go@v2
with:
go-version: ${{ env.GO_VERSION }}
- name: Login to Docker Registry
uses: docker/login-action@v2
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ secrets.QUAY_IO_USER }}
password: ${{ secrets.QUAY_IO_TOKEN }}
go-version: 1.15
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
uses: goreleaser/goreleaser-action@v2
with:
version: latest
args: release --clean
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GORELEASER_TOKEN }}

37
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,37 @@
name: tests
on:
pull_request:
types: ['opened', 'synchronize']
paths-ignore:
- 'README.md'
push:
branches:
- master
paths-ignore:
- 'README.md'
jobs:
unit:
runs-on: ubuntu-20.04
strategy:
fail-fast: true
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.15
- name: Run tests
run: |
make test
- name: Install goveralls
env:
GO111MODULE: off
run: go get github.com/mattn/goveralls
- name: Send coverage
env:
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: goveralls -coverprofile=cover.out -service=github

3
.gitignore vendored
View file

@ -39,9 +39,6 @@ Icon
*.iml
.idea
# vscode IDE
.vscode
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd

View file

@ -1,103 +0,0 @@
# https://golangci-lint.run/usage/configuration/
run:
timeout: 10m
tests: true
linters-settings:
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
goimports:
# put imports beginning with prefix after 3rd-party packages;
# it's a comma-separated list of prefixes
local-prefixes: github.com/git-chglog/git-chglog
gocyclo:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 10
dupl:
# tokens count to trigger issue, 150 by default
threshold: 100
goconst:
# minimal length of string constant, 3 by default
min-len: 3
# minimal occurrences count to trigger, 3 by default
min-occurrences: 5
lll:
# tab width in spaces. Default to 1.
tab-width: 1
unparam:
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
nakedret:
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
max-func-lines: 30
prealloc:
# XXX: we don't recommend using this linter before doing performance profiling.
# For most programs usage of prealloc will be a premature optimization.
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
# True by default.
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: false # Report preallocation suggestions on for loops, false by default
misspell:
locale: US
linters:
enable:
- gosimple
- staticcheck
- unused
- gocyclo
- goconst
- goimports
- gofmt # We enable this as well as goimports for its simplify mode.
- prealloc
- unconvert
- misspell
- nakedret
- dupl
#- depguard TODO fix later
presets:
- bugs
- unused
fast: false
issues:
# Excluding configuration per-path and per-linter
exclude-rules:
# Exclude some linters from running on tests files.
- path: _test(ing)?\.go
linters:
- gocyclo
- errcheck
- dupl
- gosec
- unparam
- testifylint
- depguard
# Show only new issues: if there are unstaged changes or untracked files,
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
# It's a super-useful option for integration of golangci-lint into existing
# large codebase. It's not practical to fix all existing issues at the moment
# of integration: much better don't allow issues in new code.
# Default is false.
new: false
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
max-same-issues: 0

View file

@ -1,5 +1,3 @@
version: 2
# This is an example .goreleaser.yml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com
project_name: git-chglog
@ -18,10 +16,11 @@ builds:
- windows
- darwin
goarch:
- 386
- amd64
- arm
- arm64
goarm:
- 6
archives:
- format_overrides:
@ -29,24 +28,19 @@ archives:
format: zip
checksum:
name_template: "checksums.txt"
name_template: 'checksums.txt'
changelog:
sort: desc
filters:
exclude:
- "^Merge"
- '^Merge'
snapshot:
name_template: "{{ .Tag }}-next"
dockers:
- image_templates:
- "quay.io/git-chglog/git-chglog:{{ .RawVersion }}"
- "quay.io/git-chglog/git-chglog:latest"
brews:
- repository:
- tap:
owner: git-chglog
name: homebrew-git-chglog
homepage: "https://godoc.org/github.com/git-chglog/git-chglog"
@ -54,4 +48,4 @@ brews:
test: |
system "#{bin}/git-chglog --help"
install: |
bin.install "git-chglog"
bin.install "git-chglog"

View file

@ -1,203 +1,43 @@
# CHANGELOG
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
<a name="unreleased"></a>
## [Unreleased]
<a name="v0.15.4"></a>
## [v0.15.4] - 2023-02-15
### Bug Fixes
- release process ([#231](https://github.com/git-chglog/git-chglog/issues/231))
- **ci:** add integration test with docker image ([#226](https://github.com/git-chglog/git-chglog/issues/226))
- **deps:** update module github.com/urfave/cli/v2 to v2.24.3 ([#227](https://github.com/git-chglog/git-chglog/issues/227))
- **deps:** update module github.com/fatih/color to v1.14.1 ([#224](https://github.com/git-chglog/git-chglog/issues/224))
- **deps:** update all non-major dependencies ([#223](https://github.com/git-chglog/git-chglog/issues/223))
### Chores
- new release due to shecksum mismatch. Closes [#232](https://github.com/git-chglog/git-chglog/issues/232)
- update changelog for v0.15.3
- update changelog for v0.15.3
- bump docker/login-action to v2. Closes [#206](https://github.com/git-chglog/git-chglog/issues/206)
- bump goreleaser/goreleaser-action to v4. Closes [#208](https://github.com/git-chglog/git-chglog/issues/208)
<a name="v0.15.2"></a>
## [v0.15.2] - 2023-01-22
### Bug Fixes
- typo in readme ([#196](https://github.com/git-chglog/git-chglog/issues/196))
- **deps:** update module gopkg.in/yaml.v2 to v3 ([#221](https://github.com/git-chglog/git-chglog/issues/221))
### Chores
- update changelog for v0.15.2
- update changelog for v0.15.2
- update Go install instructions ([#205](https://github.com/git-chglog/git-chglog/issues/205))
- bump golang to 1.19 ([#218](https://github.com/git-chglog/git-chglog/issues/218))
- **deps:** update all non-major dependencies ([#220](https://github.com/git-chglog/git-chglog/issues/220))
<a name="v0.15.1"></a>
## [v0.15.1] - 2021-12-14
### Bug Fixes
- **deps:** update all non-major dependencies ([#179](https://github.com/git-chglog/git-chglog/issues/179))
- **deps:** update module github.com/andygrunwald/go-jira to v1.14.0 ([#167](https://github.com/git-chglog/git-chglog/issues/167))
- **deps:** update module github.com/alecaivazis/survey/v2 to v2.2.16 ([#165](https://github.com/git-chglog/git-chglog/issues/165))
- **deps:** update module github.com/alecaivazis/survey/v2 to v2.2.15 ([#163](https://github.com/git-chglog/git-chglog/issues/163))
### Chores
- update changelog for v0.15.1
- ignore .vscode
- **deps:** update all non-major dependencies docker tags ([#168](https://github.com/git-chglog/git-chglog/issues/168))
<a name="v0.15.0"></a>
## [v0.15.0] - 2021-07-09
### Bug Fixes
- **deps:** update module github.com/alecaivazis/survey/v2 to v2.2.14 ([#158](https://github.com/git-chglog/git-chglog/issues/158))
- **deps:** update module github.com/alecaivazis/survey/v2 to v2.2.13 ([#156](https://github.com/git-chglog/git-chglog/issues/156))
- **deps:** update module github.com/fatih/color to v1.12.0 ([#150](https://github.com/git-chglog/git-chglog/issues/150))
- **deps:** update module github.com/fatih/color to v1.11.0 ([#149](https://github.com/git-chglog/git-chglog/issues/149))
- **deps:** update module github.com/alecaivazis/survey/v2 to v2.2.12 ([#147](https://github.com/git-chglog/git-chglog/issues/147))
### Chores
- update changelog for v0.15.0
- **deps:** update alpine docker tag to v3.14.0 ([#153](https://github.com/git-chglog/git-chglog/issues/153))
### Features
- Automatic link for gitlab merge requests ([#160](https://github.com/git-chglog/git-chglog/issues/160))
<a name="v0.14.2"></a>
## [v0.14.2] - 2021-04-16
### Bug Fixes
- add CommitGroupTitleOrder back to Options ([#143](https://github.com/git-chglog/git-chglog/issues/143))
### Chores
- update changelog for v0.14.2
- **deps:** update alpine docker tag to v3.13.5 ([#144](https://github.com/git-chglog/git-chglog/issues/144))
<a name="v0.14.1"></a>
## [v0.14.1] - 2021-04-13
### Bug Fixes
- **template:** address regression in string functions for template engine ([#142](https://github.com/git-chglog/git-chglog/issues/142))
### Chores
- update changelog for v0.14.1
- add docker target to Makefile ([#138](https://github.com/git-chglog/git-chglog/issues/138))
- add make release target ([#130](https://github.com/git-chglog/git-chglog/issues/130))
- **deps:** update alpine docker tag to v3.13.4 ([#136](https://github.com/git-chglog/git-chglog/issues/136))
### Features
- add docker image on release and master ([#135](https://github.com/git-chglog/git-chglog/issues/135))
<a name="v0.14.0"></a>
## [v0.14.0] - 2021-03-28
### Chores
- update changelog for v0.14.0
- **CHANGELOG:** regenerate CHANGELOG with type-scope and KAC template ([#129](https://github.com/git-chglog/git-chglog/issues/129))
### Features
- add sprig template functions support ([#131](https://github.com/git-chglog/git-chglog/issues/131))
- add `--sort [TYPE]` flag ([#78](https://github.com/git-chglog/git-chglog/issues/78))
<a name="v0.13.0"></a>
## [v0.13.0] - 2021-03-23
### Chores
- update changelog for v0.13.0
- use ldflags to pass version to build process ([#127](https://github.com/git-chglog/git-chglog/issues/127))
### Features
- add support for rendering .Body after .Subject as part of list ([#121](https://github.com/git-chglog/git-chglog/issues/121))
<a name="v0.12.0"></a>
## [v0.12.0] - 2021-03-20
### Chores
- update changelog for v0.12.0
- bumps version to v0.12.0
- bump golang to 1.16 ([#118](https://github.com/git-chglog/git-chglog/issues/118))
- **ci:** add golangci-lint action and apply linting changes ([#120](https://github.com/git-chglog/git-chglog/issues/120))
### Features
- allow tag sorting by semver ([#124](https://github.com/git-chglog/git-chglog/issues/124))
### BREAKING CHANGE
`JiraIssueId` has been renamed to `JiraIssueID`. This impacts the value for `pattern_maps` in `config.yml`.
* chore(ci): add golangci-lint action
* chore(lint): address errcheck lint failures
* chore(lint): address misspell lint failures
* chore(lint): address gocritic lint failures
* chore(lint): address golint lint failures
* chore(lint): address structcheck lint failures
* chore(lint): address gosimple lint failures
* chore(lint): address gofmt lint failures
* chore(ci): port to official golangci-lint github action
* Update golangci configuration for better coverage
<a name="v0.11.2"></a>
## [v0.11.2] - 2021-03-13
### Bug Fixes
- `--template` and `--repository-url` flags not being used ([#119](https://github.com/git-chglog/git-chglog/issues/119))
### Chores
- update changelog for v0.11.2
- bumps version to v0.11.2
<a name="v0.11.1"></a>
## [v0.11.1] - 2021-03-12
### Bug Fixes
- **short flags:** correctly define cli flags with shorthands ([#117](https://github.com/git-chglog/git-chglog/issues/117))
### Chores
- update readme and changelog for v0.11.1
- bumps version to v0.11.1
- **short flags**: correctly define cli flags with shorthands ([#117](https://github.com/git-chglog/git-chglog/issues/117))
<a name="v0.11.0"></a>
## [v0.11.0] - 2021-03-12
### Bug Fixes
- **deps:** update all non-major dependencies ([#115](https://github.com/git-chglog/git-chglog/issues/115))
- **deps:** update module gopkg.in/kyokomi/emoji.v1 to github.com/kyokomi/emoji/v2 ([#109](https://github.com/git-chglog/git-chglog/issues/109))
- **deps:** update module github.com/urfave/cli to v2 ([#107](https://github.com/git-chglog/git-chglog/issues/107))
- **deps:** update module github.com/stretchr/testify to v1.7.0 ([#103](https://github.com/git-chglog/git-chglog/issues/103))
- **deps:** update module gopkg.in/alecaivazis/survey.v1 to github.com/AlecAivazis/survey/v2 ([#108](https://github.com/git-chglog/git-chglog/issues/108))
- **init:** support OptionAnswer form in survey/v2 ([#113](https://github.com/git-chglog/git-chglog/issues/113))
### Chores
- update changelog for v0.11.0
- bumps version to v0.11.0
- **deps:** add initial renovatebot configuration ([#102](https://github.com/git-chglog/git-chglog/issues/102))
### Features
- add Jira integration ([#52](https://github.com/git-chglog/git-chglog/issues/52))
- **flag:** --path filtering - refs ([#62](https://github.com/git-chglog/git-chglog/issues/62)). Closes [#35](https://github.com/git-chglog/git-chglog/issues/35)
<a name="v0.10.0"></a>
## [v0.10.0] - 2021-01-16
### BREAKING CHANGE
We adapted the naming schema of the uploaded binaries by adding a `v` prefix for tags/versions starting from `v0.10.0`:
```
# up to 0.9.1
https://github.com/git-chglog/git-chglog/releases/download/<VERSION>/git-chglog_<OS>_<ARCH>
# from v0.10.0
https://github.com/git-chglog/git-chglog/releases/download/v<VERSION>/git-chglog_<OS>_<ARCH>
```
### Bug Fixes
- ignore only git-chglog binary in root and not subfolder
### Chores
- update changelog for v0.10.0
- bumps version to v0.10.0
- sorts changelog desc and excludes Merge commits
- fix Makefile typo ([#82](https://github.com/git-chglog/git-chglog/issues/82))
- **asdf:** add asdf install support to README ([#79](https://github.com/git-chglog/git-chglog/issues/79))
### Features
- Adds 'Custom' sort_type to CommitGroup ([#69](https://github.com/git-chglog/git-chglog/issues/69))
- enable tag_filter_pattern in config options ([#72](https://github.com/git-chglog/git-chglog/issues/72))
@ -206,16 +46,6 @@
- add upperFirst template function
- Add emoji format and some formatters in variables
### Reverts
- Revert "ci: switches to personal GH Token for brew cross repo releases"
- ci: switches to personal GH Token for brew cross repo releases
### Pull Requests
- Merge pull request [#65](https://github.com/git-chglog/git-chglog/issues/65) from barryib/case-sensitive-option
- Merge pull request [#59](https://github.com/git-chglog/git-chglog/issues/59) from momotaro98/feature/add-emoji-template-in-init
- Merge pull request [#66](https://github.com/git-chglog/git-chglog/issues/66) from barryib/add-upper-first-func
- Merge pull request [#68](https://github.com/git-chglog/git-chglog/issues/68) from unixorn/tweak-readme
<a name="0.9.1"></a>
## [0.9.1] - 2019-09-23
@ -228,84 +58,49 @@
### Features
- Add --tag-filter-pattern flag.
### Pull Requests
- Merge pull request [#44](https://github.com/git-chglog/git-chglog/issues/44) from evanchaoli/tag-filter
- Merge pull request [#41](https://github.com/git-chglog/git-chglog/issues/41) from StanleyGoldman/fixing-tests-windows
- Merge pull request [#37](https://github.com/git-chglog/git-chglog/issues/37) from ForkingSyndrome/master
<a name="0.8.0"></a>
## [0.8.0] - 2019-02-23
### Features
- add the contains, hasPrefix, hasSuffix, replace, lower and upper functions to the template functions map
### Pull Requests
- Merge pull request [#34](https://github.com/git-chglog/git-chglog/issues/34) from atosatto/template-functions
<a name="0.7.1"></a>
## [0.7.1] - 2018-11-10
### Bug Fixes
- Panic occured when exec --next-tag with HEAD with tag
### Pull Requests
- Merge pull request [#31](https://github.com/git-chglog/git-chglog/issues/31) from drubin/patch-1
- Merge pull request [#30](https://github.com/git-chglog/git-chglog/issues/30) from vvakame/fix-panic
<a name="0.7.0"></a>
## [0.7.0] - 2018-05-06
### Bug Fixes
- Remove accidentally added `Unreleased.Tag`
### Chores
- Update `changelog` task in Makefile
### Features
- Add URL of output example for template style
- Add `--next-tag` flag (experimental)
### Pull Requests
- Merge pull request [#22](https://github.com/git-chglog/git-chglog/issues/22) from git-chglog/feat/add-preview-style-link
- Merge pull request [#21](https://github.com/git-chglog/git-chglog/issues/21) from git-chglog/feat/next-tag
<a name="0.6.0"></a>
## [0.6.0] - 2018-05-04
### Chores
- Update CHANGELOG template format
### Features
- Add tag name header id for keep-a-changelog template
### Pull Requests
- Merge pull request [#20](https://github.com/git-chglog/git-chglog/issues/20) from git-chglog/feat/kac-template-title-id
<a name="0.5.0"></a>
## [0.5.0] - 2018-05-04
### Bug Fixes
- Add unreleased commits section to keep-a-changelog template [#15](https://github.com/git-chglog/git-chglog/issues/15)
### Chores
- Update CHANGELOG template format
### Features
- Update template format to human readable
- Add `Unreleased` field to `RenderData`
### Pull Requests
- Merge pull request [#19](https://github.com/git-chglog/git-chglog/issues/19) from git-chglog/fix/unreleased-commits
- Merge pull request [#18](https://github.com/git-chglog/git-chglog/issues/18) from ringohub/master
<a name="0.4.0"></a>
## [0.4.0] - 2018-04-14
### Features
- Add support for Bitbucket
### Pull Requests
- Merge pull request [#17](https://github.com/git-chglog/git-chglog/issues/17) from git-chglog/feat/bitbucket
- Add support for Bitbucket :tada:
<a name="0.3.3"></a>
@ -313,69 +108,42 @@
### Features
- Change to kindly error message when git-tag does not exist
### Pull Requests
- Merge pull request [#16](https://github.com/git-chglog/git-chglog/issues/16) from git-chglog/fix/empty-tag-handling
<a name="0.3.2"></a>
## [0.3.2] - 2018-04-02
### Bug Fixes
- Fix color output bug in windows help command
### Pull Requests
- Merge pull request [#14](https://github.com/git-chglog/git-chglog/issues/14) from git-chglog/fix/windows-help-color
<a name="0.3.1"></a>
## [0.3.1] - 2018-03-15
### Bug Fixes
- fix preview string of commit subject
### Pull Requests
- Merge pull request [#13](https://github.com/git-chglog/git-chglog/issues/13) from kt3k/feature/fix-preview
- Fix preview string of commit subject ([@kt3k](https://github.com/kt3k))
<a name="0.3.0"></a>
## [0.3.0] - 2018-03-12
### Chores
- Add helper task for generate CHANGELOG
### Features
- Add support for GitLab
### Pull Requests
- Merge pull request [#12](https://github.com/git-chglog/git-chglog/issues/12) from git-chglog/feat/gitlab
- Add support for GitLab :tada:
<a name="0.2.0"></a>
## [0.2.0] - 2018-03-02
### Chores
- Fix release flow (retry)
- Add AppVeyor config
### Features
- Add template for `Keep a changelog` to the `--init` option
- Supports vim like `j/k` keybind with item selection of `--init`
### Pull Requests
- Merge pull request [#11](https://github.com/git-chglog/git-chglog/issues/11) from git-chglog/develop
- Merge pull request [#10](https://github.com/git-chglog/git-chglog/issues/10) from mattn/fix-test
- Merge pull request [#9](https://github.com/git-chglog/git-chglog/issues/9) from mattn/windows-color
### Bug Fixes
- Support Windows colors :tada: ([@mattn](https://github.com/mattn))
- Fixed several bugs in Windows
<a name="0.1.0"></a>
## [0.1.0] - 2018-02-25
### Bug Fixes
- Fix a bug that `Commit.Revert.Header` is not converted by `GitHubProcessor`
- Fix error message when `Tag` can not be acquired
- Fix `Revert` of template created by Initializer
### Chores
- Fix release scripts
- Remove unnecessary task
- Add coverage measurement task for local confirmation
- Change release method of git tag on TravisCI
### Code Refactoring
- Refactor `Initializer` to testable
@ -385,19 +153,14 @@
- Add Git Basic to commit message format
- Add preview to the commit message format of `--init` option
### Pull Requests
- Merge pull request [#8](https://github.com/git-chglog/git-chglog/issues/8) from git-chglog/feat/0.0.3
- Merge pull request [#6](https://github.com/git-chglog/git-chglog/issues/6) from git-chglog/chore/coverage
- Merge pull request [#4](https://github.com/git-chglog/git-chglog/issues/4) from paralax/patch-1
- Merge pull request [#5](https://github.com/git-chglog/git-chglog/issues/5) from git-chglog/develop
- Merge pull request [#1](https://github.com/git-chglog/git-chglog/issues/1) from git-chglog/develop
<a name="0.0.2"></a>
## [0.0.2] - 2018-02-18
### Chores
- Fix release script
- Add release process
### Bug Fixes
- Fix a bug that `Commit.Revert.Header` is not converted by `GitHubProcessor`
### Features
- Add preview to the commit message format of `--init` option
<a name="0.0.1"></a>
@ -405,17 +168,6 @@
### Bug Fixes
- Fix parsing of revert and body
### Chores
- Fix timezone in TravisCI
- Add travis configuration
- Add Makefile for task management
- Fix testcase depending on datetime
- Update vendor packages
- Add e2e tests
- Setup gitignore
- Initial commit
- **editor:** Add Editorconfig
### Code Refactoring
- Fix typo
- Change to return an error if corresponding commit is empty
@ -430,16 +182,7 @@
- First implement
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/v0.15.4...HEAD
[v0.15.4]: https://github.com/git-chglog/git-chglog/compare/v0.15.2...v0.15.4
[v0.15.2]: https://github.com/git-chglog/git-chglog/compare/v0.15.1...v0.15.2
[v0.15.1]: https://github.com/git-chglog/git-chglog/compare/v0.15.0...v0.15.1
[v0.15.0]: https://github.com/git-chglog/git-chglog/compare/v0.14.2...v0.15.0
[v0.14.2]: https://github.com/git-chglog/git-chglog/compare/v0.14.1...v0.14.2
[v0.14.1]: https://github.com/git-chglog/git-chglog/compare/v0.14.0...v0.14.1
[v0.14.0]: https://github.com/git-chglog/git-chglog/compare/v0.13.0...v0.14.0
[v0.13.0]: https://github.com/git-chglog/git-chglog/compare/v0.12.0...v0.13.0
[v0.12.0]: https://github.com/git-chglog/git-chglog/compare/v0.11.2...v0.12.0
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/v0.11.2...HEAD
[v0.11.2]: https://github.com/git-chglog/git-chglog/compare/v0.11.1...v0.11.2
[v0.11.1]: https://github.com/git-chglog/git-chglog/compare/v0.11.0...v0.11.1
[v0.11.0]: https://github.com/git-chglog/git-chglog/compare/v0.10.0...v0.11.0

View file

@ -2,21 +2,22 @@
Thank you for contributing `git-chglog` :tada:
## Templates
Please use issue/PR templates which are inserted automatically.
## Found a Bug?
If you find a bug in the source code, you can help us by [submitting an issue]
to our [GitHub Repository]. Even better, you can submit a Pull Request with a
fix.
If you find a bug in the source code, you can help us by [submitting an issue](https://github.com/git-chglog/git-chglog/issues) to our [GitHub Repository](https://github.com/git-chglog/git-chglog). Even better, you can submit a Pull Request with a fix.
## Commit Message Format
A format influenced by [Angular commit message].
A format influenced by [Angular commit message](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit-message-format).
```text
```
<type>: <subject>
<BLANK LINE>
<body>
@ -24,31 +25,26 @@ A format influenced by [Angular commit message].
<footer>
```
### Type
Must be one of the following:
- **docs:** Documention only changes
- **ci:** Changes to our CI configuration files and scripts
- **chore:** Updating Makefile etc, no production code changes
- **feat:** A new feature
- **fix:** A bug fix
- **perf:** A code change that improves performance
- **refactor:** A code change that neither fixes a bug nor adds a feature
- **style:** Changes that do not affect the meaning of the code
- **test:** Adding missing tests or correcting existing tests
* **docs:** Documention only changes
* **ci:** Changes to our CI configuration files and scripts
* **chore:** Updating Makefile etc, no production code changes
* **feat:** A new feature
* **fix:** A bug fix
* **perf:** A code change that improves performance
* **refactor:** A code change that neither fixes a bug nor adds a feature
* **style:** Changes that do not affect the meaning of the code
* **test:** Adding missing tests or correcting existing tests
### Footer
The footer should contain a [closing reference to an issue] if any.
The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
The **footer** should contain any information about **Breaking Changes** and is
also the place to reference GitHub issues that this commit **Closes**.
The **footer** should contain any information about **Breaking Changes** and is also the place to reference GitHub issues that this commit **Closes**.
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space
or two newlines. The rest of the commit message is then used for this.
[submitting an issue]: https://github.com/git-chglog/git-chglog/issues
[GitHub Repository]: https://github.com/git-chglog/git-chglog
[Angular commit message]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit-message-format
[closing reference to an issue]: https://help.github.com/articles/closing-issues-via-commit-messages/
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.

View file

@ -1,12 +0,0 @@
FROM alpine
RUN apk add --no-cache git && \
mkdir /workdir && \
git config --global --add safe.directory /workdir
COPY git-chglog /usr/local/bin/git-chglog
WORKDIR /workdir
RUN chmod +x /usr/local/bin/git-chglog
ENTRYPOINT [ "/usr/local/bin/git-chglog" ]

108
Makefile
View file

@ -1,108 +1,22 @@
# Build variables
VERSION ?= $(shell git describe --tags --always)
# Go variables
GO ?= go
GOOS ?= $(shell $(GO) env GOOS)
GOARCH ?= $(shell $(GO) env GOARCH)
GOHOST ?= GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO)
LDFLAGS ?= "-X main.version=$(VERSION)"
# Docker variables
DEFAULT_TAG ?= $(shell echo "$(VERSION)" | tr -d 'v')
DOCKER_IMAGE := quay.io/git-chglog/git-chglog
DOCKER_TAG ?= $(DEFAULT_TAG)
.PHONY: all
all: help
###############
##@ Development
.PHONY: clean
clean: ## Clean workspace
@ $(MAKE) --no-print-directory log-$@
clean:
rm -rf ./dist/
rm -rf ./git-chglog
rm -rf $(GOPATH)/bin/git-chglog
rm -rf cover.out
.PHONY: test
test: ## Run tests
@ $(MAKE) --no-print-directory log-$@
$(GOHOST) test -covermode atomic -coverprofile cover.out -v ./...
.PHONY: lint
lint: ## Run linters
@ $(MAKE) --no-print-directory log-$@
golangci-lint run
#########
##@ Build
.PHONY: build
build: ## Build git-chglog
@ $(MAKE) --no-print-directory log-$@
CGO_ENABLED=0 $(GOHOST) build -ldflags=$(LDFLAGS) -o git-chglog ./cmd/git-chglog
build:
go build -o git-chglog ./cmd/git-chglog
.PHONY: test
test:
go test -covermode atomic -coverprofile cover.out -v ./...
.PHONY: install
install: ## Install git-chglog
@ $(MAKE) --no-print-directory log-$@
$(GOHOST) install ./cmd/git-chglog
.PHONY: docker
docker: build ## Build Docker image
@ $(MAKE) --no-print-directory log-$@
docker build --pull --tag $(DOCKER_IMAGE):$(DOCKER_TAG) .
.PHONY: push
push: ## Push Docker image
@ $(MAKE) --no-print-directory log-$@
docker push $(DOCKER_IMAGE):$(DOCKER_TAG)
###########
##@ Release
install:
go install ./cmd/git-chglog
.PHONY: changelog
changelog: build ## Generate changelog
@ $(MAKE) --no-print-directory log-$@
./git-chglog --next-tag $(VERSION) -o CHANGELOG.md
.PHONY: release
release: changelog ## Release a new tag
@ $(MAKE) --no-print-directory log-$@
git add CHANGELOG.md
git commit -m "chore: update changelog for $(VERSION)"
git tag $(VERSION)
git push origin master $(VERSION)
########
##@ Help
.PHONY: help
help: ## Display this help
@awk \
-v "col=\033[36m" -v "nocol=\033[0m" \
' \
BEGIN { \
FS = ":.*##" ; \
printf "Usage:\n make %s<target>%s\n", col, nocol \
} \
/^[a-zA-Z_-]+:.*?##/ { \
printf " %s%-12s%s %s\n", col, $$1, nocol, $$2 \
} \
/^##@/ { \
printf "\n%s%s%s\n", nocol, substr($$0, 5), nocol \
} \
' $(MAKEFILE_LIST)
log-%:
@grep -h -E '^$*:.*?## .*$$' $(MAKEFILE_LIST) | \
awk \
'BEGIN { \
FS = ":.*?## " \
}; \
{ \
printf "\033[36m==> %s\033[0m\n", $$2 \
}'
changelog:
@git-chglog --next-tag $(tag) $(tag)

270
README.md
View file

@ -4,12 +4,14 @@
[![godoc.org](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/git-chglog/git-chglog)
[![Actions Status](https://github.com/git-chglog/git-chglog/workflows/tests/badge.svg)](https://github.com/git-chglog/git-chglog/actions)
[![AppVeyor](https://img.shields.io/appveyor/ci/tsuyoshiwada/git-chglog/master.svg?style=flat-square)](https://ci.appveyor.com/project/tsuyoshiwada/git-chglog/branch/master)
[![Coverage Status](https://img.shields.io/coveralls/github/git-chglog/git-chglog.svg?style=flat-square)](https://coveralls.io/github/git-chglog/git-chglog?branch=master)
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/git-chglog/git-chglog/blob/master/LICENSE)
> CHANGELOG generator implemented in Go (Golang).
> CHANGELOG generator implemented in Go (Golang).
> _Anytime, anywhere, Write your CHANGELOG._
## Table of Contents
- [git-chglog](#git-chglog)
@ -22,7 +24,6 @@
- [Scoop (for Windows users)](#scoop-for-windows-users)
- [asdf](#asdf)
- [Go users](#go-users)
- [Docker](#docker)
- [Test Installation](#test-installation)
- [Quick Start](#quick-start)
- [CLI Usage](#cli-usage)
@ -33,7 +34,6 @@
- [`template`](#template)
- [`info`](#info)
- [`options`](#options)
- [`options.sort`](#optionssort)
- [`options.commits`](#optionscommits)
- [`options.commit_groups`](#optionscommit_groups)
- [`options.header`](#optionsheader)
@ -45,36 +45,35 @@
- [Templates](#templates)
- [Supported Styles](#supported-styles)
- [Jira Integration](#jira-integration)
- [1. Change the header parse pattern to recognize Jira issue id in the configure file](#1-change-the-header-parse-pattern-to-recognize-jira-issue-id-in-the-configure-file)
- [2. Add Jira configuration to the configure file](#2-add-jira-configuration-to-the-configure-file)
- [3. Update the template to show Jira data](#3-update-the-template-to-show-jira-data)
- [FAQ](#faq)
- [TODO](#todo)
- [Thanks](#thanks)
- [Contributing](#contributing)
- [Development](#development)
- [Release Process](#release-process)
- [Feedback](#feedback)
- [Development](#development)
- [Feedback](#feedback)
- [CHANGELOG](#changelog)
- [Related Projects](#related-projects)
- [License](#license)
## Features
- :recycle: High portability
- It works with single binary. Therefore, any project (environment) can be used.
- :beginner: Simple usability
- The CLI usage is very simple and has low learning costs.
- For example, the simplest command is `$ git-chglog`.
- :rocket: High flexibility
- Commit message format and ...
- CHANGELOG's style (Template) and ...
- etc ...
* :recycle: High portability
- It works with single binary. Therefore, any project (environment) can be used.
* :beginner: Simple usability
- The CLI usage is very simple and has low learning costs.
- For example, the simplest command is `$ git-chglog`.
* :rocket: High flexibility
- Commit message format and ...
- CHANGELOG's style (Template) and ...
- etc ...
## How it works
`git-chglog` internally uses the `git` command to get data to include in the
CHANGELOG. The basic steps are as follows.
`git-chglog` internally uses the `git` command to get data to include in the CHANGELOG.
The basic steps are as follows.
1. Get all the tags.
1. Get the commits contained between `tagA` and `tagB`.
@ -82,8 +81,7 @@ CHANGELOG. The basic steps are as follows.
## Getting Started
We will start with installation and introduce the steps up to the automatic generation
of the configuration file and template.
We will start with installation and introduce the steps up to the automatic generation of the configuration file and template.
### Installation
@ -92,64 +90,54 @@ Please install `git-chglog` in a way that matches your environment.
#### [Homebrew](https://brew.sh) (for macOS users)
```bash
brew tap git-chglog/git-chglog
brew install git-chglog
$ brew tap git-chglog/git-chglog
$ brew install git-chglog
```
#### [Scoop](https://scoop.sh) (for Windows users)
```bash
scoop install git-chglog
```
$ scoop install git-chglog
```
#### [asdf](https://asdf-vm.com/)
```bash
asdf plugin-add git-chglog https://github.com/GoodwayGroup/asdf-git-chglog.git
asdf install git-chglog latest
$ asdf plugin-add git-chglog https://github.com/GoodwayGroup/asdf-git-chglog.git
$ asdf install git-chglog latest
```
#### Go users
```bash
go install github.com/git-chglog/git-chglog/cmd/git-chglog@latest
$ go get -u github.com/git-chglog/git-chglog/cmd/git-chglog
```
### [Docker](https://www.docker.com/)
The compiled docker images are maintained on [quay.io](https://quay.io/repository/git-chglog/git-chglog).
We maintain the following tags:
- `edge`: Image that is build from the current `HEAD` of the main line branch.
- `latest`: Image that is built from the [latest released version](https://github.com/git-chglog/git-chglog/releases)
- `x.y.y` (versions): Images that are build from the tagged versions within Github.
```bash
docker pull quay.io/git-chglog/git-chglog:latest
docker run -v "$PWD":/workdir quay.io/git-chglog/git-chglog --version
```
---
If you are using another platform, you can download a binary from the [releases page]
and place it in a directory in your `$PATH`.
If you are using another platform, you can download a binary from the [releases page](https://github.com/git-chglog/git-chglog/releases) and place it in a directory in your `$PATH`.
### Test Installation
You can check with the following command whether the `git-chglog` command was
included in a directory that is in your `$PATH`.
You can check with the following command whether the `git-chglog` command was included in a directory that is in your `$PATH`.
```bash
$ git-chglog --version
# outputs the git-chglog version
```
### Quick Start
`git-chglog` requires configuration files and templates to generate a CHANGELOG.
`git-chglog` requires configuration files and templates to generate a CHANGELOG.
However, it is a waste of time to create configuration files and templates from scratch.
Therefore we recommend using the `--init` option which will create them interactively :+1:
```bash
git-chglog --init
$ git-chglog --init
```
![init option demo](./docs/assets/init.gif)
@ -158,26 +146,24 @@ git-chglog --init
You are now ready for configuration files and templates!
Let's immediately generate a CHANGELOG of your project.
By doing the following simple command, Markdown for your CHANGELOG is displayed
on stdout.
Let's immediately generate a CHANGELOG of your project.
By doing the following simple command, Markdown for your CHANGELOG is displayed on stdout.
```bash
git-chglog
$ git-chglog
```
Use `-o` (`--output`) option if you want to output to a file instead of stdout.
```bash
git-chglog -o CHANGELOG.md
$ git-chglog -o CHANGELOG.md
```
---
You now know basic usage of `git-chglog`!
In order to make a better CHANGELOG, please refer to the following document and
customize it.
In order to make a better CHANGELOG, please refer to the following document and customize it.
## CLI Usage
@ -210,7 +196,6 @@ OPTIONS:
--jira-url value Jira URL [$JIRA_URL]
--jira-username value Jira username [$JIRA_USERNAME]
--jira-token value Jira token [$JIRA_TOKEN]
--sort value Specify how to sort tags; currently supports "date" or by "semver" (default: date)
--help, -h show help (default: false)
--version, -v print the version (default: false)
@ -261,8 +246,7 @@ The table below shows Query patterns and summaries, and Query examples.
## Configuration
The `git-chglog` configuration is a yaml file. The default location is
`.chglog/config.yml`.
The `git-chglog` configuration is a yaml file. The default location is `.chglog/config.yml`.
Below is a complete list that you can use with `git-chglog`.
@ -276,7 +260,6 @@ info:
options:
tag_filter_pattern: '^v'
sort: "date"
commits:
filters:
@ -331,8 +314,7 @@ Git execution command.
### `style`
CHANGELOG style. Automatic linking of issues and notices, initial value setting
such as merges etc. are done automatically.
CHANGELOG style. Automatic linking of issues and notices, initial value setting such as merges etc. are done automatically.
| Required | Type | Default | Description |
|:---------|:-------|:---------|:-------------------------------------------------------|
@ -340,8 +322,7 @@ such as merges etc. are done automatically.
### `template`
Path for the template file. It is specified by a relative path from the setting
file. Absolute paths are also ok.
Path for the template file. It is specified by a relative path from the setting file. Absolute paths are also ok.
| Required | Type | Default | Description |
|:---------|:-------|:---------------------|:------------|
@ -349,8 +330,7 @@ file. Absolute paths are also ok.
### `info`
Metadata for CHANGELOG. Depending on Style, it is sometimes used in processing,
so it is recommended to specify it.
Metadata for CHANGELOG. Depending on Style, it is sometimes used in processing, so it is recommended to specify it.
| Key | Required | Type | Default | Description |
|:-----------------|:---------|:-------|:--------------|:-----------------------|
@ -361,22 +341,14 @@ so it is recommended to specify it.
Options used to process commits.
#### `options.sort`
Options concerning the acquisition and sort of commits.
| Required | Type | Default | Description |
|:---------|:------------|:----------|:--------------------------------------------------------------------------------------------------------------------|
| N | String | `"date"` | Defines how tags are sorted in the generated change log. Values: "date", "semver". |
#### `options.commits`
Options concerning the acquisition and sort of commits.
| Key | Required | Type | Default | Description |
|:----------|:---------|:------------|:----------|:----------------------------------------------------------------------------------------------------|
| `filters` | N | Map in List | none | Filter by using `Commit` properties and values. Filtering is not done by specifying an empty value. |
| `sort_by` | N | String | `"Scope"` | Property name to use for sorting `Commit`. See [Commit]. |
| Key | Required | Type | Default | Description |
|:----------|:---------|:------------|:----------|:--------------------------------------------------------------------------------------------------------------------|
| `filters` | N | Map in List | none | Filter by using `Commit` properties and values. Filtering is not done by specifying an empty value. |
| `sort_by` | N | String | `"Scope"` | Property name to use for sorting `Commit`. See [Commit](https://godoc.org/github.com/git-chglog/git-chglog#Commit). |
#### `options.commit_groups`
@ -442,22 +414,9 @@ Options to detect notes contained in commit bodies.
## Templates
The `git-chglog` template uses the `text/template` package and enhanced templating functions provided by [Sprig]. For basic usage please refer to the following.
The `git-chglog` template uses the `text/template` package. For basic usage please refer to the following.
- [text/template](https://golang.org/pkg/text/template/)
- [Sprig]
We have implemented the following custom template functions. These override functions provided by [Sprig].
| Name | Signature | Description |
| :----------- | :-------------------------------------------- | :---------------------------------------------------------------------------- |
| `contains` | `func(s, substr string) bool` | Reports whether `substr` is within `s` using `strings.Contains` |
| `datetime` | `func(layout string, input time.Time) string` | Generate a formatted Date string based on layout |
| `hasPrefix` | `func(s, prefix string) bool` | Tests whether the string `s` begins with `prefix` using `strings.HasPrefix` |
| `hasSuffix` | `func(s, suffix string) bool` | Tests whether the string `s` ends with `suffix`. using `strings.HasPrefix` |
| `indent` | `func(s string, n int) string` | Indent all lines of `s` by `n` spaces |
| `replace` | `func(s, old, new string, n int) string` | Replace `old` with `new` within string `s`, `n` times using `strings.Replace` |
| `upperFirst` | `func(s string) string` | Upper case the first character of a string |
> [text/template](https://golang.org/pkg/text/template/)
If you are not satisfied with the prepared template please try customizing one.
@ -536,20 +495,20 @@ See the godoc [RenderData][doc-render-data] documentation for available variable
| [GitLab](https://about.gitlab.com/) | :white_check_mark: | Mentions automatic link. Automatic link to references. |
| [Bitbucket](https://bitbucket.org/product) | :white_check_mark: | Mentions automatic link. Automatic link to references. |
> :memo: Even with styles that are not yet supported, it is possible to make
ordinary CHANGELOG.
> :memo: Even with styles that are not yet supported, it is possible to make ordinary CHANGELOG.
## Jira Integration
Jira is a popular project management tool. When a project uses Jira to track
feature development and bug fixes, it may also want to generate change log based
information stored in Jira. With embedding a Jira story id in git commit header,
the git-chglog tool may automatically fetch data of the story from Jira, those
data then can be used to render the template.
Jira is a popular project management tool. When a project uses Jira to track feature development and bug fixes,
it may also want to generate change log based information stored in Jira. With embedding a Jira story id in git
commit header, the git-chglog tool may automatically fetch data of the story from Jira, those data then can be
used to render the template.
Take the following steps to add Jira integration:
### 1. Change the header parse pattern to recognize Jira issue id in the configure file
#### 1. Change the header parse pattern to recognize Jira issue id in the configure file.
__Where Jira issue is identical Jira story.__
@ -560,16 +519,16 @@ The following is a sample pattern:
pattern: "^(?:(\\w*)|(?:\\[(.*)\\])?)\\:\\s(.*)$"
pattern_maps:
- Type
- JiraIssueID
- JiraIssueId
- Subject
```
This sample pattern can match both forms of commit headers:
- `feat: new feature of something`
- `[JIRA-ID]: something`
* `feat: new feature of something`
* `[JIRA-ID]: something`
### 2. Add Jira configuration to the configure file
#### 2. Add Jira configuration to the configure file.
The following is a sample:
@ -586,22 +545,20 @@ The following is a sample:
description_pattern: "<changelog>(.*)</changelog>"
```
Here you need to define Jira URL, access username and token (password). If you
don't want to write your Jira access credential in configure file, you may define
them with environment variables: `JIRA_URL`, `JIRA_USERNAME` and `JIRA_TOKEN`.
Here you need to define Jira URL, access username and token (password). If you don't want to
write your Jira access credential in configure file, you may define them with environment variables:
`JIRA_URL`, `JIRA_USERNAME` and `JIRA_TOKEN`.
You also needs to define a issue type map. In above sample, Jira issue type `Task`
will be mapped to `fix` and `Story` will be mapped to `feat`.
You also needs to define a issue type map. In above sample, Jira issue type `Task` will be
mapped to `fix` and `Story` will be mapped to `feat`.
As a Jira story's description could be very long, you might not want to include
the entire description into change log. In that case, you may define `description_pattern`
like above, so that only content embraced with `<changelog> ... </changelog>`
will be included.
As a Jira story's description could be very long, you might not want to include the entire
description into change log. In that case, you may define `description_pattern` like above,
so that only content embraced with `<changelog> ... </changelog>` will be included.
### 3. Update the template to show Jira data
#### 3. Update the template to show Jira data.
In the template, if a commit contains a Jira issue id, then you may show Jira
data. For example:
In the template, if a commit contains a Jira issue id, then you may show Jira data. For example:
```markdown
{{ range .CommitGroups -}}
@ -616,22 +573,21 @@ data. For example:
Within a `Commit`, the following Jira data can be used in template:
- `.JiraIssue.Summary` - Summary of the Jira story
- `.JiraIssue.Description` - Description of the Jira story
- `.JiraIssue.Type` - Original type of the Jira story, and `.Type` will be mapped type.
- `.JiraIssue.Labels` - A list of strings, each is a Jira label.
* `.JiraIssue.Summary` - Summary of the Jira story
* `.JiraIssue.Description` - Description of the Jira story
* `.JiraIssue.Type` - Original type of the Jira story, and `.Type` will be mapped type.
* `.JiraIssue.Labels` - A list of strings, each is a Jira label.
## FAQ
<details>
<summary>Why do not you output files by default?</summary>
This is not for the purpose of completely automating the generation of CHANGELOG
files, it is only for assisting generation.
This is not for the purpose of completely automating the generation of CHANGELOG files, it is only for assisting generation.
It is ideal to describe everything included in CHANGELOG in your commits. But
actually it is very difficult to do it perfectly.
It is ideal to describe everything included in CHANGELOG in your commits. But actually it is very difficult to do it perfectly.
There are times when you need to edit the generated output to write a great CHANGELOG.
There are times when you need to edit the generated output to write a great CHANGELOG.
By displaying it on the standard output, it makes it easy to change the contents.
</details>
@ -641,86 +597,63 @@ Within a `Commit`, the following Jira data can be used in template:
Yes, it can be solved by using the `--next-tag` flag.
For example, let's say you want to upgrade your project to `2.0.0`.
For example, let's say you want to upgrade your project to `2.0.0`.
You can create CHANGELOG containing `2.0.0` as follows.
```bash
git-chglog --next-tag 2.0.0 -o CHANGELOG.md
git commit -am "release 2.0.0"
git tag 2.0.0
$ git-chglog --next-tag 2.0.0 -o CHANGELOG.md
$ git commit -am "release 2.0.0"
$ git tag 2.0.0
```
The point to notice is that before actually creating a tag with `git`, it is
conveying the next version with `--next-tag` :+1:
The point to notice is that before actually creating a tag with `git`, it is conveying the next version with `--next-tag` :+1:
This is a step that is necessary for project operation in many cases.
</details>
<details>
<summary>Can I generate a CHANGELOG based on certain tags?</summary>
Yes, it can be solved by use the `--tag-filter-pattern` flag.
For example, the following command will only include tags starting with "v":
```bash
git-chglog --tag-filter-pattern '^v'
$ git-chglog --tag-filter-pattern '^v'
```
</details>
## TODO
- [x] Windows Support
- [x] More styles (GitHub, GitLab, Bitbucket :tada:)
- [ ] Snippetization of configuration files (improvement of reusability)
- [ ] More test test test ... (and example)
* [x] Windows Support
* [x] More styles (GitHub, GitLab, Bitbucket :tada:)
* [ ] Snippetization of configuration files (improvement of reusability)
* [ ] More test test test ... (and example)
## Thanks
`git-chglog` is inspired by [conventional-changelog]. Thank you!
`git-chglog` is inspired by [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog). Thank you!
## Contributing
We always welcome your contributions :clap:
We alway welcome your contributions :clap:
## Development
### Development
1. Use Golang version `>= 1.24`
1. Fork (https://github.com/git-chglog/git-chglog) :tada:
1. Create a feature branch :coffee:
1. Run test suite with the `$ make test` command and confirm that it passes :zap:
1. Run linters with the `$ make lint` command and confirm it passes :broom:
- The project uses [golangci-lint]
1. Commit your changes :memo:
1. Rebase your local changes against the `master` branch :bulb:
1. Create new Pull Request :love_letter:
Bugs, feature requests and comments are more than welcome in the [issues].
Bugs, feature requests and comments are more than welcome in the [issues](https://github.com/git-chglog/git-chglog/issues).
## Release Process
### Feedback
There is a `release` target within the Makefile that wraps up the steps to
release a new version.
> NOTE: Pass the `VERSION` variable when running the command to properly set
> the tag version for the release.
```bash
$ VERSION=vX.Y.Z make release
# EXAMPLE:
$ VERSION=v0.11.3 make release
```
Once the `tag` has been pushed, the `goreleaser` github action will take care
of the rest.
## Feedback
I would like to make `git-chglog` a better tool.
I would like to make `git-chglog` a better tool.
The goal is to be able to use in various projects.
Therefore, your feedback is very useful.
Therefore, your feedback is very useful.
I am very happy to tell you your opinions on Issues and PR :heart:
## CHANGELOG
@ -729,20 +662,13 @@ See [CHANGELOG.md](./CHANGELOG.md)
## Related Projects
- [git-chglog/artwork] - Assets for `git-chglog`.
* [git-chglog/artwork](https://github.com/git-chglog/artwork) - Assets for `git-chglog`.
## License
[MIT © tsuyoshiwada](./LICENSE)
[releases page]: https://github.com/git-chglog/git-chglog/releases
[Commit]: https://godoc.org/github.com/git-chglog/git-chglog#Commit
[doc-commit]: https://godoc.org/github.com/git-chglog/git-chglog#Commit
[doc-commit-group]: https://godoc.org/github.com/git-chglog/git-chglog#CommitGroup
[doc-ref]: https://godoc.org/github.com/git-chglog/git-chglog#Ref
[doc-render-data]: https://godoc.org/github.com/git-chglog/git-chglog#RenderData
[conventional-changelog]: https://github.com/conventional-changelog/conventional-changelog
[golangci-lint]: https://golangci-lint.run/usage/install/#local-installation
[issues]: https://github.com/git-chglog/git-chglog/issues
[git-chglog/artwork]: https://github.com/git-chglog/artwork
[Sprig]: http://masterminds.github.io/sprig

View file

@ -5,15 +5,13 @@ import (
"errors"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
"text/template"
"time"
"github.com/Masterminds/sprig/v3"
"github.com/tsuyoshiwada/go-gitcmd"
gitcmd "github.com/tsuyoshiwada/go-gitcmd"
)
// Options is an option used to process commits
@ -21,7 +19,6 @@ type Options struct {
Processor Processor
NextTag string // Treat unreleased commits as specified tags (EXPERIMENTAL)
TagFilterPattern string // Filter tag by regexp
Sort string // Specify how to sort tags; currently supports "date" (default) or by "semver".
NoCaseSensitive bool // Filter commits in a case insensitive way
CommitFilters map[string][]string // Filter by using `Commit` properties and values. Filtering is not done by specifying an empty value
CommitSortBy string // Property name to use for sorting `Commit` (e.g. `Scope`)
@ -40,7 +37,7 @@ type Options struct {
NoteKeywords []string // Keyword list to find `Note`. A semicolon is a separator, like `<keyword>:` (e.g. `BREAKING CHANGE`)
JiraUsername string
JiraToken string
JiraURL string
JiraUrl string
JiraTypeMaps map[string]string
JiraIssueDescriptionPattern string
Paths []string // Path filter
@ -122,7 +119,7 @@ func NewGenerator(logger *Logger, config *Config) *Generator {
return &Generator{
client: client,
config: config,
tagReader: newTagReader(client, config.Options.TagFilterPattern, config.Options.Sort),
tagReader: newTagReader(client, config.Options.TagFilterPattern),
tagSelector: newTagSelector(),
commitParser: newCommitParser(logger, client, jiraClient, config),
commitExtractor: newCommitExtractor(config.Options),
@ -132,21 +129,16 @@ func NewGenerator(logger *Logger, config *Config) *Generator {
// Generate gets the commit based on the specified tag `query` and writes the result to `io.Writer`
//
// tag `query` can be specified with the following rule
//
// <old>..<new> - Commit contained in `<new>` tags from `<old>` (e.g. `1.0.0..2.0.0`)
// <tagname>.. - Commit from the `<tagname>` to the latest tag (e.g. `1.0.0..`)
// ..<tagname> - Commit from the oldest tag to `<tagname>` (e.g. `..1.0.0`)
// <tagname> - Commit contained in `<tagname>` (e.g. `1.0.0`)
// <old>..<new> - Commit contained in `<new>` tags from `<old>` (e.g. `1.0.0..2.0.0`)
// <tagname>.. - Commit from the `<tagname>` to the latest tag (e.g. `1.0.0..`)
// ..<tagname> - Commit from the oldest tag to `<tagname>` (e.g. `..1.0.0`)
// <tagname> - Commit contained in `<tagname>` (e.g. `1.0.0`)
func (gen *Generator) Generate(w io.Writer, query string) error {
back, err := gen.workdir()
if err != nil {
return err
}
defer func() {
if err = back(); err != nil {
log.Fatal(err)
}
}()
defer back()
tags, first, err := gen.getTags(query)
if err != nil {
@ -277,7 +269,7 @@ func (gen *Generator) getTags(query string) ([]*Tag, string, error) {
// Assign the date with `readVersions()`
tags = append([]*Tag{
{
&Tag{
Name: next,
Subject: next,
Previous: previous,
@ -326,6 +318,30 @@ func (gen *Generator) render(w io.Writer, unreleased *Unreleased, versions []*Ve
"datetime": func(layout string, input time.Time) string {
return input.Format(layout)
},
// check whether substs is withing s
"contains": func(s, substr string) bool {
return strings.Contains(s, substr)
},
// check whether s begins with prefix
"hasPrefix": func(s, prefix string) bool {
return strings.HasPrefix(s, prefix)
},
// check whether s ends with suffix
"hasSuffix": func(s, suffix string) bool {
return strings.HasSuffix(s, suffix)
},
// replace the first n instances of old with new
"replace": func(s, old, new string, n int) string {
return strings.Replace(s, old, new, n)
},
// lower case a string
"lower": func(s string) string {
return strings.ToLower(s)
},
// upper case a string
"upper": func(s string) string {
return strings.ToUpper(s)
},
// upper case the first character of a string
"upperFirst": func(s string) string {
if len(s) > 0 {
@ -333,26 +349,11 @@ func (gen *Generator) render(w io.Writer, unreleased *Unreleased, versions []*Ve
}
return ""
},
// indent all lines of s n spaces
"indent": func(s string, n int) string {
if len(s) == 0 {
return ""
}
pad := strings.Repeat(" ", n)
return pad + strings.ReplaceAll(s, "\n", "\n"+pad)
},
// While Sprig provides these functions, they change the standard input
// order which leads to a regression. For an example see:
// https://github.com/Masterminds/sprig/blob/master/functions.go#L149
"contains": strings.Contains,
"hasPrefix": strings.HasPrefix,
"hasSuffix": strings.HasSuffix,
"replace": strings.Replace,
}
fname := filepath.Base(gen.config.Template)
t := template.Must(template.New(fname).Funcs(sprig.TxtFuncMap()).Funcs(fmap).ParseFiles(gen.config.Template))
t := template.Must(template.New(fname).Funcs(fmap).ParseFiles(gen.config.Template))
return t.Execute(w, &RenderData{
Info: gen.config.Info,

View file

@ -32,17 +32,17 @@ func TestMain(m *testing.M) {
func setup(dir string, setupRepo func(commitFunc, tagFunc, gitcmd.Client)) {
testDir := filepath.Join(cwd, testRepoRoot, dir)
_ = os.RemoveAll(testDir)
_ = os.MkdirAll(testDir, os.ModePerm)
_ = os.Chdir(testDir)
os.RemoveAll(testDir)
os.MkdirAll(testDir, os.ModePerm)
os.Chdir(testDir)
loc, _ := time.LoadLocation("UTC")
time.Local = loc
git := gitcmd.New(nil)
_, _ = git.Exec("init")
_, _ = git.Exec("config", "user.name", "test_user")
_, _ = git.Exec("config", "user.email", "test@example.com")
git.Exec("init")
git.Exec("config", "user.name", "test_user")
git.Exec("config", "user.email", "test@example.com")
var commit = func(date, subject, body string) {
msg := subject
@ -51,21 +51,21 @@ func setup(dir string, setupRepo func(commitFunc, tagFunc, gitcmd.Client)) {
}
t, _ := time.Parse(internalTimeFormat, date)
d := t.Format("Mon Jan 2 15:04:05 2006 +0000")
_, _ = git.Exec("commit", "--allow-empty", "--date", d, "-m", msg)
git.Exec("commit", "--allow-empty", "--date", d, "-m", msg)
}
var tag = func(name string) {
_, _ = git.Exec("tag", name)
git.Exec("tag", name)
}
setupRepo(commit, tag, git)
_ = os.Chdir(cwd)
os.Chdir(cwd)
}
func cleanup() {
_ = os.Chdir(cwd)
_ = os.RemoveAll(filepath.Join(cwd, testRepoRoot))
os.Chdir(cwd)
os.RemoveAll(filepath.Join(cwd, testRepoRoot))
}
func TestGeneratorNotFoundTags(t *testing.T) {
@ -89,11 +89,9 @@ func TestGeneratorNotFoundTags(t *testing.T) {
buf := &bytes.Buffer{}
err := gen.Generate(buf, "")
expected := strings.TrimSpace(buf.String())
assert.Error(err)
assert.Contains(err.Error(), "git-tag does not exist")
assert.Equal("", expected)
assert.Equal("", buf.String())
}
func TestGeneratorNotFoundCommits(t *testing.T) {
@ -118,10 +116,8 @@ func TestGeneratorNotFoundCommits(t *testing.T) {
buf := &bytes.Buffer{}
err := gen.Generate(buf, "foo")
expected := strings.TrimSpace(buf.String())
assert.Error(err)
assert.Equal("", expected)
assert.Equal("", buf.String())
}
func TestGeneratorNotFoundCommitsOne(t *testing.T) {
@ -175,11 +171,9 @@ func TestGeneratorNotFoundCommitsOne(t *testing.T) {
buf := &bytes.Buffer{}
err := gen.Generate(buf, "foo")
expected := strings.TrimSpace(buf.String())
assert.Error(err)
assert.Contains(err.Error(), "\"foo\" was not found")
assert.Equal("", expected)
assert.Equal("", buf.String())
}
func TestGeneratorWithTypeScopeSubject(t *testing.T) {
@ -199,7 +193,7 @@ func TestGeneratorWithTypeScopeSubject(t *testing.T) {
tag("1.1.0")
commit("2018-01-03 00:00:00", "feat(context): Online breaking change", "BREAKING CHANGE: Online breaking change message.")
commit("2018-01-03 00:01:00", "feat(router): Multiple breaking change", `This is body,
commit("2018-01-03 00:01:00", "feat(router): Muliple breaking change", `This is body,
BREAKING CHANGE:
Multiple
@ -221,9 +215,8 @@ change message.`)
RepositoryURL: "https://github.com/git-chglog/git-chglog",
},
Options: &Options{
Sort: "date",
CommitFilters: map[string][]string{
"Type": {
"Type": []string{
"feat",
"fix",
},
@ -263,7 +256,7 @@ change message.`)
buf := &bytes.Buffer{}
err := gen.Generate(buf, "")
expected := strings.TrimSpace(buf.String())
output := strings.Replace(strings.TrimSpace(buf.String()), "\r\n", "\n", -1)
assert.Nil(err)
assert.Equal(`<a name="unreleased"></a>
@ -277,7 +270,7 @@ change message.`)
## [2.0.0-beta.0] - 2018-01-03
### Features
- **context:** Online breaking change
- **router:** Multiple breaking change
- **router:** Muliple breaking change
### BREAKING CHANGE
@ -309,7 +302,7 @@ Online breaking change message.
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/2.0.0-beta.0...HEAD
[2.0.0-beta.0]: https://github.com/git-chglog/git-chglog/compare/1.1.0...2.0.0-beta.0
[1.1.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...1.1.0`, expected)
[1.1.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...1.1.0`, output)
}
func TestGeneratorWithNextTag(t *testing.T) {
@ -336,10 +329,9 @@ func TestGeneratorWithNextTag(t *testing.T) {
RepositoryURL: "https://github.com/git-chglog/git-chglog",
},
Options: &Options{
Sort: "date",
NextTag: "3.0.0",
CommitFilters: map[string][]string{
"Type": {
"Type": []string{
"feat",
},
},
@ -360,7 +352,7 @@ func TestGeneratorWithNextTag(t *testing.T) {
buf := &bytes.Buffer{}
err := gen.Generate(buf, "")
expected := strings.TrimSpace(buf.String())
output := strings.Replace(strings.TrimSpace(buf.String()), "\r\n", "\n", -1)
assert.Nil(err)
assert.Equal(`<a name="unreleased"></a>
@ -387,11 +379,11 @@ func TestGeneratorWithNextTag(t *testing.T) {
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/3.0.0...HEAD
[3.0.0]: https://github.com/git-chglog/git-chglog/compare/2.0.0...3.0.0
[2.0.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...2.0.0`, expected)
[2.0.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...2.0.0`, output)
buf = &bytes.Buffer{}
err = gen.Generate(buf, "3.0.0")
expected = strings.TrimSpace(buf.String())
output = strings.Replace(strings.TrimSpace(buf.String()), "\r\n", "\n", -1)
assert.Nil(err)
assert.Equal(`<a name="unreleased"></a>
@ -405,7 +397,7 @@ func TestGeneratorWithNextTag(t *testing.T) {
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/3.0.0...HEAD
[3.0.0]: https://github.com/git-chglog/git-chglog/compare/2.0.0...3.0.0`, expected)
[3.0.0]: https://github.com/git-chglog/git-chglog/compare/2.0.0...3.0.0`, output)
}
func TestGeneratorWithTagFiler(t *testing.T) {
@ -432,7 +424,7 @@ func TestGeneratorWithTagFiler(t *testing.T) {
Options: &Options{
TagFilterPattern: "^v",
CommitFilters: map[string][]string{
"Type": {
"Type": []string{
"feat",
},
},
@ -453,7 +445,6 @@ func TestGeneratorWithTagFiler(t *testing.T) {
buf := &bytes.Buffer{}
err := gen.Generate(buf, "")
expected := strings.TrimSpace(buf.String())
assert.Nil(err)
assert.Equal(`<a name="unreleased"></a>
@ -467,165 +458,6 @@ func TestGeneratorWithTagFiler(t *testing.T) {
- **core:** version dev-1.0.0
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/v1.0.0...HEAD`, expected)
}
func TestGeneratorWithTrimmedBody(t *testing.T) {
assert := assert.New(t)
testName := "trimmed_body"
setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
commit("2018-01-01 00:00:00", "feat: single line commit", "")
commit("2018-01-01 00:01:00", "feat: multi-line commit", `
More details about the change and why it went in.
BREAKING CHANGE:
When using .TrimmedBody Notes are not included and can only appear in the Notes section.
Signed-off-by: First Last <first.last@mail.com>
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>`)
commit("2018-01-01 00:00:00", "feat: another single line commit", "")
tag("1.0.0")
})
gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
&Config{
Bin: "git",
WorkingDir: filepath.Join(testRepoRoot, testName),
Template: filepath.Join(cwd, "testdata", testName+".md"),
Info: &Info{
Title: "CHANGELOG Example",
RepositoryURL: "https://github.com/git-chglog/git-chglog",
},
Options: &Options{
CommitFilters: map[string][]string{
"Type": {
"feat",
},
},
CommitSortBy: "Scope",
CommitGroupBy: "Type",
CommitGroupSortBy: "Title",
CommitGroupTitleMaps: map[string]string{
"feat": "Features",
},
HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
HeaderPatternMaps: []string{
"Type",
"Scope",
"Subject",
},
NoteKeywords: []string{
"BREAKING CHANGE",
},
},
})
buf := &bytes.Buffer{}
err := gen.Generate(buf, "")
expected := strings.TrimSpace(buf.String())
assert.Nil(err)
assert.Equal(`<a name="unreleased"></a>
## [Unreleased]
<a name="1.0.0"></a>
## 1.0.0 - 2018-01-01
### Features
- another single line commit
- multi-line commit
More details about the change and why it went in.
- single line commit
### BREAKING CHANGE
When using .TrimmedBody Notes are not included and can only appear in the Notes section.
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/1.0.0...HEAD`, expected)
}
func TestGeneratorWithSprig(t *testing.T) {
assert := assert.New(t)
testName := "with_sprig"
setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) {
commit("2018-01-01 00:00:00", "feat(core): version 1.0.0", "")
tag("1.0.0")
commit("2018-02-01 00:00:00", "feat(core): version 2.0.0", "")
tag("2.0.0")
commit("2018-03-01 00:00:00", "feat(core): version 3.0.0", "")
})
gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true),
&Config{
Bin: "git",
WorkingDir: filepath.Join(testRepoRoot, testName),
Template: filepath.Join(cwd, "testdata", testName+".md"),
Info: &Info{
Title: "CHANGELOG Example",
RepositoryURL: "https://github.com/git-chglog/git-chglog",
},
Options: &Options{
Sort: "date",
NextTag: "3.0.0",
CommitFilters: map[string][]string{
"Type": {
"feat",
},
},
CommitSortBy: "Scope",
CommitGroupBy: "Type",
CommitGroupSortBy: "Title",
CommitGroupTitleMaps: map[string]string{
"feat": "Features",
},
HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$",
HeaderPatternMaps: []string{
"Type",
"Scope",
"Subject",
},
},
})
buf := &bytes.Buffer{}
err := gen.Generate(buf, "")
expected := strings.TrimSpace(buf.String())
assert.Nil(err)
assert.Equal(`My Changelog
<a name="unreleased"></a>
## [Unreleased]
<a name="3.0.0"></a>
## [3.0.0] - 2018-03-01
### Features
- **CORE:** version 3.0.0
<a name="2.0.0"></a>
## [2.0.0] - 2018-02-01
### Features
- **CORE:** version 2.0.0
<a name="1.0.0"></a>
## 1.0.0 - 2018-01-01
### Features
- **CORE:** version 1.0.0
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/3.0.0...HEAD
[3.0.0]: https://github.com/git-chglog/git-chglog/compare/2.0.0...3.0.0
[2.0.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...2.0.0`, expected)
[Unreleased]: https://github.com/git-chglog/git-chglog/compare/v1.0.0...HEAD`, strings.TrimSpace(buf.String()))
}

View file

@ -7,7 +7,6 @@ import (
"time"
"github.com/fatih/color"
chglog "github.com/git-chglog/git-chglog"
)

View file

@ -8,9 +8,8 @@ import (
"regexp"
"testing"
"github.com/stretchr/testify/assert"
chglog "github.com/git-chglog/git-chglog"
"github.com/stretchr/testify/assert"
)
func TestCLIForStdout(t *testing.T) {
@ -37,7 +36,7 @@ func TestCLIForStdout(t *testing.T) {
if config.Bin != "/custom/bin/git" {
return errors.New("")
}
_, _ = w.Write([]byte("success!!"))
w.Write([]byte("success!!"))
return nil
},
}
@ -105,7 +104,7 @@ func TestCLIForFile(t *testing.T) {
if filepath.ToSlash(config.Bin) != "/custom/bin/git" {
return errors.New("")
}
_, _ = w.Write([]byte("success!!"))
w.Write([]byte("success!!"))
return nil
},
}

View file

@ -4,9 +4,8 @@ import (
"path/filepath"
"strings"
"github.com/imdario/mergo"
chglog "github.com/git-chglog/git-chglog"
"github.com/imdario/mergo"
)
// Info ...
@ -50,7 +49,6 @@ type NoteOptions struct {
Keywords []string `yaml:"keywords"`
}
// JiraClientInfoOptions ...
type JiraClientInfoOptions struct {
Username string `yaml:"username"`
Token string `yaml:"token"`
@ -72,7 +70,6 @@ type JiraOptions struct {
// Options ...
type Options struct {
TagFilterPattern string `yaml:"tag_filter_pattern"`
Sort string `yaml:"sort"`
Commits CommitOptions `yaml:"commits"`
CommitGroups CommitGroupOptions `yaml:"commit_groups"`
Header PatternOptions `yaml:"header"`
@ -123,7 +120,6 @@ func (config *Config) Normalize(ctx *CLIContext) error {
}
config.normalizeStyle()
config.normalizeTagSortBy()
return nil
}
@ -140,19 +136,6 @@ func (config *Config) normalizeStyle() {
}
}
func (config *Config) normalizeTagSortBy() {
switch {
case config.Options.Sort == "":
config.Options.Sort = "date"
case strings.EqualFold(config.Options.Sort, "date"):
config.Options.Sort = "date"
case strings.EqualFold(config.Options.Sort, "semver"):
config.Options.Sort = "semver"
default:
config.Options.Sort = "date"
}
}
// For GitHub
func (config *Config) normalizeStyleOfGitHub() {
opts := config.Options
@ -303,12 +286,11 @@ func (config *Config) Convert(ctx *CLIContext) *chglog.Config {
Template: orValue(ctx.Template, config.Template),
Info: &chglog.Info{
Title: info.Title,
RepositoryURL: orValue(ctx.RepositoryURL, info.RepositoryURL),
RepositoryURL: orValue(ctx.RepositoryUrl, info.RepositoryURL),
},
Options: &chglog.Options{
NextTag: ctx.NextTag,
TagFilterPattern: ctx.TagFilterPattern,
Sort: orValue(ctx.Sort, opts.Sort),
NoCaseSensitive: ctx.NoCaseSensitive,
Paths: ctx.Paths,
CommitFilters: opts.Commits.Filters,
@ -316,7 +298,6 @@ func (config *Config) Convert(ctx *CLIContext) *chglog.Config {
CommitGroupBy: opts.CommitGroups.GroupBy,
CommitGroupSortBy: opts.CommitGroups.SortBy,
CommitGroupTitleMaps: opts.CommitGroups.TitleMaps,
CommitGroupTitleOrder: opts.CommitGroups.TitleOrder,
HeaderPattern: opts.Header.Pattern,
HeaderPatternMaps: opts.Header.PatternMaps,
IssuePrefix: opts.Issues.Prefix,
@ -328,7 +309,7 @@ func (config *Config) Convert(ctx *CLIContext) *chglog.Config {
NoteKeywords: opts.Notes.Keywords,
JiraUsername: orValue(ctx.JiraUsername, opts.Jira.ClintInfo.Username),
JiraToken: orValue(ctx.JiraToken, opts.Jira.ClintInfo.Token),
JiraURL: orValue(ctx.JiraURL, opts.Jira.ClintInfo.URL),
JiraUrl: orValue(ctx.JiraUrl, opts.Jira.ClintInfo.URL),
JiraTypeMaps: opts.Jira.Issue.TypeMaps,
JiraIssueDescriptionPattern: opts.Jira.Issue.DescriptionPattern,
},

View file

@ -1,10 +1,9 @@
package main
import (
"os"
"path/filepath"
"io/ioutil"
"gopkg.in/yaml.v2"
yaml "gopkg.in/yaml.v2"
)
// ConfigLoader ...
@ -21,8 +20,7 @@ func NewConfigLoader() ConfigLoader {
}
func (loader *configLoaderImpl) Load(path string) (*Config, error) {
fp := filepath.Clean(path)
bytes, err := os.ReadFile(fp)
bytes, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}

View file

@ -11,7 +11,7 @@ type CLIContext struct {
Stderr io.Writer
ConfigPath string
Template string
RepositoryURL string
RepositoryUrl string
OutputPath string
Silent bool
NoColor bool
@ -22,9 +22,8 @@ type CLIContext struct {
TagFilterPattern string
JiraUsername string
JiraToken string
JiraURL string
JiraUrl string
Paths []string
Sort string
}
// InitContext ...

View file

@ -18,7 +18,7 @@ func (t *customTemplateBuilderImpl) Build(ans *Answer) (string, error) {
tpl += t.versionHeader(ans.Style, ans.Template)
// commits
tpl += t.commits(ans.CommitMessageFormat)
tpl += t.commits(ans.Template, ans.CommitMessageFormat)
// revert
if ans.IncludeReverts {
@ -75,7 +75,7 @@ func (*customTemplateBuilderImpl) versionHeader(style, template string) string {
return tpl
}
func (*customTemplateBuilderImpl) commits(format string) string {
func (*customTemplateBuilderImpl) commits(template, format string) string {
var (
header string
body string

View file

@ -2,6 +2,7 @@ package main
import (
"io"
"io/ioutil"
"os"
)
@ -34,18 +35,15 @@ func (*osFileSystem) Exists(path string) bool {
func (*osFileSystem) MkdirP(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
//nolint:gosec
return os.MkdirAll(path, os.ModePerm)
}
return nil
}
func (*osFileSystem) Create(name string) (File, error) {
//nolint: gosec
return os.Create(name)
}
func (*osFileSystem) WriteFile(path string, content []byte) error {
//nolint:gosec
return os.WriteFile(path, content, os.ModePerm)
return ioutil.WriteFile(path, content, os.ModePerm)
}

View file

@ -2,16 +2,17 @@ package main
import (
"fmt"
"github.com/git-chglog/git-chglog"
"path/filepath"
"github.com/fatih/color"
chglog "github.com/git-chglog/git-chglog"
gitcmd "github.com/tsuyoshiwada/go-gitcmd"
)
// Initializer ...
type Initializer struct {
ctx *InitContext
client gitcmd.Client
fs FileSystem
logger *chglog.Logger
questioner Questioner

View file

@ -3,20 +3,14 @@ package main
import (
"fmt"
"io"
"log"
"os"
"github.com/fatih/color"
"github.com/mattn/go-colorable"
"github.com/tsuyoshiwada/go-gitcmd"
gitcmd "github.com/tsuyoshiwada/go-gitcmd"
"github.com/urfave/cli/v2"
)
// version is passed in via LDFLAGS main.version
var version string
// CreateApp creates and initializes CLI application
// with description, flags, version, etc.
func CreateApp(actionFunc cli.ActionFunc) *cli.App {
ttl := color.New(color.FgYellow).SprintFunc()
@ -77,7 +71,7 @@ func CreateApp(actionFunc cli.ActionFunc) *cli.App {
app := cli.NewApp()
app.Name = "git-chglog"
app.Usage = "todo usage for git-chglog"
app.Version = version
app.Version = Version
app.Flags = []cli.Flag{
// init
@ -178,13 +172,6 @@ func CreateApp(actionFunc cli.ActionFunc) *cli.App {
EnvVars: []string{"JIRA_TOKEN"},
},
// sort
&cli.StringFlag{
Name: "sort",
Usage: "Specify how to sort tags; currently supports \"date\" or by \"semver\"",
DefaultText: "date",
},
// help & version
cli.HelpFlag,
cli.VersionFlag,
@ -195,8 +182,6 @@ func CreateApp(actionFunc cli.ActionFunc) *cli.App {
return app
}
// AppAction is a callback function to create initializer
// and CLIContext and ultimately run the application.
func AppAction(c *cli.Context) error {
wd, err := os.Getwd()
if err != nil {
@ -234,7 +219,7 @@ func AppAction(c *cli.Context) error {
Stderr: colorable.NewColorableStderr(),
ConfigPath: c.String("config"),
Template: c.String("template"),
RepositoryURL: c.String("repository-url"),
RepositoryUrl: c.String("repository-url"),
OutputPath: c.String("output"),
Silent: c.Bool("silent"),
NoColor: c.Bool("no-color"),
@ -245,9 +230,8 @@ func AppAction(c *cli.Context) error {
TagFilterPattern: c.String("tag-filter-pattern"),
JiraUsername: c.String("jira-username"),
JiraToken: c.String("jira-token"),
JiraURL: c.String("jira-url"),
JiraUrl: c.String("jira-url"),
Paths: c.StringSlice("path"),
Sort: c.String("sort"),
},
fs,
NewConfigLoader(),
@ -261,8 +245,5 @@ func AppAction(c *cli.Context) error {
func main() {
app := CreateApp(AppAction)
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
app.Run(os.Args)
}

View file

@ -1,16 +1,14 @@
package main
import (
"log"
"testing"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v2"
"testing"
)
var gAssert *assert.Assertions
func mockAppAction(c *cli.Context) error {
func mock_app_action(c *cli.Context) error {
assert := gAssert
assert.Equal("c.yml", c.String("config"))
assert.Equal("^v", c.String("tag-filter-pattern"))
@ -27,7 +25,7 @@ func TestCreateApp(t *testing.T) {
assert.True(true)
gAssert = assert
app := CreateApp(mockAppAction)
app := CreateApp(mock_app_action)
args := []string{
"git-chglog",
"--silent",
@ -38,8 +36,5 @@ func TestCreateApp(t *testing.T) {
"--next-tag", "v5",
"--tag-filter-pattern", "^v",
}
err := app.Run(args)
if err != nil {
log.Fatal(err)
}
app.Run(args)
}

View file

@ -3,9 +3,8 @@ package main
import (
"testing"
"github.com/stretchr/testify/assert"
chglog "github.com/git-chglog/git-chglog"
"github.com/stretchr/testify/assert"
)
func TestProcessorFactory(t *testing.T) {

View file

@ -6,8 +6,8 @@ import (
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/tsuyoshiwada/go-gitcmd"
gitcmd "github.com/tsuyoshiwada/go-gitcmd"
survey "github.com/AlecAivazis/survey/v2"
)
// Answer ...
@ -52,12 +52,11 @@ func (q *questionerImpl) Ask() (*Answer, error) {
t := q.fs.Exists(tpl)
msg := ""
switch {
case c && t:
if c && t {
msg = fmt.Sprintf("\"%s\" and \"%s\" already exists. Do you want to overwrite?", config, tpl)
case c:
} else if c {
msg = fmt.Sprintf("\"%s\" already exists. Do you want to overwrite?", config)
case t:
} else if t {
msg = fmt.Sprintf("\"%s\" already exists. Do you want to overwrite?", tpl)
}

View file

@ -7,7 +7,7 @@ import (
"strings"
)
var reSSH = regexp.MustCompile(`^\w+@([\w\.\-]+):([\w\.\-]+)\/([\w\.\-]+)$`)
var reSSH = regexp.MustCompile("^\\w+@([\\w\\.\\-]+):([\\w\\.\\-]+)\\/([\\w\\.\\-]+)$")
func remoteOriginURLToHTTP(rawurl string) string {
if rawurl == "" {

View file

@ -74,7 +74,7 @@ func (f *CommitMessageFormat) PatternMapString() string {
return fmt.Sprintf("\n%s", strings.Join(arr, "\n"))
}
// FilterTypesString ...
// FilterTypeString ...
func (f *CommitMessageFormat) FilterTypesString() string {
if len(f.typeSamples) == 0 {
return " []"

View file

@ -0,0 +1,4 @@
package main
// Version of git-chglog cli client
const Version = "v0.11.2"

View file

@ -119,7 +119,6 @@ func (e *commitExtractor) commitGroupTitle(commit *Commit) (string, string) {
if t, ok := e.opts.CommitGroupTitleMaps[v]; ok {
ttl = t
} else {
//nolint:staticcheck
ttl = strings.Title(raw)
}
}
@ -128,11 +127,7 @@ func (e *commitExtractor) commitGroupTitle(commit *Commit) (string, string) {
return raw, ttl
}
func (e *commitExtractor) sortCommitGroups(groups []*CommitGroup) { //nolint:gocyclo
// NOTE(khos2ow): this function is over our cyclomatic complexity goal.
// Be wary when adding branches, and look for functionality that could
// be reasonably moved into an injected dependency.
func (e *commitExtractor) sortCommitGroups(groups []*CommitGroup) {
order := make(map[string]int)
if e.opts.CommitGroupSortBy == "Custom" {
for i, t := range e.opts.CommitGroupTitleOrder {
@ -141,9 +136,6 @@ func (e *commitExtractor) sortCommitGroups(groups []*CommitGroup) { //nolint:goc
}
// groups
// TODO(khos2ow): move the inline sort function to
// conceret implementation of sort.Interface in order
// to reduce cyclomatic complaxity.
sort.Slice(groups, func(i, j int) bool {
if e.opts.CommitGroupSortBy == "Custom" {
return order[groups[i].RawTitle] < order[groups[j].RawTitle]
@ -173,11 +165,6 @@ func (e *commitExtractor) sortCommitGroups(groups []*CommitGroup) { //nolint:goc
// commits
for _, group := range groups {
group := group // pin group to avoid potential bugs with passing group to lower functions
// TODO(khos2ow): move the inline sort function to
// conceret implementation of sort.Interface in order
// to reduce cyclomatic complaxity.
sort.Slice(group.Commits, func(i, j int) bool {
var (
a, b interface{}
@ -211,7 +198,6 @@ func (e *commitExtractor) sortNoteGroups(groups []*NoteGroup) {
// notes
for _, group := range groups {
group := group // pin group to avoid potential bugs with passing group to lower functions
sort.Slice(group.Notes, func(i, j int) bool {
return strings.ToLower(group.Notes[i].Title) < strings.ToLower(group.Notes[j].Title)
})

View file

@ -20,14 +20,14 @@ func TestCommitExtractor(t *testing.T) {
fixtures := []*Commit{
// [0]
{
&Commit{
Type: "foo",
Scope: "c",
Header: "1",
Notes: []*Note{},
},
// [1]
{
&Commit{
Type: "foo",
Scope: "b",
Header: "2",
@ -37,7 +37,7 @@ func TestCommitExtractor(t *testing.T) {
},
},
// [2]
{
&Commit{
Type: "bar",
Scope: "d",
Header: "3",
@ -47,7 +47,7 @@ func TestCommitExtractor(t *testing.T) {
},
},
// [3]
{
&Commit{
Type: "foo",
Scope: "a",
Header: "4",
@ -56,7 +56,7 @@ func TestCommitExtractor(t *testing.T) {
},
},
// [4]
{
&Commit{
Type: "",
Scope: "",
Header: "Merge1",
@ -67,7 +67,7 @@ func TestCommitExtractor(t *testing.T) {
},
},
// [5]
{
&Commit{
Type: "",
Scope: "",
Header: "Revert1",
@ -81,14 +81,14 @@ func TestCommitExtractor(t *testing.T) {
commitGroups, mergeCommits, revertCommits, noteGroups := extractor.Extract(fixtures)
assert.Equal([]*CommitGroup{
{
&CommitGroup{
RawTitle: "bar",
Title: "BAR",
Commits: []*Commit{
fixtures[2],
},
},
{
&CommitGroup{
RawTitle: "foo",
Title: "Foo",
Commits: []*Commit{
@ -108,26 +108,26 @@ func TestCommitExtractor(t *testing.T) {
}, revertCommits)
assert.Equal([]*NoteGroup{
{
&NoteGroup{
Title: "note1-title",
Notes: []*Note{
fixtures[1].Notes[0],
fixtures[2].Notes[0],
},
},
{
&NoteGroup{
Title: "note2-title",
Notes: []*Note{
fixtures[1].Notes[1],
},
},
{
&NoteGroup{
Title: "note3-title",
Notes: []*Note{
fixtures[2].Notes[1],
},
},
{
&NoteGroup{
Title: "note4-title",
Notes: []*Note{
fixtures[3].Notes[0],

View file

@ -4,11 +4,7 @@ import (
"strings"
)
func commitFilter(commits []*Commit, filters map[string][]string, noCaseSensitive bool) []*Commit { //nolint:gocyclo
// NOTE(khos2ow): this function is over our cyclomatic complexity goal.
// Be wary when adding branches, and look for functionality that could
// be reasonably moved into an injected dependency.
func commitFilter(commits []*Commit, filters map[string][]string, noCaseSensitive bool) []*Commit {
res := []*Commit{}
for _, commit := range commits {

View file

@ -18,27 +18,27 @@ func TestCommitFilter(t *testing.T) {
}
fixtures := []*Commit{
{
&Commit{
Type: "foo",
Scope: "hoge",
Subject: "1",
},
{
&Commit{
Type: "foo",
Scope: "fuga",
Subject: "2",
},
{
&Commit{
Type: "bar",
Scope: "hoge",
Subject: "3",
},
{
&Commit{
Type: "bar",
Scope: "fuga",
Subject: "4",
},
{
&Commit{
Type: "Bar",
Scope: "hogera",
Subject: "5",

View file

@ -59,8 +59,6 @@ type commitParser struct {
reIssue *regexp.Regexp
reNotes *regexp.Regexp
reMention *regexp.Regexp
reSignOff *regexp.Regexp
reCoAuthor *regexp.Regexp
reJiraIssueDescription *regexp.Regexp
}
@ -82,9 +80,7 @@ func newCommitParser(logger *Logger, client gitcmd.Client, jiraClient JiraClient
reRef: regexp.MustCompile("(?i)(" + joinedRefActions + ")\\s?([\\w/\\.\\-]+)?(?:" + joinedIssuePrefix + ")(\\d+)"),
reIssue: regexp.MustCompile("(?:" + joinedIssuePrefix + ")(\\d+)"),
reNotes: regexp.MustCompile("^(?i)\\s*(" + joinedNoteKeywords + ")[:\\s]+(.*)"),
reMention: regexp.MustCompile(`@([\w-]+)`),
reSignOff: regexp.MustCompile(`Signed-off-by:\s+([\p{L}\s\-\[\]]+)\s+<([\w+\-\[\].@]+)>`),
reCoAuthor: regexp.MustCompile(`Co-authored-by:\s+([\p{L}\s\-\[\]]+)\s+<([\w+\-\[\].@]+)>`),
reMention: regexp.MustCompile("@([\\w-]+)"),
reJiraIssueDescription: regexp.MustCompile(opts.JiraIssueDescriptionPattern),
}
}
@ -227,41 +223,11 @@ func (p *commitParser) processHeader(commit *Commit, input string) {
commit.Mentions = p.parseMentions(input)
// Jira
if commit.JiraIssueID != "" {
p.processJiraIssue(commit, commit.JiraIssueID)
if commit.JiraIssueId != "" {
p.processJiraIssue(commit, commit.JiraIssueId)
}
}
func (p *commitParser) extractLineMetadata(commit *Commit, line string) bool {
meta := false
refs := p.parseRefs(line)
if len(refs) > 0 {
meta = true
commit.Refs = append(commit.Refs, refs...)
}
mentions := p.parseMentions(line)
if len(mentions) > 0 {
meta = true
commit.Mentions = append(commit.Mentions, mentions...)
}
coAuthors := p.parseCoAuthors(line)
if len(coAuthors) > 0 {
meta = true
commit.CoAuthors = append(commit.CoAuthors, coAuthors...)
}
signers := p.parseSigners(line)
if len(signers) > 0 {
meta = true
commit.Signers = append(commit.Signers, signers...)
}
return meta
}
func (p *commitParser) processBody(commit *Commit, input string) {
input = convNewline(input, "\n")
@ -271,29 +237,30 @@ func (p *commitParser) processBody(commit *Commit, input string) {
// notes & refs & mentions
commit.Notes = []*Note{}
inNote := false
trim := false
fenceDetector := newMdFenceDetector()
lines := strings.Split(input, "\n")
// body without notes & refs & mentions
trimmedBody := make([]string, 0, len(lines))
for _, line := range lines {
if !inNote {
trim = false
}
fenceDetector.Update(line)
if !fenceDetector.InCodeblock() && p.extractLineMetadata(commit, line) {
trim = true
inNote = false
if !fenceDetector.InCodeblock() {
refs := p.parseRefs(line)
if len(refs) > 0 {
inNote = false
commit.Refs = append(commit.Refs, refs...)
}
mentions := p.parseMentions(line)
if len(mentions) > 0 {
inNote = false
commit.Mentions = append(commit.Mentions, mentions...)
}
}
// Q: should this check also only be outside of code blocks?
res := p.reNotes.FindAllStringSubmatch(line, -1)
if len(res) > 0 {
inNote = true
trim = true
for _, r := range res {
commit.Notes = append(commit.Notes, &Note{
Title: r[1],
@ -304,13 +271,8 @@ func (p *commitParser) processBody(commit *Commit, input string) {
last := commit.Notes[len(commit.Notes)-1]
last.Body = last.Body + "\n" + line
}
if !trim {
trimmedBody = append(trimmedBody, line)
}
}
commit.TrimmedBody = strings.TrimSpace(strings.Join(trimmedBody, "\n"))
p.trimSpaceInNotes(commit)
}
@ -355,30 +317,6 @@ func (p *commitParser) parseRefs(input string) []*Ref {
return refs
}
func (p *commitParser) parseSigners(input string) []Contact {
res := p.reSignOff.FindAllStringSubmatch(input, -1)
contacts := make([]Contact, len(res))
for i, r := range res {
contacts[i].Name = r[1]
contacts[i].Email = r[2]
}
return contacts
}
func (p *commitParser) parseCoAuthors(input string) []Contact {
res := p.reCoAuthor.FindAllStringSubmatch(input, -1)
contacts := make([]Contact, len(res))
for i, r := range res {
contacts[i].Name = r[1]
contacts[i].Email = r[2]
}
return contacts
}
func (p *commitParser) parseMentions(input string) []string {
res := p.reMention.FindAllStringSubmatch(input, -1)
mentions := make([]string, len(res))
@ -426,10 +364,10 @@ func (p *commitParser) uniqMentions(mentions []string) []string {
return arr
}
func (p *commitParser) processJiraIssue(commit *Commit, issueID string) {
issue, err := p.jiraClient.GetJiraIssue(commit.JiraIssueID)
func (p *commitParser) processJiraIssue(commit *Commit, issueId string) {
issue, err := p.jiraClient.GetJiraIssue(commit.JiraIssueId)
if err != nil {
p.logger.Error(fmt.Sprintf("Failed to parse Jira story %s: %s\n", issueID, err))
p.logger.Error(fmt.Sprintf("Failed to parse Jira story %s: %s\n", issueId, err))
return
}
commit.Type = p.config.Options.JiraTypeMaps[issue.Fields.Type.Name]

View file

@ -3,6 +3,7 @@ package chglog
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
@ -22,7 +23,7 @@ func TestCommitParserParse(t *testing.T) {
return "", errors.New("")
}
bytes, _ := os.ReadFile(filepath.Join("testdata", "gitlog.txt"))
bytes, _ := ioutil.ReadFile(filepath.Join("testdata", "gitlog.txt"))
return string(bytes), nil
},
@ -32,7 +33,7 @@ func TestCommitParserParse(t *testing.T) {
mock, nil, &Config{
Options: &Options{
CommitFilters: map[string][]string{
"Type": {
"Type": []string{
"feat",
"fix",
"perf",
@ -78,7 +79,7 @@ func TestCommitParserParse(t *testing.T) {
commits, err := parser.Parse("HEAD")
assert.Nil(err)
assert.Equal([]*Commit{
{
&Commit{
Hash: &Hash{
Long: "65cf1add9735dcc4810dda3312b0792236c97c4e",
Short: "65cf1add",
@ -96,22 +97,21 @@ func TestCommitParserParse(t *testing.T) {
Merge: nil,
Revert: nil,
Refs: []*Ref{
{
&Ref{
Action: "",
Ref: "123",
Source: "",
},
},
Notes: []*Note{},
Mentions: []string{},
Header: "feat(*): Add new feature #123",
Type: "feat",
Scope: "*",
Subject: "Add new feature #123",
Body: "",
TrimmedBody: "",
Notes: []*Note{},
Mentions: []string{},
Header: "feat(*): Add new feature #123",
Type: "feat",
Scope: "*",
Subject: "Add new feature #123",
Body: "",
},
{
&Commit{
Hash: &Hash{
Long: "14ef0b6d386c5432af9292eab3c8314fa3001bc7",
Short: "14ef0b6d",
@ -132,24 +132,24 @@ func TestCommitParserParse(t *testing.T) {
},
Revert: nil,
Refs: []*Ref{
{
&Ref{
Action: "",
Ref: "3",
Source: "",
},
{
&Ref{
Action: "Fixes",
Ref: "3",
Source: "",
},
{
&Ref{
Action: "Closes",
Ref: "1",
Source: "",
},
},
Notes: []*Note{
{
&Note{
Title: "BREAKING CHANGE",
Body: "This is breaking point message.",
},
@ -166,9 +166,8 @@ Fixes #3
Closes #1
BREAKING CHANGE: This is breaking point message.`,
TrimmedBody: `This is body message.`,
},
{
&Commit{
Hash: &Hash{
Long: "809a8280ffd0dadb0f4e7ba9fc835e63c37d6af6",
Short: "809a8280",
@ -201,9 +200,8 @@ BREAKING CHANGE: This is breaking point message.`,
@tsuyoshiwada
@hogefuga
@FooBarBaz`,
TrimmedBody: `Has mention body`,
},
{
&Commit{
Hash: &Hash{
Long: "74824d6bd1470b901ec7123d13a76a1b8938d8d0",
Short: "74824d6b",
@ -221,19 +219,19 @@ BREAKING CHANGE: This is breaking point message.`,
Merge: nil,
Revert: nil,
Refs: []*Ref{
{
&Ref{
Action: "Fixes",
Ref: "123",
Source: "",
},
{
&Ref{
Action: "Closes",
Ref: "456",
Source: "username/repository",
},
},
Notes: []*Note{
{
&Note{
Title: "BREAKING CHANGE",
Body: fmt.Sprintf(`This is multiline breaking change note.
It is treated as the body of the Note until a mention or reference appears.
@ -282,9 +280,8 @@ class MyController extends Controller {
Fixes #123
Closes username/repository#456`, "```", "```"),
TrimmedBody: `This mixed body message.`,
},
{
&Commit{
Hash: &Hash{
Long: "123456789735dcc4810dda3312b0792236c97c4e",
Short: "12345678",
@ -303,15 +300,14 @@ Closes username/repository#456`, "```", "```"),
Revert: &Revert{
Header: "fix(core): commit message",
},
Refs: []*Ref{},
Notes: []*Note{},
Mentions: []string{},
Header: "Revert \"fix(core): commit message\"",
Type: "",
Scope: "",
Subject: "",
Body: "This reverts commit f755db78dcdf461dc42e709b3ab728ceba353d1d.",
TrimmedBody: "This reverts commit f755db78dcdf461dc42e709b3ab728ceba353d1d.",
Refs: []*Ref{},
Notes: []*Note{},
Mentions: []string{},
Header: "Revert \"fix(core): commit message\"",
Type: "",
Scope: "",
Subject: "",
Body: "This reverts commit f755db78dcdf461dc42e709b3ab728ceba353d1d.",
},
}, commits)
}
@ -375,7 +371,7 @@ func TestCommitParserParseWithJira(t *testing.T) {
return "", errors.New("")
}
bytes, _ := os.ReadFile(filepath.Join("testdata", "gitlog_jira.txt"))
bytes, _ := ioutil.ReadFile(filepath.Join("testdata", "gitlog_jira.txt"))
return string(bytes), nil
},
@ -385,7 +381,7 @@ func TestCommitParserParseWithJira(t *testing.T) {
mock, mockJiraClient{}, &Config{
Options: &Options{
CommitFilters: map[string][]string{
"Type": {
"Type": []string{
"feat",
"fix",
"perf",
@ -395,7 +391,7 @@ func TestCommitParserParseWithJira(t *testing.T) {
HeaderPattern: "^(?:(\\w*)|(?:\\[(.*)\\])?)\\:\\s(.*)$",
HeaderPatternMaps: []string{
"Type",
"JiraIssueID",
"JiraIssueId",
"Subject",
},
JiraTypeMaps: map[string]string{
@ -407,7 +403,7 @@ func TestCommitParserParseWithJira(t *testing.T) {
commits, err := parser.Parse("HEAD")
assert.Nil(err)
commit := commits[0]
assert.Equal(commit.JiraIssueID, "JIRA-1111")
assert.Equal(commit.JiraIssueId, "JIRA-1111")
assert.Equal(commit.JiraIssue.Type, "Story")
assert.Equal(commit.JiraIssue.Summary, "summary of JIRA-1111")
assert.Equal(commit.JiraIssue.Description, "description of JIRA-1111")

View file

@ -19,7 +19,7 @@ func Example() {
},
Options: &Options{
CommitFilters: map[string][]string{
"Type": {
"Type": []string{
"feat",
"fix",
},

View file

@ -8,12 +8,6 @@ type Hash struct {
Short string
}
// Contact of co-authors and signers
type Contact struct {
Name string
Email string
}
// Author of commit
type Author struct {
Name string
@ -58,7 +52,7 @@ type NoteGroup struct {
Notes []*Note
}
// JiraIssue is information about a jira ticket (type, summary, description, and labels)
// JiraIssue
type JiraIssue struct {
Type string
Summary string
@ -75,17 +69,14 @@ type Commit struct {
Revert *Revert // If it is not a revert commit, `nil` is assigned
Refs []*Ref
Notes []*Note
Mentions []string // Name of the user included in the commit header or body
CoAuthors []Contact // (e.g. `Co-authored-by: user <user@email>`)
Signers []Contact // (e.g. `Signed-off-by: user <user@email>`)
Mentions []string // Name of the user included in the commit header or body
JiraIssue *JiraIssue // If no issue id found in header, `nil` is assigned
Header string // (e.g. `feat(core)[RNWY-310]: Add new feature`)
Type string // (e.g. `feat`)
Scope string // (e.g. `core`)
Subject string // (e.g. `Add new feature`)
JiraIssueID string // (e.g. `RNWY-310`)
Header string // (e.g. `feat(core)[RNWY-310]: Add new feature`)
Type string // (e.g. `feat`)
Scope string // (e.g. `core`)
Subject string // (e.g. `Add new feature`)
JiraIssueId string // (e.g. `RNWY-310`)
Body string
TrimmedBody string // Body without any Notes/Refs/Mentions/CoAuthors/Signers
}
// CommitGroup is a collection of commits grouped according to the `CommitGroupBy` option

52
go.mod
View file

@ -1,48 +1,16 @@
module github.com/git-chglog/git-chglog
go 1.24.1
go 1.15
require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/Masterminds/sprig/v3 v3.3.0
github.com/andygrunwald/go-jira v1.16.0
github.com/coreos/go-semver v0.3.1
github.com/fatih/color v1.18.0
github.com/imdario/mergo v0.3.16
github.com/kyokomi/emoji/v2 v2.2.13
github.com/mattn/go-colorable v0.1.14
github.com/stretchr/testify v1.10.0
github.com/AlecAivazis/survey/v2 v2.2.9
github.com/andygrunwald/go-jira v1.13.0
github.com/fatih/color v1.10.0
github.com/imdario/mergo v0.3.12
github.com/kyokomi/emoji/v2 v2.2.8
github.com/mattn/go-colorable v0.1.8
github.com/stretchr/testify v1.7.0
github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df
github.com/urfave/cli/v2 v2.27.6
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v3 v3.0.1
)
require (
dario.cat/mergo v1.0.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/trivago/tgo v1.0.7 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.23.0 // indirect
golang.org/x/text v0.17.0 // indirect
github.com/urfave/cli/v2 v2.3.0
gopkg.in/yaml.v2 v2.4.0
)

167
go.sum
View file

@ -1,135 +1,80 @@
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ=
github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/AlecAivazis/survey/v2 v2.2.9 h1:LWvJtUswz/W9/zVVXELrmlvdwWcKE60ZAw0FWV9vssk=
github.com/AlecAivazis/survey/v2 v2.2.9/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/andygrunwald/go-jira v1.13.0 h1:vvIImGgX32bHfoiyUwkNo+/YrPnRczNarvhLOncP6dE=
github.com/andygrunwald/go-jira v1.13.0/go.mod h1:jYi4kFDbRPZTJdJOVJO4mpMMIwdB+rcZwSO58DzPd2I=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU=
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0=
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kyokomi/emoji/v2 v2.2.13 h1:GhTfQa67venUUvmleTNFnb+bi7S3aocF7ZCXU9fSO7U=
github.com/kyokomi/emoji/v2 v2.2.13/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ=
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM=
github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/trivago/tgo v1.0.1 h1:bxatjJIXNIpV18bucU4Uk/LaoxvxuOlp/oowRHyncLQ=
github.com/trivago/tgo v1.0.1/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc=
github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df h1:Y2l28Jr3vOEeYtxfVbMtVfOdAwuUqWaP9fvNKiBVeXY=
github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df/go.mod h1:pnyouUty/nBr/zm3GYwTIt+qFTLWbdjeLjZmJdzJOu8=
github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -4,7 +4,6 @@ import (
agjira "github.com/andygrunwald/go-jira"
)
// JiraClient is an HTTP client for Jira
type JiraClient interface {
GetJiraIssue(id string) (*agjira.Issue, error)
}
@ -15,12 +14,11 @@ type jiraClient struct {
url string
}
// NewJiraClient returns an instance of JiraClient
func NewJiraClient(config *Config) JiraClient {
return jiraClient{
username: config.Options.JiraUsername,
token: config.Options.JiraToken,
url: config.Options.JiraURL,
token: config.Options.JiraToken,
url: config.Options.JiraUrl,
}
}

View file

@ -1,15 +1,14 @@
package chglog
import (
"testing"
"github.com/stretchr/testify/assert"
"testing"
)
func TestJira(t *testing.T) {
assert := assert.New(t)
config := &Config{
config := &Config {
Options: &Options{
Processor: nil,
NextTag: "",
@ -30,7 +29,7 @@ func TestJira(t *testing.T) {
NoteKeywords: nil,
JiraUsername: "uuu",
JiraToken: "ppp",
JiraURL: "http://jira.com",
JiraUrl: "http://jira.com",
JiraTypeMaps: nil,
JiraIssueDescriptionPattern: "",
},

View file

@ -7,7 +7,7 @@ import (
"regexp"
"github.com/fatih/color"
"github.com/kyokomi/emoji/v2"
emoji "github.com/kyokomi/emoji/v2"
)
// Logger ...
@ -26,7 +26,7 @@ func NewLogger(stdout, stderr io.Writer, silent, noEmoji bool) *Logger {
stderr: stderr,
silent: silent,
noEmoji: noEmoji,
reEmoji: regexp.MustCompile(`:[\w\+_\-]+:\s?`),
reEmoji: regexp.MustCompile(":[\\w\\+_\\-]+:\\s?"),
}
}

View file

@ -6,8 +6,8 @@ import (
"testing"
"github.com/fatih/color"
emoji "github.com/kyokomi/emoji/v2"
"github.com/stretchr/testify/assert"
emoji "github.com/kyokomi/emoji/v2"
)
func TestLoggerLogSilent(t *testing.T) {
@ -40,7 +40,7 @@ func TestLoggerLogNoEmoji(t *testing.T) {
stderr := &bytes.Buffer{}
logger := NewLogger(stdout, stderr, false, true)
logger.Log(":+1:Hello, World! :)")
assert.Equal(fmt.Sprint("Hello, World! :)\n"), stdout.String()) //nolint:gosimple
assert.Equal(fmt.Sprint("Hello, World! :)\n"), stdout.String())
}
func TestLoggerError(t *testing.T) {

View file

@ -14,8 +14,8 @@ type Processor interface {
// GitHubProcessor is optimized for CHANGELOG used in GitHub
//
// The following processing is performed
// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://github.com/tsuyoshiwada))
// - Automatic link to references (#123 -> [#123](https://github.com/owner/repo/issues/123))
// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://github.com/tsuyoshiwada))
// - Automatic link to references (#123 -> [#123](https://github.com/owner/repo/issues/123))
type GitHubProcessor struct {
Host string // Host name used for link destination. Note: You must include the protocol (e.g. "https://github.com")
config *Config
@ -33,8 +33,8 @@ func (p *GitHubProcessor) Bootstrap(config *Config) {
p.Host = strings.TrimRight(p.Host, "/")
}
p.reMention = regexp.MustCompile(`@(\w+)`)
p.reIssue = regexp.MustCompile(`(?i)(#|gh-)(\d+)`)
p.reMention = regexp.MustCompile("@(\\w+)")
p.reIssue = regexp.MustCompile("(?i)(#|gh-)(\\d+)")
}
// ProcessCommit ...
@ -69,15 +69,13 @@ func (p *GitHubProcessor) addLinks(input string) string {
// GitLabProcessor is optimized for CHANGELOG used in GitLab
//
// The following processing is performed
// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://gitlab.com/tsuyoshiwada))
// - Automatic link to references issues (#123 -> [#123](https://gitlab.com/owner/repo/issues/123))
// - Automatic link to references merge request (!123 -> [#123](https://gitlab.com/owner/repo/merge_requests/123))
// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://gitlab.com/tsuyoshiwada))
// - Automatic link to references (#123 -> [#123](https://gitlab.com/owner/repo/issues/123))
type GitLabProcessor struct {
Host string // Host name used for link destination. Note: You must include the protocol (e.g. "https://gitlab.com")
config *Config
reMention *regexp.Regexp
reIssue *regexp.Regexp
reMergeRequest *regexp.Regexp
Host string // Host name used for link destination. Note: You must include the protocol (e.g. "https://gitlab.com")
config *Config
reMention *regexp.Regexp
reIssue *regexp.Regexp
}
// Bootstrap ...
@ -90,9 +88,8 @@ func (p *GitLabProcessor) Bootstrap(config *Config) {
p.Host = strings.TrimRight(p.Host, "/")
}
p.reMention = regexp.MustCompile(`@(\w+)`)
p.reIssue = regexp.MustCompile(`(?i)#(\d+)`)
p.reMergeRequest = regexp.MustCompile(`(?i)!(\d+)`)
p.reMention = regexp.MustCompile("@(\\w+)")
p.reIssue = regexp.MustCompile("(?i)#(\\d+)")
}
// ProcessCommit ...
@ -121,17 +118,14 @@ func (p *GitLabProcessor) addLinks(input string) string {
// issues
input = p.reIssue.ReplaceAllString(input, "[#$1]("+repoURL+"/issues/$1)")
// merge requests
input = p.reMergeRequest.ReplaceAllString(input, "[!$1]("+repoURL+"/merge_requests/$1)")
return input
}
// BitbucketProcessor is optimized for CHANGELOG used in Bitbucket
//
// The following processing is performed
// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://bitbucket.org/tsuyoshiwada/))
// - Automatic link to references (#123 -> [#123](https://bitbucket.org/owner/repo/issues/123/))
// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://bitbucket.org/tsuyoshiwada/))
// - Automatic link to references (#123 -> [#123](https://bitbucket.org/owner/repo/issues/123/))
type BitbucketProcessor struct {
Host string // Host name used for link destination. Note: You must include the protocol (e.g. "https://bitbucket.org")
config *Config
@ -149,8 +143,8 @@ func (p *BitbucketProcessor) Bootstrap(config *Config) {
p.Host = strings.TrimRight(p.Host, "/")
}
p.reMention = regexp.MustCompile(`@(\w+)`)
p.reIssue = regexp.MustCompile(`(?i)#(\d+)`)
p.reMention = regexp.MustCompile("@(\\w+)")
p.reIssue = regexp.MustCompile("(?i)#(\\d+)")
}
// ProcessCommit ...

View file

@ -27,7 +27,7 @@ func TestGitHubProcessor(t *testing.T) {
multiline [#789](https://example.com/issues/789)
[@foo](https://github.com/foo), [@bar](https://github.com/bar)`,
Notes: []*Note{
{
&Note{
Body: `issue1 [#11](https://example.com/issues/11)
issue2 [#22](https://example.com/issues/22)
[gh-56](https://example.com/issues/56) hoge fuga`,
@ -42,7 +42,7 @@ issue2 [#22](https://example.com/issues/22)
multiline #789
@foo, @bar`,
Notes: []*Note{
{
&Note{
Body: `issue1 #11
issue2 #22
gh-56 hoge fuga`,
@ -83,34 +83,30 @@ func TestGitLabProcessor(t *testing.T) {
assert.Equal(
&Commit{
Header: "message [@foo](https://gitlab.com/foo) [#123](https://example.com/issues/123) [!345](https://example.com/merge_requests/345)",
Subject: "message [@foo](https://gitlab.com/foo) [#123](https://example.com/issues/123) [!345](https://example.com/merge_requests/345)",
Header: "message [@foo](https://gitlab.com/foo) [#123](https://example.com/issues/123)",
Subject: "message [@foo](https://gitlab.com/foo) [#123](https://example.com/issues/123)",
Body: `issue [#456](https://example.com/issues/456)
multiline [#789](https://example.com/issues/789)
merge request [!345](https://example.com/merge_requests/345)
[@foo](https://gitlab.com/foo), [@bar](https://gitlab.com/bar)`,
Notes: []*Note{
{
Body: `issue1 [#11](https://example.com/issues/11) [!33](https://example.com/merge_requests/33)
&Note{
Body: `issue1 [#11](https://example.com/issues/11)
issue2 [#22](https://example.com/issues/22)
merge request [!33](https://example.com/merge_requests/33)
gh-56 hoge fuga`,
},
},
},
processor.ProcessCommit(
&Commit{
Header: "message @foo #123 !345",
Subject: "message @foo #123 !345",
Header: "message @foo #123",
Subject: "message @foo #123",
Body: `issue #456
multiline #789
merge request !345
@foo, @bar`,
Notes: []*Note{
{
Body: `issue1 #11 !33
&Note{
Body: `issue1 #11
issue2 #22
merge request !33
gh-56 hoge fuga`,
},
},
@ -121,13 +117,13 @@ gh-56 hoge fuga`,
assert.Equal(
&Commit{
Revert: &Revert{
Header: "revert header [@mention](https://gitlab.com/mention) [#123](https://example.com/issues/123) [!345](https://example.com/merge_requests/345)",
Header: "revert header [@mention](https://gitlab.com/mention) [#123](https://example.com/issues/123)",
},
},
processor.ProcessCommit(
&Commit{
Revert: &Revert{
Header: "revert header @mention #123 !345",
Header: "revert header @mention #123",
},
},
),
@ -155,7 +151,7 @@ func TestBitbucketProcessor(t *testing.T) {
multiline [#789](https://example.com/issues/789/)
[@foo](https://bitbucket.org/foo/), [@bar](https://bitbucket.org/bar/)`,
Notes: []*Note{
{
&Note{
Body: `issue1 [#11](https://example.com/issues/11/)
issue2 [#22](https://example.com/issues/22/)
gh-56 hoge fuga`,
@ -170,7 +166,7 @@ gh-56 hoge fuga`,
multiline #789
@foo, @bar`,
Notes: []*Note{
{
&Note{
Body: `issue1 #11
issue2 #22
gh-56 hoge fuga`,

View file

@ -7,23 +7,21 @@ import (
"strings"
"time"
"github.com/coreos/go-semver/semver"
gitcmd "github.com/tsuyoshiwada/go-gitcmd"
)
type tagReader struct {
client gitcmd.Client
format string
separator string
reFilter *regexp.Regexp
sortBy string
}
func newTagReader(client gitcmd.Client, filterPattern string, sort string) *tagReader {
func newTagReader(client gitcmd.Client, filterPattern string) *tagReader {
return &tagReader{
client: client,
separator: "@@__CHGLOG__@@",
reFilter: regexp.MustCompile(filterPattern),
sortBy: sort,
}
}
@ -38,7 +36,7 @@ func (r *tagReader) ReadAll() ([]*Tag, error) {
tags := []*Tag{}
if err != nil {
return tags, fmt.Errorf("failed to get git-tag: %w", err)
return tags, fmt.Errorf("failed to get git-tag: %s", err.Error())
}
lines := strings.Split(out, "\n")
@ -74,33 +72,12 @@ func (r *tagReader) ReadAll() ([]*Tag, error) {
})
}
switch r.sortBy {
case "date":
r.sortTags(tags)
case "semver":
r.filterSemVerTags(&tags)
r.sortTagsBySemver(tags)
}
r.sortTags(tags)
r.assignPreviousAndNextTag(tags)
return tags, nil
}
func (*tagReader) filterSemVerTags(tags *[]*Tag) {
// filter out any non-semver tags
for i, t := range *tags {
// remove leading v, since its so
// common.
name := strings.TrimPrefix(t.Name, "v")
// attempt semver parse, if not successful
// remove it from tags slice.
if _, err := semver.NewVersion(name); err != nil {
*tags = append((*tags)[:i], (*tags)[i+1:]...)
}
}
}
func (*tagReader) parseRefname(input string) string {
return strings.Replace(input, "refs/tags/", "", 1)
}
@ -148,13 +125,3 @@ func (*tagReader) sortTags(tags []*Tag) {
return !tags[i].Date.Before(tags[j].Date)
})
}
func (*tagReader) sortTagsBySemver(tags []*Tag) {
sort.Slice(tags, func(i, j int) bool {
semver1 := strings.TrimPrefix(tags[i].Name, "v")
semver2 := strings.TrimPrefix(tags[j].Name, "v")
v1 := semver.New(semver1)
v2 := semver.New(semver2)
return v2.LessThan(*v1)
})
}

View file

@ -21,7 +21,6 @@ func TestTagReader(t *testing.T) {
"refs/tags/v2.0.4-beta.1@@__CHGLOG__@@Release v2.0.4-beta.1@@__CHGLOG__@@Thu Feb 1 00:00:00 2018 +0000@@__CHGLOG__@@",
"refs/tags/4.4.3@@__CHGLOG__@@This is tag subject@@__CHGLOG__@@@@__CHGLOG__@@Fri Feb 2 00:00:00 2018 +0000",
"refs/tags/4.4.4@@__CHGLOG__@@Release 4.4.4@@__CHGLOG__@@Fri Feb 2 10:00:40 2018 +0000@@__CHGLOG__@@",
"refs/tags/v2.0.4-beta.2@@__CHGLOG__@@Release v2.0.4-beta.2@@__CHGLOG__@@Sat Feb 3 12:15:00 2018 +0000@@__CHGLOG__@@",
"refs/tags/5.0.0-rc.0@@__CHGLOG__@@Release 5.0.0-rc.0@@__CHGLOG__@@Sat Feb 3 12:30:10 2018 +0000@@__CHGLOG__@@",
"refs/tags/hoge_fuga@@__CHGLOG__@@Invalid semver tag name@@__CHGLOG__@@Mon Mar 12 12:30:10 2018 +0000@@__CHGLOG__@@",
"hoge@@__CHGLOG__@@",
@ -29,12 +28,12 @@ func TestTagReader(t *testing.T) {
},
}
actual, err := newTagReader(client, "", "date").ReadAll()
actual, err := newTagReader(client, "").ReadAll()
assert.Nil(err)
assert.Equal(
[]*Tag{
{
&Tag{
Name: "hoge_fuga",
Subject: "Invalid semver tag name",
Date: time.Date(2018, 3, 12, 12, 30, 10, 0, time.UTC),
@ -45,7 +44,7 @@ func TestTagReader(t *testing.T) {
Date: time.Date(2018, 2, 3, 12, 30, 10, 0, time.UTC),
},
},
{
&Tag{
Name: "5.0.0-rc.0",
Subject: "Release 5.0.0-rc.0",
Date: time.Date(2018, 2, 3, 12, 30, 10, 0, time.UTC),
@ -54,89 +53,13 @@ func TestTagReader(t *testing.T) {
Subject: "Invalid semver tag name",
Date: time.Date(2018, 3, 12, 12, 30, 10, 0, time.UTC),
},
Previous: &RelateTag{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
},
},
{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
Next: &RelateTag{
Name: "5.0.0-rc.0",
Subject: "Release 5.0.0-rc.0",
Date: time.Date(2018, 2, 3, 12, 30, 10, 0, time.UTC),
},
Previous: &RelateTag{
Name: "4.4.4",
Subject: "Release 4.4.4",
Date: time.Date(2018, 2, 2, 10, 0, 40, 0, time.UTC),
},
},
{
Name: "4.4.4",
Subject: "Release 4.4.4",
Date: time.Date(2018, 2, 2, 10, 0, 40, 0, time.UTC),
Next: &RelateTag{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
},
Previous: &RelateTag{
Name: "4.4.3",
Subject: "This is tag subject",
Date: time.Date(2018, 2, 2, 0, 0, 0, 0, time.UTC),
},
},
{
Name: "4.4.3",
Subject: "This is tag subject",
Date: time.Date(2018, 2, 2, 0, 0, 0, 0, time.UTC),
Next: &RelateTag{
Name: "4.4.4",
Subject: "Release 4.4.4",
Date: time.Date(2018, 2, 2, 10, 0, 40, 0, time.UTC),
},
Previous: &RelateTag{
Name: "v2.0.4-beta.1",
Subject: "Release v2.0.4-beta.1",
Date: time.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
},
},
{
Name: "v2.0.4-beta.1",
Subject: "Release v2.0.4-beta.1",
Date: time.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
Next: &RelateTag{
Name: "4.4.3",
Subject: "This is tag subject",
Date: time.Date(2018, 2, 2, 0, 0, 0, 0, time.UTC),
},
Previous: nil,
},
},
actual,
)
actual, err = newTagReader(client, "", "semver").ReadAll()
assert.Nil(err)
assert.Equal(
[]*Tag{
{
Name: "5.0.0-rc.0",
Subject: "Release 5.0.0-rc.0",
Date: time.Date(2018, 2, 3, 12, 30, 10, 0, time.UTC),
Next: nil,
Previous: &RelateTag{
Name: "4.4.4",
Subject: "Release 4.4.4",
Date: time.Date(2018, 2, 2, 10, 0, 40, 0, time.UTC),
},
},
{
&Tag{
Name: "4.4.4",
Subject: "Release 4.4.4",
Date: time.Date(2018, 2, 2, 10, 0, 40, 0, time.UTC),
@ -151,7 +74,7 @@ func TestTagReader(t *testing.T) {
Date: time.Date(2018, 2, 2, 0, 0, 0, 0, time.UTC),
},
},
{
&Tag{
Name: "4.4.3",
Subject: "This is tag subject",
Date: time.Date(2018, 2, 2, 0, 0, 0, 0, time.UTC),
@ -160,35 +83,20 @@ func TestTagReader(t *testing.T) {
Subject: "Release 4.4.4",
Date: time.Date(2018, 2, 2, 10, 0, 40, 0, time.UTC),
},
Previous: &RelateTag{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
},
},
{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
Next: &RelateTag{
Name: "4.4.3",
Subject: "This is tag subject",
Date: time.Date(2018, 2, 2, 0, 0, 0, 0, time.UTC),
},
Previous: &RelateTag{
Name: "v2.0.4-beta.1",
Subject: "Release v2.0.4-beta.1",
Date: time.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
},
},
{
&Tag{
Name: "v2.0.4-beta.1",
Subject: "Release v2.0.4-beta.1",
Date: time.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
Next: &RelateTag{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
Name: "4.4.3",
Subject: "This is tag subject",
Date: time.Date(2018, 2, 2, 0, 0, 0, 0, time.UTC),
},
Previous: nil,
},
@ -196,33 +104,18 @@ func TestTagReader(t *testing.T) {
actual,
)
actualFiltered, errFiltered := newTagReader(client, "^v", "date").ReadAll()
assert.Nil(errFiltered)
actual_filtered, err_filtered := newTagReader(client, "^v").ReadAll()
assert.Nil(err_filtered)
assert.Equal(
[]*Tag{
{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
Next: nil,
Previous: &RelateTag{
Name: "v2.0.4-beta.1",
Subject: "Release v2.0.4-beta.1",
Date: time.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
},
},
{
Name: "v2.0.4-beta.1",
Subject: "Release v2.0.4-beta.1",
Date: time.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
Next: &RelateTag{
Name: "v2.0.4-beta.2",
Subject: "Release v2.0.4-beta.2",
Date: time.Date(2018, 2, 3, 12, 15, 0, 0, time.UTC),
},
&Tag{
Name: "v2.0.4-beta.1",
Subject: "Release v2.0.4-beta.1",
Date: time.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
Next: nil,
Previous: nil,
},
},
actualFiltered,
actual_filtered,
)
}

View file

@ -19,16 +19,14 @@ func (s *tagSelector) Select(tags []*Tag, query string) ([]*Tag, string, error)
case 2:
old := tokens[0]
new := tokens[1]
switch {
case old == "" && new == "":
if old == "" && new == "" {
return nil, "", nil
case old == "":
} else if old == "" {
return s.selectBeforeTags(tags, new)
case new == "":
} else if new == "" {
return s.selectAfterTags(tags, old)
default:
return s.selectRangeTags(tags, tokens[0], tokens[1])
}
return s.selectRangeTags(tags, tokens[0], tokens[1])
}
return nil, "", errFailedQueryParse
@ -78,8 +76,7 @@ func (*tagSelector) selectBeforeTags(tags []*Tag, token string) ([]*Tag, string,
}
func (*tagSelector) selectAfterTags(tags []*Tag, token string) ([]*Tag, string, error) {
// NOTE(clok): the res slice can range in size based on the token passed in.
var ( //nolint:prealloc
var (
res []*Tag
from string
)

View file

@ -12,51 +12,51 @@ func TestTagSelector(t *testing.T) {
selector := newTagSelector()
fixtures := []*Tag{
{Name: "2.2.12-rc.12"},
{Name: "2.1.0"},
{Name: "v2.0.0-beta.1"},
{Name: "v1.2.9"},
{Name: "v1.0.0"},
&Tag{Name: "2.2.12-rc.12"},
&Tag{Name: "2.1.0"},
&Tag{Name: "v2.0.0-beta.1"},
&Tag{Name: "v1.2.9"},
&Tag{Name: "v1.0.0"},
}
table := map[string][]string{
// Single
"2.2.12-rc.12": {
"2.2.12-rc.12": []string{
"2.2.12-rc.12",
"2.1.0",
},
"v2.0.0-beta.1": {
"v2.0.0-beta.1": []string{
"v2.0.0-beta.1",
"v1.2.9",
},
"v1.0.0": {
"v1.0.0": []string{
"v1.0.0",
"",
},
// ~ <tag>
"..2.1.0": {
"..2.1.0": []string{
"2.1.0",
"v2.0.0-beta.1",
"v1.2.9",
"v1.0.0",
"",
},
"..v1.0.0": {
"..v1.0.0": []string{
"v1.0.0",
"",
},
// <tag> ~
"v2.0.0-beta.1..": {
"v2.0.0-beta.1..": []string{
"2.2.12-rc.12",
"2.1.0",
"v2.0.0-beta.1",
"v1.2.9",
},
"2.2.12-rc.12..": {
"2.2.12-rc.12..": []string{
"2.2.12-rc.12",
"2.1.0",
},
"v1.0.0..": {
"v1.0.0..": []string{
"2.2.12-rc.12",
"2.1.0",
"v2.0.0-beta.1",
@ -65,7 +65,7 @@ func TestTagSelector(t *testing.T) {
"",
},
// <tag> ~ <tag>
"v1.0.0..2.2.12-rc.12": {
"v1.0.0..2.2.12-rc.12": []string{
"2.2.12-rc.12",
"2.1.0",
"v2.0.0-beta.1",
@ -73,13 +73,13 @@ func TestTagSelector(t *testing.T) {
"v1.0.0",
"",
},
"v1.0.0..v2.0.0-beta.1": {
"v1.0.0..v2.0.0-beta.1": []string{
"v2.0.0-beta.1",
"v1.2.9",
"v1.0.0",
"",
},
"v1.2.9..2.1.0": {
"v1.2.9..2.1.0": []string{
"2.1.0",
"v2.0.0-beta.1",
"v1.2.9",

View file

@ -1,48 +0,0 @@
{{ if .Versions -}}
<a name="unreleased"></a>
## [Unreleased]
{{ if .Unreleased.CommitGroups -}}
{{ range .Unreleased.CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{ if .TrimmedBody -}}
{{ indent .TrimmedBody 2 }}
{{ end -}}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}
{{ range .Versions }}
<a name="{{ .Tag.Name }}"></a>
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
{{ range .CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{ if .TrimmedBody -}}
{{ indent .TrimmedBody 2 }}
{{ end -}}
{{ end }}
{{ end -}}
{{- if .NoteGroups -}}
{{ range .NoteGroups -}}
### {{ .Title }}
{{ range .Notes }}
{{ .Body }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}
{{- if .Versions }}
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
{{ range .Versions -}}
{{ if .Tag.Previous -}}
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
{{ end -}}
{{ end -}}
{{ end -}}

View file

@ -1,57 +0,0 @@
{{ title "my changelog" }}
{{ if .Versions -}}
<a name="unreleased"></a>
## [Unreleased]
{{ if .Unreleased.CommitGroups -}}
{{ range .Unreleased.CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}
{{ range .Versions }}
<a name="{{ .Tag.Name }}"></a>
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
{{ range .CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
- {{ if .Scope }}**{{ .Scope | upper }}:** {{ end }}{{ .Subject }}
{{ end }}
{{ end -}}
{{- if .RevertCommits -}}
### Reverts
{{ range .RevertCommits -}}
- {{ .Revert.Header }}
{{ end }}
{{ end -}}
{{- if .MergeCommits -}}
### Pull Requests
{{ range .MergeCommits -}}
- {{ .Header }}
{{ end }}
{{ end -}}
{{- if .NoteGroups -}}
{{ range .NoteGroups -}}
### {{ .Title }}
{{ range .Notes }}
{{ .Body }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}
{{- if .Versions }}
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
{{ range .Versions -}}
{{ if .Tag.Previous -}}
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
{{ end -}}
{{ end -}}
{{ end -}}

View file

@ -23,7 +23,6 @@ func dotGet(target interface{}, prop string) (interface{}, bool) {
value = reflect.ValueOf(target)
}
//nolint:staticcheck
field := value.FieldByName(strings.Title(key))
if !field.IsValid() {
return nil, false