Compare commits

..

1 Commits

Author SHA1 Message Date
Sebastian
0a2a2d2c5b test 2020-01-30 15:02:21 +01:00
47 changed files with 582 additions and 2892 deletions

View File

@@ -1,30 +1,24 @@
name: Go name: Go
on: on: [push, pull_request]
pull_request:
push:
branches:
- master
jobs: jobs:
build: build:
strategy: name: Build
matrix:
go: ["1.13", "1.14", "1.15", "1.16"]
name: Build with go version ${{ matrix.go }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up GoLang ${{ matrix.go }} - name: Set up Go 1.13
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: ${{ matrix.go }} go-version: 1.13
id: go id: go
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: golangci-lint - name: Lint
uses: golangci/golangci-lint-action@v2 run: |
with: export PATH=$PATH:$(go env GOPATH)/bin
version: v1.29 curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.18.0
golangci-lint run ./...
- name: Run tests - name: Run tests
run: go test ./... run: go test ./...
@@ -35,52 +29,27 @@ jobs:
run: | run: |
go build -o build/go-semantic-release-temp ./cmd/go-semantic-release/ go build -o build/go-semantic-release-temp ./cmd/go-semantic-release/
./build/go-semantic-release-temp next --no-cache --loglevel trace ./build/go-semantic-release-temp next --no-cache --loglevel trace
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o build/go-semantic-release.linux_x86_64 -ldflags "-w -s --X main.version=`./build/go-semantic-release-temp next`" ./cmd/go-semantic-release/ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o build/go-semantic-release -ldflags "-w -s --X main.version=`./build/go-semantic-release-temp next`" ./cmd/go-semantic-release/
GOOS=windows GOARCH=386 CGO_ENABLED=0 go build -o build/go-semantic-release.windows_i386.exe -ldflags "-w -s -X main.version=`./build/go-semantic-release-temp next`" ./cmd/go-semantic-release/ GOOS=windows GOARCH=386 CGO_ENABLED=0 go build -o build/go-semantic-release.exe -ldflags "-w -s -X main.version=`./build/go-semantic-release-temp next`" ./cmd/go-semantic-release/
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o build/go-semantic-release.windows_x86_64.exe -ldflags "-w -s -X main.version=`./build/go-semantic-release-temp next`" ./cmd/go-semantic-release/
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -o build/go-semantic-release.darwin_x86_64 -ldflags "-w -s -X main.version=`./build/go-semantic-release-temp next`" ./cmd/go-semantic-release/ - name: Build Docker image
- name: Build Docker image PR
if: github.ref != 'refs/heads/master' if: github.ref != 'refs/heads/master'
run: |
docker build -t nightapes/go-semantic-release:development-${{matrix.go}} .
- name: Build Docker image master
if: github.ref == 'refs/heads/master'
run: | run: |
docker login -u nightapes -p ${{ secrets.DOCKER_PASSWORD }} docker login -u nightapes -p ${{ secrets.DOCKER_PASSWORD }}
docker login -u nightapes -p ${{ secrets.GITHUB_TOKEN }} docker.pkg.github.com docker login -u nightapes -p ${{ secrets.GITHUB_TOKEN }} docker.pkg.github.com
docker build -t nightapes/go-semantic-release:development-${{matrix.go}} . docker build -t nightapes/go-semantic-release:development .
docker push nightapes/go-semantic-release:development-${{matrix.go}} docker push nightapes/go-semantic-release:development
docker tag nightapes/go-semantic-release:development-${{matrix.go}} docker.pkg.github.com/nightapes/go-semantic-release/go-semantic-release:development-${{matrix.go}} docker tag nightapes/go-semantic-release:development docker.pkg.github.com/nightapes/go-semantic-release/go-semantic-release:development
docker push docker.pkg.github.com/nightapes/go-semantic-release/go-semantic-release:development-${{matrix.go}} docker push docker.pkg.github.com/nightapes/go-semantic-release/go-semantic-release:development
- uses: actions/upload-artifact@v1
if: matrix.go == '1.15' - name: Push Docker image
with: if: github.ref != 'refs/heads/master'
name: build run: |
path: build
release:
name: Release
runs-on: ubuntu-latest
needs: build
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v1
- uses: actions/download-artifact@v1
with:
name: build
path: build
- name: Release - name: Release
if: github.ref == 'refs/heads/master'
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
chmod -R +x build
docker login -u nightapes -p ${{ secrets.DOCKER_PASSWORD }} docker login -u nightapes -p ${{ secrets.DOCKER_PASSWORD }}
docker login -u nightapes -p $GITHUB_TOKEN docker.pkg.github.com docker login -u nightapes -p $GITHUB_TOKEN docker.pkg.github.com
./build/go-semantic-release-temp release --loglevel trace ./build/go-semantic-release-temp release --loglevel trace
- name: Release PR
if: github.ref != 'refs/heads/master'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
chmod -R +x build
./build/go-semantic-release-temp release --loglevel trace

View File

@@ -7,14 +7,10 @@ branch:
master: release master: release
beta: beta beta: beta
assets: assets:
- name: ./build/go-semantic-release.linux_x86_64 - name: ./build/go-semantic-release
compress: true compress: false
- name: ./build/go-semantic-release.windows_i386.exe - name: ./build/go-semantic-release.exe
compress: true compress: false
- name: ./build/go-semantic-release.windows_x86_64.exe
compress: true
- name: ./build/go-semantic-release.darwin_x86_64
compress: true
changelog: changelog:
docker: docker:
latest: true latest: true

View File

@@ -2,8 +2,8 @@ FROM alpine:3.10.2
WORKDIR /code WORKDIR /code
COPY ./build/go-semantic-release.linux_x86_64 . COPY ./build/go-semantic-release .
USER 1000 USER 1000
ENTRYPOINT [ "./go-semantic-release.linux_x86_64" ] ENTRYPOINT [ "./go-semantic-release" ]

View File

@@ -1,14 +0,0 @@
all: build
.PHONY: build
build:
go build -o build/go-semantic-release-temp ./cmd/go-semantic-release/
lint:
golangci-lint run --print-issued-lines=false --fix ./...
test:
go test --coverprofile coverage.out -v -race -parallel 20 ./...

145
README.md
View File

@@ -1,10 +1,8 @@
# go-semantic-release # go-semantic-release
![go-semantic-release](https://github.com/Nightapes/go-semantic-release/workflows/Go/badge.svg)
## Release Types ## Release Types
| Type | Implemented | Git tag | Changelog | Release | Write access git | Api token | | Type | Implemendet | Git tag | Changelog | Release | Write access git | Api token |
| ----------- | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | | ----------- | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: |
| `github` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | | `github` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: |
| `gitlab` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: | | `gitlab` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | :white_check_mark: |
@@ -19,18 +17,6 @@
* Travis CI * Travis CI
* Custom CI, set enviroment `CI=true` * Custom CI, set enviroment `CI=true`
## Download
You can download the newest version under [releases](https://github.com/Nightapes/go-semantic-release/releases)
or
you can use a Docker image
`docker pull nightapes/go-semantic-release:<VERSION>` or `docker pull docker.pkg.github.com/nightapes/go-semantic-release/go-semantic-release:<VERSION>`
## How to use ## How to use
`go-semantic-release` config file `go-semantic-release` config file
@@ -56,26 +42,15 @@ hooks:
- name: echo $RELEASE_VERSION - name: echo $RELEASE_VERSION
postRelease: postRelease:
- name: echo $RELEASE_VERSION - name: echo $RELEASE_VERSION
integrations:
npm:
enabled: true
``` ```
#### CommitFormat #### CommitFormat t
Supported formats: Set the commit format, at the moment we support ony [angular](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit-message-format), more coming soon.
* [angular](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit-message-format) ```yml
commitFormat: angular
```yml ```
commitFormat: angular
```
* [conventional](https://www.conventionalcommits.org/en/v1.0.0/#summaryhttps://www.conventionalcommits.org/en/v1.0.0/#summary)
```yml
commitFormat: conventional
```
#### Branch #### Branch
@@ -108,24 +83,21 @@ release: 'github'
github: github:
user: "<user/group" user: "<user/group"
repo: "<repositroyname>" repo: "<repositroyname>"
## Optional, if you are not using github.com ## Optional, if your not using github.com
customUrl: <https://your.github> customUrl: <https://your.github>
## Optional, if you want to change the default tag prefix ("v")
tagPrefix: ""
``` ```
##### Gitlab ##### Gitlab
You need to set the env `GITLAB_ACCESS_TOKEN` with an personal access token. You need to set the env `GITLAB_ACCESS_TOKEN` with an personal access token.
```yml ```yml
release: 'gitlab' release: 'gitlab'
gitlab: gitlab:
repo: "<repositroyname>" ## Example group/project repo: "<repositroyname>" ## Example group/project
## Optional, if your not using gitlab.com ## Optional, if your not using gitlab.com
customUrl: <https://your.gitlab> customUrl: <https://your.gitlab>
## Optional, if you want to change the default tag prefix ("v")
tagPrefix: ""
``` ```
##### Git only ##### Git only
@@ -139,8 +111,6 @@ git:
email: "<email>" # Used for creating tag email: "<email>" # Used for creating tag
user: "<user>" : # Used for creating tag and pushing user: "<user>" : # Used for creating tag and pushing
auth: "<token>" # Used for pushing, can be env "$GIT_TOKEN", will be replaced with env auth: "<token>" # Used for pushing, can be env "$GIT_TOKEN", will be replaced with env
## Optional, if you want to change the default tag prefix ("v")
tagPrefix: ""
``` ```
@@ -159,82 +129,18 @@ assets:
#### Hooks #### Hooks
Hooks will run when calling `release`. Hooks run only if a release will be triggered. Hooks will run when calling `release`. Hooks run only if a release will be triggered.
You can define hooks which run before or after the release. The shell commands will run in order, you can access the current release version via
an environment variable `RELEASE_VERSION`
```yml
hooks:
preRelease:
- name: echo $RELEASE_VERSION
postRelease:
- name: echo $RELEASE_VERSION
```
#### Integrations
Integrations are simple helpers to make integration with existing tools easier.
At the moment npm is supported, the integration will set the version before release to the `package.json`
```yml
integrations:
npm:
enabled: true
```
#### Changelog #### Changelog
Following variables and objects can be used for templates: Following variables can be used for templates:
* `Commits` string
__Top level__ * `Version` string
* `Now` time.Time
| Field | Type | Description | * `Backtick` string
| -------- | ------ | ----- | * `HasDocker` bool
| `Commits` | string | Fully rendered commit messages. This is left for backward compatibility. | * `HasDockerLatest` bool
| `CommitsContent` | commitsContent | Raw parsed commit data. Use this if you want to customize the output. | * `DockerRepository` string
| `Version` | string | Next release version |
| `Now` | time.Time | Current time of generating changelog |
| `Backtick` | string | Backtick character |
| `HasDocker` | bool | If a docker repository is set in the config. |
| `HasDockerLatest` | bool | If `latest` image was uploaded |
| `DockerRepository` | string | Docker repository |
__commitsContent__
| Field | Type | Description |
| -------- | ------ | ----- |
| `Commits` | map[string][]AnalyzedCommit | Commits grouped by commit type |
| `BreakingChanges` | []AnalyzedCommit | Analyzed commit structure |
| `Order` | []string | Ordered list of types |
| `HasURL` | bool | If a URL is available for commits |
| `URL` | string | URL for to the commit with {{hash}} suffix |
__AnalyzedCommit__
| Field | Type | Description |
| -------- | ------ | ----- |
| `Commit` | Commit | Original GIT commit |
| `Tag` | string | Type of commit (e.g. feat, fix, ...) |
| `TagString` | string | Full name of the type |
| `Scope` | bool | Scope value from the commit |
| `Subject` | string | URL for to the commit with {{hash}} suffix |
| `MessageBlocks` | map[string][]MessageBlock | Different sections of a message (e.g. body, footer etc.) |
| `IsBreaking` | bool | If this commit contains a breaking change |
| `Print` | bool | Should this commit be included in Changelog output |
__Commit__
| Field | Type | Description |
| -------- | ------ | ----- |
| `Message` | string | Original git commit message |
| `Author` | string | Name of the author |
| `Hash` | string | Commit hash value "|
__MessageBlock__
| Field | Type | Description |
| -------- | ------ | ----- |
| `Label` | string | Label for a block (optional). This will usually be a token used in a footer |
| `Content` | string | The parsed content of a block |
```yml ```yml
changelog: changelog:
@@ -254,21 +160,9 @@ changelog:
repository: ## Your docker repository, which is used for docker run repository: ## Your docker repository, which is used for docker run
``` ```
##### NPM
You can print a help text for a npm package
```yml
changelog:
npm:
name: ## Name of the npm package
repository: ## Your docker repository, which is used for docker run
```
### Version ### Version
`go-semantic-release` has two modes for calculating the version: automatic or manual. `go-semantic-release` has two modes for calcualting the version: automatic or manual.
#### Automatic #### Automatic
@@ -288,8 +182,7 @@ following command:
Print the next version, can be used to add version to your program Print the next version, can be used to add version to your program
```bash ```bash
./go-semantic-release next // show next version (calculated by new commits since last version) ./go-semantic-release next
./go-semantic-release last // show last released version
``` ```
Example with go-lang Example with go-lang

View File

@@ -7,7 +7,6 @@ import (
) )
func init() { func init() {
changelogCmd.Flags().Bool("checks", false, "Check for missing values and envs")
changelogCmd.Flags().StringP("out", "o", "CHANGELOG.md", "Name of the file") changelogCmd.Flags().StringP("out", "o", "CHANGELOG.md", "Name of the file")
rootCmd.AddCommand(changelogCmd) rootCmd.AddCommand(changelogCmd)
} }
@@ -36,12 +35,12 @@ var changelogCmd = &cobra.Command{
return err return err
} }
configChecks, err := cmd.Flags().GetBool("checks") ignoreConfigChecks, err := cmd.Flags().GetBool("no-checks")
if err != nil { if err != nil {
return err return err
} }
s, err := semanticrelease.New(readConfig(config), repository, configChecks) s, err := semanticrelease.New(readConfig(config), repository, !ignoreConfigChecks)
if err != nil { if err != nil {
return err return err
} }
@@ -62,6 +61,10 @@ var changelogCmd = &cobra.Command{
return err return err
} }
return s.WriteChangeLog(generatedChangelog.Content, file) if err = s.WriteChangeLog(generatedChangelog.Content, file); err != nil {
log.Fatal(err)
}
return nil
}, },
} }

View File

@@ -7,7 +7,6 @@ import (
) )
func init() { func init() {
hooksCmd.Flags().Bool("checks", false, "Check for missing values and envs")
rootCmd.AddCommand(hooksCmd) rootCmd.AddCommand(hooksCmd)
} }
@@ -30,14 +29,14 @@ var hooksCmd = &cobra.Command{
return err return err
} }
configChecks, err := cmd.Flags().GetBool("checks") ignoreConfigChecks, err := cmd.Flags().GetBool("no-checks")
if err != nil { if err != nil {
return err return err
} }
releaseConfig := readConfig(config) releaseConfig := readConfig(config)
s, err := semanticrelease.New(releaseConfig, repository, configChecks) s, err := semanticrelease.New(releaseConfig, repository, !ignoreConfigChecks)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -1,62 +0,0 @@
package commands
import (
"github.com/Nightapes/go-semantic-release/internal/integrations"
"github.com/Nightapes/go-semantic-release/pkg/semanticrelease"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
func init() {
integrationsCmd.Flags().Bool("checks", false, "Check for missing values and envs")
integrationsCmd.Flags().StringP("out", "o", "CHANGELOG.md", "Name of the file")
rootCmd.AddCommand(integrationsCmd)
}
var integrationsCmd = &cobra.Command{
Use: "integrations",
Short: "Call integrations from config file manual",
RunE: func(cmd *cobra.Command, args []string) error {
config, err := cmd.Flags().GetString("config")
if err != nil {
return err
}
repository, err := cmd.Flags().GetString("repository")
if err != nil {
return err
}
force, err := cmd.Flags().GetBool("no-cache")
if err != nil {
return err
}
configChecks, err := cmd.Flags().GetBool("checks")
if err != nil {
return err
}
releaseConfig := readConfig(config)
s, err := semanticrelease.New(releaseConfig, repository, configChecks)
if err != nil {
return err
}
provider, err := s.GetCIProvider()
if err != nil {
return err
}
releaseVersion, err := s.GetNextVersion(provider, force)
if err != nil {
return err
}
log.Debugf("Found %d commits till last release", len(releaseVersion.Commits))
i := integrations.New(&releaseConfig.Integrations, releaseVersion)
return i.Run()
},
}

View File

@@ -1,59 +0,0 @@
package commands
import (
"fmt"
"github.com/Nightapes/go-semantic-release/pkg/semanticrelease"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
func init() {
lastCmd.Flags().Bool("checks", false, "Check for missing values and envs")
rootCmd.AddCommand(lastCmd)
}
var lastCmd = &cobra.Command{
Use: "last",
Short: "Get last version",
RunE: func(cmd *cobra.Command, args []string) error {
config, err := cmd.Flags().GetString("config")
if err != nil {
return err
}
repository, err := cmd.Flags().GetString("repository")
if err != nil {
return err
}
force, err := cmd.Flags().GetBool("no-cache")
if err != nil {
return err
}
configChecks, err := cmd.Flags().GetBool("checks")
if err != nil {
return err
}
s, err := semanticrelease.New(readConfig(config), repository, configChecks)
if err != nil {
return err
}
provider, err := s.GetCIProvider()
if err != nil {
log.Infof("Will not calculate version, set fake version. Could not find CI Provider, if running locally, set env CI=true")
fmt.Println("0.0.0-fake.0")
return nil
}
releaseVersion, err := s.GetNextVersion(provider, force)
if err != nil {
return err
}
fmt.Println(releaseVersion.Last.Version.String())
return nil
},
}

View File

@@ -8,7 +8,6 @@ import (
) )
func init() { func init() {
nextCmd.Flags().Bool("checks", false, "Check for missing values and envs")
rootCmd.AddCommand(nextCmd) rootCmd.AddCommand(nextCmd)
} }
@@ -31,12 +30,12 @@ var nextCmd = &cobra.Command{
return err return err
} }
configChecks, err := cmd.Flags().GetBool("checks") ignoreConfigChecks, err := cmd.Flags().GetBool("no-checks")
if err != nil { if err != nil {
return err return err
} }
s, err := semanticrelease.New(readConfig(config), repository, configChecks) s, err := semanticrelease.New(readConfig(config), repository, !ignoreConfigChecks)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -6,7 +6,6 @@ import (
) )
func init() { func init() {
releaseCmd.Flags().Bool("no-checks", false, "Ignore missing values and envs")
rootCmd.AddCommand(releaseCmd) rootCmd.AddCommand(releaseCmd)
} }

View File

@@ -35,6 +35,7 @@ func init() {
rootCmd.PersistentFlags().StringP("loglevel", "l", "error", "Set loglevel") rootCmd.PersistentFlags().StringP("loglevel", "l", "error", "Set loglevel")
rootCmd.PersistentFlags().StringP("config", "c", ".release.yml", "Path to config file") rootCmd.PersistentFlags().StringP("config", "c", ".release.yml", "Path to config file")
rootCmd.PersistentFlags().Bool("no-cache", false, "Ignore cache, don't use in ci build") rootCmd.PersistentFlags().Bool("no-cache", false, "Ignore cache, don't use in ci build")
rootCmd.PersistentFlags().Bool("no-checks", false, "Ignore missing values and envs")
} }
func readConfig(file string) *config.ReleaseConfig { func readConfig(file string) *config.ReleaseConfig {

View File

@@ -7,7 +7,6 @@ import (
) )
func init() { func init() {
setCmd.Flags().Bool("checks", false, "Check for missing values and envs")
rootCmd.AddCommand(setCmd) rootCmd.AddCommand(setCmd)
} }
@@ -27,12 +26,12 @@ var setCmd = &cobra.Command{
return err return err
} }
configChecks, err := cmd.Flags().GetBool("checks") ignoreConfigChecks, err := cmd.Flags().GetBool("no-checks")
if err != nil { if err != nil {
return err return err
} }
s, err := semanticrelease.New(readConfig(config), repository, configChecks) s, err := semanticrelease.New(readConfig(config), repository, !ignoreConfigChecks)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -6,8 +6,6 @@ import (
) )
func init() { func init() {
zipCmd.Flags().Bool("checks", false, "Check for missing values and envs")
zipCmd.Flags().StringP("algorithm", "a", "sha256", "Algorithm for checksum (crc32,md5,sha1,sha224,sha384,sha256,sha512)")
rootCmd.AddCommand(zipCmd) rootCmd.AddCommand(zipCmd)
} }
@@ -25,12 +23,12 @@ var zipCmd = &cobra.Command{
return err return err
} }
configChecks, err := cmd.Flags().GetBool("checks") ignoreConfigChecks, err := cmd.Flags().GetBool("no-checks")
if err != nil { if err != nil {
return err return err
} }
s, err := semanticrelease.New(readConfig(config), repository, configChecks) s, err := semanticrelease.New(readConfig(config), repository, !ignoreConfigChecks)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -1,26 +1,5 @@
{{ define "commitList" }}
{{ range $index,$commit := .BreakingChanges -}}
{{ if eq $index 0 -}}
## BREAKING CHANGES
{{ end -}}
* {{ if $commit.Scope }}**{{$.Backtick}}{{$commit.Scope}}{{$.Backtick}}**{{ end }} {{$commit.ParsedBreakingChangeMessage}}
introduced by commit:
{{$commit.ParsedMessage}} {{if $.HasURL}} ([{{ printf "%.7s" $commit.Commit.Hash}}]({{ replace $.URL "{{hash}}" $commit.Commit.Hash}})){{end}}
{{ end -}}
{{ range $key := .Order -}}
{{ $commits := index $.Commits $key -}}
{{ if $commits -}}
### {{ $key }}
{{ range $index,$commit := $commits -}}
* {{ if $commit.Scope }}**{{$.Backtick}}{{$commit.Scope}}{{$.Backtick}}** {{end}}{{$commit.ParsedMessage}}{{if $.HasURL}} ([{{ printf "%.7s" $commit.Commit.Hash}}]({{ replace $.URL "{{hash}}" $commit.Commit.Hash}})){{end}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
# My custom release template v{{$.Version}} ({{.Now.Format "2006-01-02"}}) # My custom release template v{{$.Version}} ({{.Now.Format "2006-01-02"}})
{{ template "commitList" .CommitsContent -}} {{ .Commits -}}
{{ if .HasDocker}} {{ if .HasDocker}}
## Docker image ## Docker image

38
go.mod
View File

@@ -3,27 +3,21 @@ module github.com/Nightapes/go-semantic-release
go 1.13 go 1.13
require ( require (
github.com/Masterminds/semver v1.5.0 github.com/Masterminds/semver v1.4.2
github.com/Microsoft/go-winio v0.4.16 // indirect github.com/gliderlabs/ssh v0.2.2 // indirect
github.com/go-git/go-billy/v5 v5.0.0 github.com/google/go-cmp v0.3.0 // indirect
github.com/go-git/go-git/v5 v5.2.0
github.com/golang/protobuf v1.4.3 // indirect
github.com/google/go-github/v25 v25.1.3 github.com/google/go-github/v25 v25.1.3
github.com/imdario/mergo v0.3.11 // indirect github.com/kevinburke/ssh_config v0.0.0-20190630040420-2e50c441276c // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/pkg/errors v0.8.1
github.com/magefile/mage v1.11.0 // indirect github.com/sirupsen/logrus v1.4.2
github.com/pkg/errors v0.9.1 github.com/spf13/cobra v0.0.5
github.com/sirupsen/logrus v1.8.0 github.com/stretchr/testify v1.3.0
github.com/spf13/cobra v1.1.3 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
github.com/stretchr/testify v1.7.0 golang.org/x/net v0.0.0-20190628185345-da137c7871d7 // indirect
github.com/tidwall/pretty v1.1.0 // indirect golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
github.com/tidwall/sjson v1.1.5 golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect google.golang.org/appengine v1.6.1 // indirect
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect gopkg.in/src-d/go-billy.v4 v4.3.1
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 // indirect gopkg.in/src-d/go-git.v4 v4.12.0
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93 gopkg.in/yaml.v2 v2.2.2
golang.org/x/sys v0.0.0-20210223212115-eede4237b368 // indirect
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )

611
go.sum
View File

@@ -1,624 +1,161 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.3/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M=
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI=
github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= 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-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github/v25 v25.1.3 h1:Ht4YIQgUh4l4lc80fvGnw60khXysXvlgPxPP8uJG3EA= github.com/google/go-github/v25 v25.1.3 h1:Ht4YIQgUh4l4lc80fvGnw60khXysXvlgPxPP8uJG3EA=
github.com/google/go-github/v25 v25.1.3/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw= github.com/google/go-github/v25 v25.1.3/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/kevinburke/ssh_config v0.0.0-20190630040420-2e50c441276c h1:VAx3LRNjVNvjtgO7KFRuT/3aye/0zJvwn01rHSfoolo=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kevinburke/ssh_config v0.0.0-20190630040420-2e50c441276c/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tidwall/gjson v1.6.8 h1:CTmXMClGYPAmln7652e69B7OLXfTi5ABcPPwjIWUv7w=
github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/sjson v1.1.5 h1:wsUceI/XDyZk3J1FUvuuYlK62zJv2HO2Pzb8A5EWdUE=
github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM=
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93 h1:alLDrZkL34Y2bnGHfvC1CYBRBXCXgx8AC2vY4MRtYX4=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9 h1:lkiLiLBHGoH3XnqSLUIaBsilGMUjI+Uy2Xu2JLUtTas=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210223212115-eede4237b368 h1:fDE3p0qf2V1co1vfj3/o87Ps8Hq6QTGNxJ5Xe7xSp80=
golang.org/x/sys v0.0.0-20210223212115-eede4237b368/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/src-d/go-billy.v4 v4.3.1 h1:OkK1DmefDy1Z6Veu82wdNj/cLpYORhdX4qdaYCPwc7s=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/src-d/go-billy.v4 v4.3.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/src-d/go-git.v4 v4.12.0 h1:CKgvBCJCcdfNnyXPYI4Cp8PaDDAmAPEN0CtfEdEAbd8=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-git.v4 v4.12.0/go.mod h1:zjlNnzc1Wjn43v3Mtii7RVxiReNP0fIu9npcXKzuNp4=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
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.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@@ -2,29 +2,20 @@
package analyzer package analyzer
import ( import (
"bufio"
"fmt" "fmt"
"regexp"
"strings"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
const breakingChangeKeywords = "BREAKING CHANGE" //Analyzer struct
const defaultBreakingChangePrefix = breakingChangeKeywords + ":"
const footerTokenRegex = "^(?P<token>[^\\s][\\w\\- ]+[^\\s])<SEP>.*"
var defaultTokenSeparators = [2]string{ ": ", " #"}
// Analyzer struct
type Analyzer struct { type Analyzer struct {
analyzeCommits analyzeCommits analyzeCommits analyzeCommits
ChangelogConfig config.ChangelogConfig Config config.ChangelogConfig
AnalyzerConfig config.AnalyzerConfig
} }
// Rule for commits //Rule for commits
type Rule struct { type Rule struct {
Tag string Tag string
TagString string TagString string
@@ -33,28 +24,25 @@ type Rule struct {
} }
type analyzeCommits interface { type analyzeCommits interface {
analyze(commit shared.Commit, tag Rule) *shared.AnalyzedCommit analyze(commit shared.Commit, tag Rule) (shared.AnalyzedCommit, bool, error)
getRules() []Rule getRules() []Rule
} }
// New Analyzer struct for given commit format //New Analyzer struct for given commit format
func New(format string, analyzerConfig config.AnalyzerConfig, chglogConfig config.ChangelogConfig) (*Analyzer, error) { func New(format string, config config.ChangelogConfig) (*Analyzer, error) {
analyzer := &Analyzer{ analyzer := &Analyzer{
AnalyzerConfig: analyzerConfig, Config: config,
ChangelogConfig: chglogConfig,
} }
switch format { switch format {
case ANGULAR: case ANGULAR:
analyzer.analyzeCommits = newAngular() analyzer.analyzeCommits = newAngular()
log.Debugf("Commit format set to %s", ANGULAR) log.Debugf("Commit format set to %s", ANGULAR)
case CONVENTIONAL:
analyzer.analyzeCommits = newConventional(analyzerConfig)
log.Debugf("Commit format set to %s", CONVENTIONAL)
default: default:
return nil, fmt.Errorf("invalid commit format: %s", format) return nil, fmt.Errorf("invalid commit format: %s", format)
} }
return analyzer, nil return analyzer, nil
} }
// GetRules from current mode // GetRules from current mode
@@ -62,8 +50,9 @@ func (a *Analyzer) GetRules() []Rule {
return a.analyzeCommits.getRules() return a.analyzeCommits.getRules()
} }
// Analyze commits and return commits split by major,minor,patch // Analyze commits and return commits splitted by major,minor,patch
func (a *Analyzer) Analyze(commits []shared.Commit) map[shared.Release][]shared.AnalyzedCommit { func (a *Analyzer) Analyze(commits []shared.Commit) map[shared.Release][]shared.AnalyzedCommit {
analyzedCommits := make(map[shared.Release][]shared.AnalyzedCommit) analyzedCommits := make(map[shared.Release][]shared.AnalyzedCommit)
analyzedCommits["major"] = make([]shared.AnalyzedCommit, 0) analyzedCommits["major"] = make([]shared.AnalyzedCommit, 0)
analyzedCommits["minor"] = make([]shared.AnalyzedCommit, 0) analyzedCommits["minor"] = make([]shared.AnalyzedCommit, 0)
@@ -72,132 +61,25 @@ func (a *Analyzer) Analyze(commits []shared.Commit) map[shared.Release][]shared.
for _, commit := range commits { for _, commit := range commits {
for _, rule := range a.analyzeCommits.getRules() { for _, rule := range a.analyzeCommits.getRules() {
analyzedCommit := a.analyzeCommits.analyze(commit, rule) analyzedCommit, hasBreakingChange, err := a.analyzeCommits.analyze(commit, rule)
if analyzedCommit == nil { if err == nil {
continue if a.Config.PrintAll {
} analyzedCommit.Print = true
if a.ChangelogConfig.PrintAll || rule.Changelog { } else {
analyzedCommit.Print = true analyzedCommit.Print = rule.Changelog
} }
if analyzedCommit.IsBreaking { if hasBreakingChange {
analyzedCommits["major"] = append(analyzedCommits["major"], *analyzedCommit) analyzedCommits["major"] = append(analyzedCommits["major"], analyzedCommit)
} else {
analyzedCommits[rule.Release] = append(analyzedCommits[rule.Release], analyzedCommit)
}
break break
} }
analyzedCommits[rule.Release] = append(analyzedCommits[rule.Release], *analyzedCommit)
break
} }
} }
log.Debugf("Analyzed commits: major=%d minor=%d patch=%d none=%d", len(analyzedCommits["major"]), len(analyzedCommits["minor"]), len(analyzedCommits["patch"]), len(analyzedCommits["none"])) log.Debugf("Analyzed commits: major=%d minor=%d patch=%d none=%d", len(analyzedCommits["major"]), len(analyzedCommits["minor"]), len(analyzedCommits["patch"]), len(analyzedCommits["none"]))
return analyzedCommits return analyzedCommits
} }
//
// getRegexMatchedMap will match a regex with named groups and map the matching
// results to corresponding group names
//
func getRegexMatchedMap(regEx, url string) (paramsMap map[string]string) {
var compRegEx = regexp.MustCompile(regEx)
match := compRegEx.FindStringSubmatch(url)
paramsMap = make(map[string]string)
for i, name := range compRegEx.SubexpNames() {
if i > 0 && i <= len(match) {
paramsMap[name] = match[i]
}
}
return paramsMap
}
//
// getMessageBlocksFromTexts converts strings to an array of MessageBlock
//
func getMessageBlocksFromTexts(txtArray, separators []string) []shared.MessageBlock {
blocks := make([]shared.MessageBlock, len(txtArray))
for i, line := range txtArray{
blocks[i] = parseMessageBlock(line, separators)
}
return blocks
}
//
// parseMessageBlock parses a text in to MessageBlock
//
func parseMessageBlock(msg string, separators []string) shared.MessageBlock {
msgBlock := shared.MessageBlock{
Label: "",
Content: msg,
}
if token, sep := findFooterToken(msg, separators); len(token) > 0{
msgBlock.Label = token
content := strings.Replace(msg, token + sep, "", 1)
msgBlock.Content = strings.TrimSpace(content)
}
return msgBlock
}
//
// findFooterToken checks if given text has a token with one of the separators and returns a token
//
func findFooterToken(text string, separators []string) (token string, sep string) {
for _, sep := range separators {
regex := strings.Replace(footerTokenRegex, "<SEP>", sep, 1)
matches := getRegexMatchedMap(regex, text)
if token, ok := matches["token"]; ok {
return token, sep
}
}
return "", ""
}
//
// getDefaultMessageBlockMap parses a text block and splits in to different sections.
// default logic to distinguish different parts is:
// - Body starts right after the header (without beginning with a token)
// - Body ends when a footer is discovered or text ends
// - A footer is detected when it starts with a token ending with a separator
// - A footer ends when another footer is found or text ends
//
func getDefaultMessageBlockMap(txtBlock string, tokenSep []string) map[string][]shared.MessageBlock{
msgBlockMap := make(map[string][]shared.MessageBlock)
footers := make([]string, 0)
body, footerBlock, line := "", "", ""
footerFound := false
// Look through each line
scanner := bufio.NewScanner(strings.NewReader(txtBlock))
for scanner.Scan() {
line = scanner.Text()
if token, _ := findFooterToken(line, tokenSep); len(token) > 0 {
// if footer was already found from before
if len(footerBlock) > 0{
footers = append(footers, strings.TrimSpace(footerBlock))
}
footerFound = true
footerBlock = ""
}
//'\n' is removed when reading from scanner
if !footerFound {
body += line + "\n"
}else{
footerBlock += line + "\n"
}
}
if len(footerBlock) > 0 {
footers = append(footers, strings.TrimSpace(footerBlock))
}
body = strings.TrimSpace(body)
if len(body) > 0{
msgBlockMap["body"] = []shared.MessageBlock {{
Label: "",
Content: body,
} }
}
footerBlocks := getMessageBlocksFromTexts(footers, tokenSep)
if len(footerBlocks) > 0 {
msgBlockMap["footer"] = footerBlocks
}
return msgBlockMap
}

View File

@@ -10,7 +10,7 @@ import (
func TestAnalyzer(t *testing.T) { func TestAnalyzer(t *testing.T) {
_, err := analyzer.New("unknown", config.AnalyzerConfig{}, config.ChangelogConfig{}) _, err := analyzer.New("unknown", config.ChangelogConfig{})
assert.Error(t, err) assert.Error(t, err)
} }

View File

@@ -2,7 +2,8 @@
package analyzer package analyzer
import ( import (
"github.com/Nightapes/go-semantic-release/pkg/config" "fmt"
"regexp"
"strings" "strings"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@@ -14,16 +15,14 @@ type angular struct {
rules []Rule rules []Rule
regex string regex string
log *log.Entry log *log.Entry
config config.AnalyzerConfig
} }
// ANGULAR identifier // ANGULAR identifer
const ANGULAR = "angular" const ANGULAR = "angular"
var angularFooterTokenSep = defaultTokenSeparators
func newAngular() *angular { func newAngular() *angular {
return &angular{ return &angular{
regex: `^(?P<type>\w*)(?:\((?P<scope>.*)\))?: (?P<subject>.*)`, regex: `^(TAG)(?:\((.*)\))?: (.*)`,
log: log.WithField("analyzer", ANGULAR), log: log.WithField("analyzer", ANGULAR),
rules: []Rule{ rules: []Rule{
{ {
@@ -37,14 +36,12 @@ func newAngular() *angular {
TagString: "Bug fixes", TagString: "Bug fixes",
Release: "patch", Release: "patch",
Changelog: true, Changelog: true,
}, }, {
{
Tag: "perf", Tag: "perf",
TagString: "Performance improvements", TagString: "Performance improvments",
Release: "patch", Release: "patch",
Changelog: true, Changelog: true,
}, }, {
{
Tag: "docs", Tag: "docs",
TagString: "Documentation changes", TagString: "Documentation changes",
Release: "none", Release: "none",
@@ -55,26 +52,22 @@ func newAngular() *angular {
TagString: "Style", TagString: "Style",
Release: "none", Release: "none",
Changelog: false, Changelog: false,
}, }, {
{
Tag: "refactor", Tag: "refactor",
TagString: "Code refactor", TagString: "Code refactor",
Release: "none", Release: "none",
Changelog: false, Changelog: false,
}, }, {
{
Tag: "test", Tag: "test",
TagString: "Testing", TagString: "Testing",
Release: "none", Release: "none",
Changelog: false, Changelog: false,
}, }, {
{
Tag: "chore", Tag: "chore",
TagString: "Changes to the build process or auxiliary tools and libraries such as documentation generation", TagString: "Changes to the build process or auxiliary tools and libraries such as documentation generation",
Release: "none", Release: "none",
Changelog: false, Changelog: false,
}, }, {
{
Tag: "build", Tag: "build",
TagString: "Changes to CI/CD", TagString: "Changes to CI/CD",
Release: "none", Release: "none",
@@ -88,52 +81,38 @@ func (a *angular) getRules() []Rule {
return a.rules return a.rules
} }
func (a *angular) analyze(commit shared.Commit, rule Rule) *shared.AnalyzedCommit { func (a *angular) analyze(commit shared.Commit, rule Rule) (shared.AnalyzedCommit, bool, error) {
tokenSep := append(a.config.TokenSeparators, angularFooterTokenSep[:]...)
firstSplit := strings.SplitN(commit.Message, "\n", 2) analyzed := shared.AnalyzedCommit{
header := firstSplit[0]
body := ""
if len(firstSplit) > 1 {
body = firstSplit[1]
}
matches := getRegexMatchedMap(a.regex, header)
if len(matches) == 0 || matches["type"] != rule.Tag{
a.log.Tracef("%s does not match %s, skip", commit.Message, rule.Tag)
return nil
}
msgBlockMap := getDefaultMessageBlockMap(body, tokenSep)
analyzed := &shared.AnalyzedCommit{
Commit: commit, Commit: commit,
Tag: rule.Tag, Tag: rule.Tag,
TagString: rule.TagString, TagString: rule.TagString,
Scope: shared.Scope(matches["scope"]),
Subject: strings.TrimSpace(matches["subject"]),
MessageBlocks: msgBlockMap,
} }
isBreaking := strings.Contains(commit.Message, defaultBreakingChangePrefix) re := regexp.MustCompile(strings.Replace(a.regex, "TAG", rule.Tag, -1))
analyzed.IsBreaking = isBreaking matches := re.FindAllStringSubmatch(commit.Message, -1)
if len(matches) >= 1 {
if len(matches[0]) >= 3 {
oldFormatMessage := strings.TrimSpace(matches["subject"] + "\n" + body) analyzed.Scope = shared.Scope(matches[0][2])
if !isBreaking { message := strings.Join(matches[0][3:], "")
analyzed.ParsedMessage = strings.Trim(oldFormatMessage, " ") if !strings.Contains(message, "BREAKING CHANGE:") {
a.log.Tracef("%s: found %s", commit.Message, rule.Tag) analyzed.ParsedMessage = strings.Trim(message, " ")
return analyzed
a.log.Tracef("%s: found %s", commit.Message, rule.Tag)
return analyzed, false, nil
}
breakingChange := strings.SplitN(message, "BREAKING CHANGE:", 2)
analyzed.ParsedMessage = strings.Trim(breakingChange[0], " ")
analyzed.ParsedBreakingChangeMessage = strings.Trim(breakingChange[1], " ")
a.log.Tracef(" %s, BREAKING CHANGE found", commit.Message)
return analyzed, true, nil
}
} }
a.log.Tracef("%s does not match %s, skip", commit.Message, rule.Tag)
return analyzed, false, fmt.Errorf("not found")
a.log.Tracef(" %s, BREAKING CHANGE found", commit.Message)
breakingChange := strings.SplitN(oldFormatMessage, defaultBreakingChangePrefix, 2)
if len(breakingChange) > 1 {
analyzed.ParsedMessage = strings.TrimSpace(breakingChange[0])
analyzed.ParsedBreakingChangeMessage = strings.TrimSpace(breakingChange[1])
} else {
analyzed.ParsedBreakingChangeMessage = breakingChange[0]
}
return analyzed
} }

View File

@@ -10,7 +10,7 @@ import (
) )
func TestAngular(t *testing.T) { func TestAngular(t *testing.T) {
t.Parallel()
testConfigs := []struct { testConfigs := []struct {
testCase string testCase string
commits []shared.Commit commits []shared.Commit
@@ -19,8 +19,8 @@ func TestAngular(t *testing.T) {
{ {
testCase: "feat", testCase: "feat",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": { "minor": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
@@ -31,16 +31,14 @@ func TestAngular(t *testing.T) {
Tag: "feat", Tag: "feat",
TagString: "Features", TagString: "Features",
Print: true, Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
"major": {}, "major": []shared.AnalyzedCommit{},
"patch": {}, "patch": []shared.AnalyzedCommit{},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
commits: []shared.Commit{ commits: []shared.Commit{
{ shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
Hash: "12345667", Hash: "12345667",
@@ -50,8 +48,8 @@ func TestAngular(t *testing.T) {
{ {
testCase: "feat breaking change", testCase: "feat breaking change",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": { "minor": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
@@ -62,12 +60,10 @@ func TestAngular(t *testing.T) {
Tag: "feat", Tag: "feat",
TagString: "Features", TagString: "Features",
Print: true, Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
"major": { "major": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat(internal/changelog): my first break BREAKING CHANGE: change api to v2", Message: "feat(internal/changelog): my first break BREAKING CHANGE: change api to v2",
Author: "me", Author: "me",
@@ -79,102 +75,39 @@ func TestAngular(t *testing.T) {
TagString: "Features", TagString: "Features",
Print: true, Print: true,
ParsedBreakingChangeMessage: "change api to v2", ParsedBreakingChangeMessage: "change api to v2",
IsBreaking: true,
Subject: "my first break BREAKING CHANGE: change api to v2",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
"patch": {}, "patch": []shared.AnalyzedCommit{},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
commits: []shared.Commit{ commits: []shared.Commit{
{ shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
Hash: "12345667", Hash: "12345667",
}, },
{ shared.Commit{
Message: "feat(internal/changelog): my first break BREAKING CHANGE: change api to v2", Message: "feat(internal/changelog): my first break BREAKING CHANGE: change api to v2",
Author: "me", Author: "me",
Hash: "12345668", Hash: "12345668",
}, },
}, },
}, },
{
testCase: "feat breaking change footer",
commits: []shared.Commit{
{
Message: "feat(internal/changelog): my first commit",
Author: "me",
Hash: "12345667",
},
{
Message: "feat(internal/changelog): my first break \n\nBREAKING CHANGE: change api to v2\n",
Author: "me",
Hash: "12345668",
},
},
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {
{
Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "internal/changelog",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
"major": {
{
Commit: shared.Commit{
Message: "feat(internal/changelog): my first break \n\nBREAKING CHANGE: change api to v2\n",
Author: "me",
Hash: "12345668",
},
Scope: "internal/changelog",
ParsedMessage: "my first break",
Tag: "feat",
TagString: "Features",
Print: true,
ParsedBreakingChangeMessage: "change api to v2",
IsBreaking: true,
Subject: "my first break",
MessageBlocks: map[string][]shared.MessageBlock{
"footer": {
shared.MessageBlock{
Label: "BREAKING CHANGE",
Content: "change api to v2",
},
},
},
},
},
"patch": {},
"none": {},
},
},
{ {
testCase: "invalid", testCase: "invalid",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {}, "minor": []shared.AnalyzedCommit{},
"major": {}, "major": []shared.AnalyzedCommit{},
"patch": {}, "patch": []shared.AnalyzedCommit{},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
commits: []shared.Commit{ commits: []shared.Commit{
{ shared.Commit{
Message: "internal/changelog: my first commit", Message: "internal/changelog: my first commit",
Author: "me", Author: "me",
Hash: "12345667", Hash: "12345667",
}, },
{ shared.Commit{
Message: "Merge feat(internal/changelog): my first commit", Message: "Merge feat(internal/changelog): my first commit",
Author: "me", Author: "me",
Hash: "12345667", Hash: "12345667",
@@ -184,8 +117,8 @@ func TestAngular(t *testing.T) {
{ {
testCase: "feat and build", testCase: "feat and build",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": { "minor": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
@@ -196,12 +129,10 @@ func TestAngular(t *testing.T) {
Tag: "feat", Tag: "feat",
TagString: "Features", TagString: "Features",
Print: true, Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
"none": { "none": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "build(internal/changelog): my first build", Message: "build(internal/changelog): my first build",
Author: "me", Author: "me",
@@ -213,20 +144,18 @@ func TestAngular(t *testing.T) {
TagString: "Changes to CI/CD", TagString: "Changes to CI/CD",
Print: false, Print: false,
ParsedBreakingChangeMessage: "", ParsedBreakingChangeMessage: "",
Subject: "my first build",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
"patch": {}, "patch": []shared.AnalyzedCommit{},
"major": {}, "major": []shared.AnalyzedCommit{},
}, },
commits: []shared.Commit{ commits: []shared.Commit{
{ shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
Hash: "12345667", Hash: "12345667",
}, },
{ shared.Commit{
Message: "build(internal/changelog): my first build", Message: "build(internal/changelog): my first build",
Author: "me", Author: "me",
Hash: "12345668", Hash: "12345668",
@@ -235,7 +164,7 @@ func TestAngular(t *testing.T) {
}, },
} }
angular, err := analyzer.New("angular", config.AnalyzerConfig{}, config.ChangelogConfig{}) angular, err := analyzer.New("angular", config.ChangelogConfig{})
assert.NoError(t, err) assert.NoError(t, err)
for _, test := range testConfigs { for _, test := range testConfigs {
@@ -245,4 +174,5 @@ func TestAngular(t *testing.T) {
assert.Equalf(t, test.analyzedCommits["patch"], analyzedCommits["patch"], "Testcase %s should have patch commits", test.testCase) assert.Equalf(t, test.analyzedCommits["patch"], analyzedCommits["patch"], "Testcase %s should have patch commits", test.testCase)
assert.Equalf(t, test.analyzedCommits["none"], analyzedCommits["none"], "Testcase %s should have none commits", test.testCase) assert.Equalf(t, test.analyzedCommits["none"], analyzedCommits["none"], "Testcase %s should have none commits", test.testCase)
} }
} }

View File

@@ -1,143 +0,0 @@
// Package analyzer provides different commit analyzer
package analyzer
import (
"github.com/Nightapes/go-semantic-release/pkg/config"
"strings"
log "github.com/sirupsen/logrus"
"github.com/Nightapes/go-semantic-release/internal/shared"
)
type conventional struct {
rules []Rule
regex string
log *log.Entry
config config.AnalyzerConfig
}
// CONVENTIONAL identifier
const CONVENTIONAL = "conventional"
var conventionalFooterTokenSep = defaultTokenSeparators
func newConventional(config config.AnalyzerConfig) *conventional {
return &conventional{
config: config,
regex: `^(?P<type>\w*)(?:\((?P<scope>.*)\))?(?P<breaking>\!)?: (?P<subject>.*)`,
log: log.WithField("analyzer", CONVENTIONAL),
rules: []Rule{
{
Tag: "feat",
TagString: "Features",
Release: "minor",
Changelog: true,
},
{
Tag: "fix",
TagString: "Bug fixes",
Release: "patch",
Changelog: true,
},
{
Tag: "perf",
TagString: "Performance improvements",
Release: "patch",
Changelog: true,
},
{
Tag: "docs",
TagString: "Documentation changes",
Release: "none",
Changelog: false,
},
{
Tag: "style",
TagString: "Style",
Release: "none",
Changelog: false,
},
{
Tag: "refactor",
TagString: "Code refactor",
Release: "none",
Changelog: false,
},
{
Tag: "test",
TagString: "Testing",
Release: "none",
Changelog: false,
},
{
Tag: "chore",
TagString: "Changes to the build process or auxiliary tools and libraries such as documentation generation",
Release: "none",
Changelog: false,
},
{
Tag: "build",
TagString: "Changes to CI/CD",
Release: "none",
Changelog: false,
},
},
}
}
func (a *conventional) getRules() []Rule {
return a.rules
}
func (a *conventional) analyze(commit shared.Commit, rule Rule) *shared.AnalyzedCommit {
tokenSep := append(a.config.TokenSeparators, conventionalFooterTokenSep[:]...)
firstSplit := strings.SplitN(commit.Message, "\n", 2)
header := firstSplit[0]
body := ""
if len(firstSplit) > 1 {
body = firstSplit[1]
}
matches := getRegexMatchedMap(a.regex, header)
if len(matches) == 0 || matches["type"] != rule.Tag{
a.log.Tracef("%s does not match %s, skip", commit.Message, rule.Tag)
return nil
}
msgBlockMap := getDefaultMessageBlockMap(body, tokenSep)
analyzed := &shared.AnalyzedCommit{
Commit: commit,
Tag: rule.Tag,
TagString: rule.TagString,
Scope: shared.Scope(matches["scope"]),
Subject: strings.TrimSpace(matches["subject"]),
MessageBlocks: msgBlockMap,
}
isBreaking := matches["breaking"] == "!" || strings.Contains(commit.Message, defaultBreakingChangePrefix)
analyzed.IsBreaking = isBreaking
oldFormatMessage := strings.TrimSpace(matches["subject"] + "\n" + body)
if !isBreaking {
analyzed.ParsedMessage = strings.Trim(oldFormatMessage, " ")
a.log.Tracef("%s: found %s", commit.Message, rule.Tag)
return analyzed
}
a.log.Infof(" %s, BREAKING CHANGE found", commit.Message)
breakingChange := strings.SplitN(oldFormatMessage, defaultBreakingChangePrefix, 2)
if len(breakingChange) > 1 {
analyzed.ParsedMessage = strings.TrimSpace(breakingChange[0])
analyzed.ParsedBreakingChangeMessage = strings.TrimSpace(breakingChange[1])
} else {
analyzed.ParsedBreakingChangeMessage = breakingChange[0]
}
return analyzed
}

View File

@@ -1,496 +0,0 @@
package analyzer_test
import (
"testing"
"github.com/Nightapes/go-semantic-release/internal/analyzer"
"github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config"
"github.com/stretchr/testify/assert"
)
func TestConventional(t *testing.T) {
t.Parallel()
testConfigs := []struct {
testCase string
commits []shared.Commit
wantAnalyzedCommits map[shared.Release][]shared.AnalyzedCommit
}{
{
testCase: "feat",
wantAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {
{
Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "internal/changelog",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
Print: true,
},
{
Commit: shared.Commit{
Message: "feat: no scope",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "no scope",
Tag: "feat",
TagString: "Features",
Subject: "no scope",
MessageBlocks: map[string][]shared.MessageBlock{},
Print: true,
},
},
"major": {},
"patch": {},
"none": {},
},
commits: []shared.Commit{
{
Message: "feat(internal/changelog): my first commit",
Author: "me",
Hash: "12345667",
},
{
Message: "feat: no scope",
Author: "me",
Hash: "12345667",
},
},
},
{
testCase: "feat breaking change",
wantAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {
{
Commit: shared.Commit{
Message: "feat: my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
"major": {
{
Commit: shared.Commit{
Message: "feat!: my first break",
Author: "me",
Hash: "12345668",
},
Scope: "",
ParsedMessage: "",
Tag: "feat",
TagString: "Features",
Print: true,
ParsedBreakingChangeMessage: "my first break",
IsBreaking: true,
Subject: "my first break",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
"patch": {},
"none": {},
},
commits: []shared.Commit{
{
Message: "feat: my first commit",
Author: "me",
Hash: "12345667",
},
{
Message: "feat!: my first break",
Author: "me",
Hash: "12345668",
},
},
},
{
testCase: "feat breaking change footer",
wantAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {
{
Commit: shared.Commit{
Message: "feat: my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
"major": {
{
Commit: shared.Commit{
Message: "feat: my first break \n\nBREAKING CHANGE: change api to v2\n",
Author: "me",
Hash: "12345668",
},
Scope: "",
ParsedMessage: "my first break",
Tag: "feat",
TagString: "Features",
Print: true,
ParsedBreakingChangeMessage: "change api to v2",
IsBreaking: true,
Subject: "my first break",
MessageBlocks: map[string][]shared.MessageBlock{
"footer" : { shared.MessageBlock{
Label: "BREAKING CHANGE",
Content: "change api to v2",
},
},
},
},
{
Commit: shared.Commit{
Message: "feat!: my first break \n\nBREAKING CHANGE: hey from the change",
Author: "me",
Hash: "12345669",
},
Scope: "",
ParsedMessage: "my first break",
Tag: "feat",
TagString: "Features",
Print: true,
ParsedBreakingChangeMessage: "hey from the change",
IsBreaking: true,
Subject: "my first break",
MessageBlocks: map[string][]shared.MessageBlock{
"footer" : {shared.MessageBlock{
Label: "BREAKING CHANGE",
Content: "hey from the change",
},
},
},
},
},
"patch": {},
"none": {},
},
commits: []shared.Commit{
{
Message: "feat: my first commit",
Author: "me",
Hash: "12345667",
},
{
Message: "feat: my first break \n\nBREAKING CHANGE: change api to v2\n",
Author: "me",
Hash: "12345668",
},
{
Message: "feat!: my first break \n\nBREAKING CHANGE: hey from the change",
Author: "me",
Hash: "12345669",
},
},
},
{
testCase: "invalid",
wantAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {},
"major": {},
"patch": {},
"none": {},
},
commits: []shared.Commit{
{
Message: "internal/changelog: my first commit",
Author: "me",
Hash: "12345667",
},
{
Message: "Merge feat: my first commit",
Author: "me",
Hash: "12345667",
},
},
},
{
testCase: "feat and build",
wantAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {
{
Commit: shared.Commit{
Message: "feat: my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
"none": {
{
Commit: shared.Commit{
Message: "build: my first build",
Author: "me",
Hash: "12345668",
},
Scope: "",
ParsedMessage: "my first build",
Tag: "build",
TagString: "Changes to CI/CD",
Print: false,
ParsedBreakingChangeMessage: "",
Subject: "my first build",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
"patch": {},
"major": {},
},
commits: []shared.Commit{
{
Message: "feat: my first commit",
Author: "me",
Hash: "12345667",
},
{
Message: "build: my first build",
Author: "me",
Hash: "12345668",
},
},
},
{
testCase: "fix and build",
wantAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {},
"none": {
{
Commit: shared.Commit{
Message: "build: my first build",
Author: "me",
Hash: "12345668",
},
Scope: "",
ParsedMessage: "my first build",
Tag: "build",
TagString: "Changes to CI/CD",
Print: false,
ParsedBreakingChangeMessage: "",
Subject: "my first build",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
"patch": {{
Commit: shared.Commit{
Message: "fix: my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "my first commit",
Tag: "fix",
TagString: "Bug fixes",
Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
}},
"major": {},
},
commits: []shared.Commit{
{
Message: "fix: my first commit",
Author: "me",
Hash: "12345667",
},
{
Message: "build: my first build",
Author: "me",
Hash: "12345668",
},
},
},
}
conventional, err := analyzer.New("conventional", config.AnalyzerConfig{}, config.ChangelogConfig{})
assert.NoError(t, err)
for _, test := range testConfigs {
analyzedCommits := conventional.Analyze(test.commits)
assert.Equalf(t, test.wantAnalyzedCommits["major"], analyzedCommits["major"], "Testcase %s should have major commits", test.testCase)
assert.Equalf(t, test.wantAnalyzedCommits["minor"], analyzedCommits["minor"], "Testcase %s should have minor commits", test.testCase)
assert.Equalf(t, test.wantAnalyzedCommits["patch"], analyzedCommits["patch"], "Testcase %s should have patch commits", test.testCase)
assert.Equalf(t, test.wantAnalyzedCommits["none"], analyzedCommits["none"], "Testcase %s should have none commits", test.testCase)
}
}
func TestConventional_BodyAndFooters(t *testing.T) {
t.Parallel()
testConfigs := []struct {
testCase string
commits []shared.Commit
expectedAnalyzedCommits map[shared.Release][]shared.AnalyzedCommit
}{
{
testCase: "Only body, no footer",
commits: []shared.Commit{
{
Message: "fix: squash bug for logging\n\nNow the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout",
Author: "me",
Hash: "12345667",
},
},
expectedAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"patch": {
{
Commit: shared.Commit{
Message: "fix: squash bug for logging\n\nNow the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "squash bug for logging\n\nNow the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout",
Tag: "fix",
TagString: "Bug fixes",
Print: true,
Subject: "squash bug for logging",
MessageBlocks: map[string][]shared.MessageBlock{
"body": {
shared.MessageBlock{
Label: "",
Content: "Now the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout",
},
},
},
},
},
"major": {},
"minor": {},
"none": {},
},
},
{
testCase: "Only footers, no body",
commits: []shared.Commit{
{
Message: "fix: squash bug for logging\n\nNote: now the logs will not print lines twice.\n\nIssue: #123\nSeverity: medium",
Author: "me",
Hash: "12345667",
},
},
expectedAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"patch": {
{
Commit: shared.Commit{
Message: "fix: squash bug for logging\n\nNote: now the logs will not print lines twice.\n\nIssue: #123\nSeverity: medium",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "squash bug for logging\n\nNote: now the logs will not print lines twice.\n\nIssue: #123\nSeverity: medium",
Tag: "fix",
TagString: "Bug fixes",
Print: true,
Subject: "squash bug for logging",
MessageBlocks: map[string][]shared.MessageBlock{
"footer": {
shared.MessageBlock{
Label: "Note",
Content: "now the logs will not print lines twice.",
},
shared.MessageBlock{
Label: "Issue",
Content: "#123",
},
shared.MessageBlock{
Label: "Severity",
Content: "medium",
},
},
},
},
},
"major": {},
"minor": {},
"none": {},
},
},
{
testCase: "Body and footers",
commits: []shared.Commit{
{
Message: "fix: squash bug for logging\n\nNow the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout\n\nIssue: #123\nSeverity: medium",
Author: "me",
Hash: "12345667",
},
},
expectedAnalyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"patch": {
{
Commit: shared.Commit{
Message: "fix: squash bug for logging\n\nNow the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout\n\nIssue: #123\nSeverity: medium",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "squash bug for logging\n\nNow the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout\n\nIssue: #123\nSeverity: medium",
Tag: "fix",
TagString: "Bug fixes",
Print: true,
Subject: "squash bug for logging",
MessageBlocks: map[string][]shared.MessageBlock{
"body": {
shared.MessageBlock{
Label: "",
Content: "Now the logs will not print lines twice. The following changed:\n\n-Buffer -Stdout",
},
},
"footer": {
shared.MessageBlock{
Label: "Issue",
Content: "#123",
},
shared.MessageBlock{
Label: "Severity",
Content: "medium",
},
},
},
},
},
"major": {},
"minor": {},
"none": {},
},
},
}
conventional, err := analyzer.New("conventional", config.AnalyzerConfig{}, config.ChangelogConfig{})
assert.NoError(t, err)
for _, test := range testConfigs {
analyzedCommits := conventional.Analyze(test.commits)
assert.Equalf(t, test.expectedAnalyzedCommits["major"], analyzedCommits["major"], "Testcase %s should have major commits", test.testCase)
assert.Equalf(t, test.expectedAnalyzedCommits["minor"], analyzedCommits["minor"], "Testcase %s should have minor commits", test.testCase)
assert.Equalf(t, test.expectedAnalyzedCommits["patch"], analyzedCommits["patch"], "Testcase %s should have patch commits", test.testCase)
assert.Equalf(t, test.expectedAnalyzedCommits["none"], analyzedCommits["none"], "Testcase %s should have none commits", test.testCase)
}
}

View File

@@ -1,179 +0,0 @@
package assets
import (
"archive/zip"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"fmt"
"hash"
"hash/crc32"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"github.com/Nightapes/go-semantic-release/pkg/config"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
// Asset struct
type Asset struct {
name string
path string
zippedPath string
algorithm string
isCompressed bool
}
//NewAsset from a config
func NewAsset(repository string, assetConfig config.Asset, algorithm string) (*Asset, error) {
filePath := assetConfig.Path
if assetConfig.Name != "" && assetConfig.Path == "" {
filePath = assetConfig.Name
log.Warn("Name is deprecated. Please update your config. See https://nightapes.github.io/go-semantic-release/")
}
realPath := path.Join(repository, filePath)
file, err := os.Open(realPath)
if err != nil {
file.Close()
return nil, errors.Wrapf(err, "Could not open file %s", realPath)
}
defer file.Close()
name := assetConfig.Rename
if assetConfig.Rename == "" {
info, _ := file.Stat()
name = info.Name()
}
asset := &Asset{
path: realPath,
name: name,
isCompressed: assetConfig.Compress,
algorithm: algorithm,
}
return asset, nil
}
func (a *Asset) getChecksum() (string, error) {
path, err := a.GetPath()
if err != nil {
return "", nil
}
log.Debugf("Calculating checksum for %s", path)
file, err := os.Open(path)
if err != nil {
return "", errors.Wrapf(err, "Failed to open file %s to calculate checksum", a.name)
}
defer file.Close() // nolint: errcheck
var hash hash.Hash
switch a.algorithm {
case "crc32":
hash = crc32.NewIEEE()
case "md5":
hash = md5.New()
case "sha1":
hash = sha1.New()
case "sha224":
hash = sha256.New224()
case "sha384":
hash = sha512.New384()
case "sha256":
hash = sha256.New()
case "sha512":
hash = sha512.New()
default:
hash = sha256.New()
}
_, err = io.Copy(hash, file)
if err != nil {
return "", err
}
return hex.EncodeToString(hash.Sum(nil)), nil
}
// GetPath where the file is located, if zipped true, it will compress it and give you the new location
func (a *Asset) GetPath() (string, error) {
if a.isCompressed {
return a.ZipFile()
}
return a.path, nil
}
// GetName of asset
func (a *Asset) GetName() string {
if a.isCompressed {
return fmt.Sprintf("%s.zip", a.name)
}
return a.name
}
// IsCompressed return true if file was zipped
func (a *Asset) IsCompressed() bool {
return a.isCompressed
}
// ZipFile compress given file in zip format
func (a *Asset) ZipFile() (string, error) {
if a.zippedPath != "" {
return a.zippedPath, nil
}
path := a.path
fileToZip, err := os.Open(path)
if err != nil {
return "", errors.Wrapf(err, "Could not open file %s", path)
}
defer fileToZip.Close()
zipFile, err := ioutil.TempFile(os.TempDir(), "asset.*.zip")
if err != nil {
return "", errors.Wrap(err, "Could not generate tmp file")
}
log.Debugf("Created zipfile %s", zipFile.Name())
fileToZipInfo, err := fileToZip.Stat()
if err != nil {
return "", errors.Wrap(err, "Could not read file infos")
}
zipWriter := zip.NewWriter(zipFile)
fileToZipHeader, err := zip.FileInfoHeader(fileToZipInfo)
if err != nil {
return "", errors.Wrap(err, "Could not add file infos to zip handler")
}
fileToZipHeader.Name = fileToZipInfo.Name()
fileToZipWriter, err := zipWriter.CreateHeader(fileToZipHeader)
if err != nil {
return "", errors.Wrap(err, "Could not create zip header")
}
if _, err = io.Copy(fileToZipWriter, fileToZip); err != nil {
return "", errors.Wrap(err, "Could not zip file")
}
if err := zipWriter.Close(); err != nil {
return "", errors.Wrap(err, fmt.Sprintf("Could not close zipwriter for zip %s", a.path))
}
if err := zipFile.Close(); err != nil {
return "", errors.Wrap(err, "Could not close file")
}
a.zippedPath, err = filepath.Abs(zipFile.Name())
return a.zippedPath, err
}

View File

@@ -1,79 +0,0 @@
package assets
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/Nightapes/go-semantic-release/pkg/config"
"github.com/pkg/errors"
)
// Set struct
type Set struct {
assets []*Asset
repository string
algorithm string
}
//New container for assets
func New(repository, algorithm string) *Set {
return &Set{
assets: []*Asset{},
repository: repository,
algorithm: algorithm,
}
}
// Add assets to the list
func (s *Set) Add(assetConfigs ...config.Asset) error {
for _, assetConfig := range assetConfigs {
asset, err := NewAsset(s.repository, assetConfig, s.algorithm)
if err != nil {
return err
}
s.assets = append(s.assets, asset)
}
return nil
}
func (s *Set) All() []*Asset {
return s.assets
}
func (s *Set) GenerateChecksum() error {
checksumFile, err := ioutil.TempFile(os.TempDir(), "checksum.*.txt")
if err != nil {
return errors.Wrap(err, "Could not generate tmp file for checksum")
}
defer checksumFile.Close()
lines := []string{}
for _, asset := range s.assets {
checksum, err := asset.getChecksum()
if err != nil {
return err
}
lines = append(lines, fmt.Sprintf("%s %s", checksum, asset.GetName()))
}
w := bufio.NewWriter(checksumFile)
for _, line := range lines {
fmt.Fprintln(w, line)
}
filePath, err := filepath.Abs(checksumFile.Name())
if err != nil {
return err
}
s.assets = append(s.assets, &Asset{
path: filePath,
name: "checksum.txt",
isCompressed: false,
algorithm: "",
})
return w.Flush()
}

View File

@@ -56,8 +56,8 @@ func TestWriteAndReadCache(t *testing.T) {
}, },
Branch: "master", Branch: "master",
Commits: map[shared.Release][]shared.AnalyzedCommit{ Commits: map[shared.Release][]shared.AnalyzedCommit{
"major": { "major": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "Message", Message: "Message",
Author: "Author", Author: "Author",
@@ -69,8 +69,6 @@ func TestWriteAndReadCache(t *testing.T) {
Tag: "feat", Tag: "feat",
TagString: "Features", TagString: "Features",
Print: true, Print: true,
Subject: "add gitlab as release option",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
}, },

View File

@@ -83,12 +83,12 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "1.1.0-alpha.0", nextVersion: "1.1.0-alpha.0",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {}, "major": []shared.AnalyzedCommit{},
"minor": { "minor": []shared.AnalyzedCommit{
{}, shared.AnalyzedCommit{},
}, },
"patch": {}, "patch": []shared.AnalyzedCommit{},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },
@@ -98,12 +98,12 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "1.1.0-beta.0", nextVersion: "1.1.0-beta.0",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {}, "major": []shared.AnalyzedCommit{},
"minor": { "minor": []shared.AnalyzedCommit{
{}, shared.AnalyzedCommit{},
}, },
"patch": {}, "patch": []shared.AnalyzedCommit{},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },
@@ -113,10 +113,10 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "1.0.0", nextVersion: "1.0.0",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {}, "major": []shared.AnalyzedCommit{},
"minor": {}, "minor": []shared.AnalyzedCommit{},
"patch": {}, "patch": []shared.AnalyzedCommit{},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },
@@ -126,10 +126,10 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "1.0.0", nextVersion: "1.0.0",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {{}}, "major": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"minor": {}, "minor": []shared.AnalyzedCommit{},
"patch": {}, "patch": []shared.AnalyzedCommit{},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: true, isFirst: true,
}, },
@@ -139,10 +139,10 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "2.0.0-rc.0", nextVersion: "2.0.0-rc.0",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {{}}, "major": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"minor": {{}}, "minor": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"patch": {{}}, "patch": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },
@@ -152,10 +152,10 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0-rc.0"), lastVersion: createVersion("1.0.0-rc.0"),
nextVersion: "1.0.0-rc.1", nextVersion: "1.0.0-rc.1",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {}, "major": []shared.AnalyzedCommit{},
"minor": {{}}, "minor": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"patch": {{}}, "patch": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },
@@ -165,10 +165,10 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "2.0.0", nextVersion: "2.0.0",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {{}}, "major": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"minor": {{}}, "minor": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"patch": {{}}, "patch": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },
@@ -178,10 +178,10 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "1.1.0", nextVersion: "1.1.0",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {}, "major": []shared.AnalyzedCommit{},
"minor": {{}}, "minor": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"patch": {{}}, "patch": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },
@@ -191,10 +191,10 @@ func TestCalculator_CalculateNewVersion(t *testing.T) {
lastVersion: createVersion("1.0.0"), lastVersion: createVersion("1.0.0"),
nextVersion: "1.0.1", nextVersion: "1.0.1",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"major": {}, "major": []shared.AnalyzedCommit{},
"minor": {}, "minor": []shared.AnalyzedCommit{},
"patch": {{}}, "patch": []shared.AnalyzedCommit{shared.AnalyzedCommit{}},
"none": {}, "none": []shared.AnalyzedCommit{},
}, },
isFirst: false, isFirst: false,
}, },

View File

@@ -1,7 +1,6 @@
package changelog package changelog
import ( import (
"bufio"
"bytes" "bytes"
"io/ioutil" "io/ioutil"
"strings" "strings"
@@ -32,11 +31,9 @@ introduced by commit:
{{ end -}} {{ end -}}
{{ end -}} {{ end -}}
{{ end -}}` {{ end -}}`
const defaultCommitListSubTemplate = `{{ define "commitList" }}` + defaultCommitList + "{{ end }}" const defaultChangelogTitle string = `v{{.Version}} ({{.Now.Format "2006-01-02"}})`
const defaultChangelogTitle = `v{{.Version}} ({{.Now.Format "2006-01-02"}})` const defaultChangelog string = `# v{{$.Version}} ({{.Now.Format "2006-01-02"}})
const defaultChangelog = `# v{{$.Version}} ({{.Now.Format "2006-01-02"}}) {{ .Commits -}}
{{ template "commitList" .CommitsContent -}}
{{ if .HasDocker}} {{ if .HasDocker}}
## Docker image ## Docker image
@@ -50,43 +47,25 @@ or
{{$.Backtick}}docker run {{.DockerRepository}}:latest{{$.Backtick}} {{$.Backtick}}docker run {{.DockerRepository}}:latest{{$.Backtick}}
{{ end -}} {{ end -}}
{{ end -}}
{{ if .HasNPM}}
## NodeJS Package
New NodeJS package is released under [{{.NPMPackageName}}]({{.NPMRepository}})
### Usage
{{$.Backtick}}yarn add {{.NPMPackageName}}@{{.Version}}{{$.Backtick}}
or
{{$.Backtick}}npm install -save {{.NPMPackageName}}@{{.Version}}{{$.Backtick}}
{{ end -}} {{ end -}}
` `
type changelogContent struct { type changelogContent struct {
Commits string Commits string
CommitsContent commitsContent
Version string Version string
Now time.Time Now time.Time
Backtick string Backtick string
HasDocker bool HasDocker bool
HasDockerLatest bool HasDockerLatest bool
DockerRepository string DockerRepository string
HasNPM bool
IsYarn bool
NPMRepository string
NPMPackageName string
} }
type commitsContent struct { type commitsContent struct {
Commits map[string][]shared.AnalyzedCommit Commits map[string][]shared.AnalyzedCommit
BreakingChanges []shared.AnalyzedCommit BreakingChanges []shared.AnalyzedCommit
Order []string Order []string
Version string
Now time.Time
Backtick string Backtick string
HasURL bool HasURL bool
URL string URL string
@@ -110,11 +89,11 @@ func New(config *config.ReleaseConfig, rules []analyzer.Rule, releaseTime time.T
} }
} }
// GenerateChangelog from given commits // GenerateChanglog from given commits
func (c *Changelog) GenerateChangelog(templateConfig shared.ChangelogTemplateConfig, analyzedCommits map[shared.Release][]shared.AnalyzedCommit) (*shared.GeneratedChangelog, error) { func (c *Changelog) GenerateChanglog(templateConfig shared.ChangelogTemplateConfig, analyzedCommits map[shared.Release][]shared.AnalyzedCommit) (*shared.GeneratedChangelog, error) {
commitsPerScope := map[string][]shared.AnalyzedCommit{} commitsPerScope := map[string][]shared.AnalyzedCommit{}
var commitsBreakingChange []shared.AnalyzedCommit commitsBreakingChange := []shared.AnalyzedCommit{}
order := make([]string, 0) order := make([]string, 0)
for _, rule := range c.rules { for _, rule := range c.rules {
@@ -127,7 +106,7 @@ func (c *Changelog) GenerateChangelog(templateConfig shared.ChangelogTemplateCon
for _, commits := range analyzedCommits { for _, commits := range analyzedCommits {
for _, commit := range commits { for _, commit := range commits {
if commit.Print { if commit.Print {
if commit.IsBreaking { if commit.ParsedBreakingChangeMessage != "" {
commitsBreakingChange = append(commitsBreakingChange, commit) commitsBreakingChange = append(commitsBreakingChange, commit)
continue continue
} }
@@ -140,7 +119,9 @@ func (c *Changelog) GenerateChangelog(templateConfig shared.ChangelogTemplateCon
} }
commitsContent := commitsContent{ commitsContent := commitsContent{
Version: templateConfig.Version,
Commits: commitsPerScope, Commits: commitsPerScope,
Now: c.releaseTime,
BreakingChanges: commitsBreakingChange, BreakingChanges: commitsBreakingChange,
Backtick: "`", Backtick: "`",
Order: order, Order: order,
@@ -149,25 +130,20 @@ func (c *Changelog) GenerateChangelog(templateConfig shared.ChangelogTemplateCon
} }
changelogContent := changelogContent{ changelogContent := changelogContent{
CommitsContent: commitsContent,
Version: templateConfig.Version, Version: templateConfig.Version,
Now: c.releaseTime, Now: c.releaseTime,
Backtick: "`", Backtick: "`",
HasDocker: c.config.Changelog.Docker.Repository != "", HasDocker: c.config.Changelog.Docker.Repository != "",
HasDockerLatest: c.config.Changelog.Docker.Latest, HasDockerLatest: c.config.Changelog.Docker.Latest,
DockerRepository: c.config.Changelog.Docker.Repository, DockerRepository: c.config.Changelog.Docker.Repository,
HasNPM: c.config.Changelog.NPM.PackageName != "",
NPMPackageName: c.config.Changelog.NPM.PackageName,
NPMRepository: c.config.Changelog.NPM.Repository,
} }
template := defaultChangelog
chglogTemplate := defaultCommitListSubTemplate + defaultChangelog
if c.config.Changelog.TemplatePath != "" { if c.config.Changelog.TemplatePath != "" {
content, err := ioutil.ReadFile(c.config.Changelog.TemplatePath) content, err := ioutil.ReadFile(c.config.Changelog.TemplatePath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
chglogTemplate = string(content) template = string(content)
} }
templateTitle := defaultChangelogTitle templateTitle := defaultChangelogTitle
@@ -176,41 +152,30 @@ func (c *Changelog) GenerateChangelog(templateConfig shared.ChangelogTemplateCon
} }
log.Debugf("Render title") log.Debugf("Render title")
renderedTitle, err := generateTemplate(templateTitle, changelogContent, nil) renderedTitle, err := generateTemplate(templateTitle, changelogContent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
log.Debugf("Render commits") log.Debugf("Render commits")
renderedCommitList, err := generateTemplate(defaultCommitList, commitsContent, nil) renderedCommitList, err := generateTemplate(defaultCommitList, commitsContent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
log.Tracef("Commits %s", renderedCommitList) log.Tracef("Commits %s", renderedCommitList)
changelogContent.Commits = renderedCommitList
extraFuncMap := template.FuncMap{ changelogContent.Commits = renderedCommitList
"commitUrl": func() string { return templateConfig.CommitURL },
}
log.Debugf("Render changelog") log.Debugf("Render changelog")
renderedContent, err := generateTemplate(chglogTemplate, changelogContent, extraFuncMap) renderedContent, err := generateTemplate(template, changelogContent)
return &shared.GeneratedChangelog{Title: renderedTitle, Content: renderedContent}, err return &shared.GeneratedChangelog{Title: renderedTitle, Content: renderedContent}, err
} }
func generateTemplate(text string, values interface{}, extraFuncMap template.FuncMap) (string, error) { func generateTemplate(text string, values interface{}) (string, error) {
funcMap := template.FuncMap{ funcMap := template.FuncMap{
"replace": replace, "replace": replace,
"lower": lower,
"upper": upper,
"capitalize": capitalize,
"addPrefixToLines": addPrefixToLines,
}
for k, v := range extraFuncMap {
funcMap[k] = v
} }
var tpl bytes.Buffer var tpl bytes.Buffer
@@ -228,30 +193,3 @@ func generateTemplate(text string, values interface{}, extraFuncMap template.Fun
func replace(input, from, to string) string { func replace(input, from, to string) string {
return strings.Replace(input, from, to, -1) return strings.Replace(input, from, to, -1)
} }
func lower(input string) string {
return strings.ToLower(input)
}
func upper(input string) string {
return strings.ToUpper(input)
}
func capitalize(input string) string {
if len(input) > 0 {
return strings.ToUpper(string(input[0])) + input[1:]
}
return ""
}
// Adds a prefix to each line of the given text block
// this can be helpful in rendering correct indentation or bullets for multi-line texts
func addPrefixToLines(input, prefix string) string {
output := ""
scanner := bufio.NewScanner(strings.NewReader(input))
for scanner.Scan() {
output += prefix + scanner.Text() + "\n"
}
output = strings.TrimRight(output, "\n")
return output
}

View File

@@ -29,8 +29,8 @@ func TestChangelog(t *testing.T) {
{ {
testCase: "feat", testCase: "feat",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": { "minor": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
@@ -41,8 +41,6 @@ func TestChangelog(t *testing.T) {
Tag: "feat", Tag: "feat",
TagString: "Features", TagString: "Features",
Print: true, Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
}, },
@@ -55,8 +53,8 @@ func TestChangelog(t *testing.T) {
{ {
testCase: "feat no scope", testCase: "feat no scope",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": { "minor": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat: my first commit", Message: "feat: my first commit",
Author: "me", Author: "me",
@@ -66,8 +64,6 @@ func TestChangelog(t *testing.T) {
Tag: "feat", Tag: "feat",
TagString: "Features", TagString: "Features",
Print: true, Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
}, },
}, },
@@ -80,8 +76,8 @@ func TestChangelog(t *testing.T) {
{ {
testCase: "feat breaking change", testCase: "feat breaking change",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{ analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": { "minor": []shared.AnalyzedCommit{
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit", Message: "feat(internal/changelog): my first commit",
Author: "me", Author: "me",
@@ -92,10 +88,8 @@ func TestChangelog(t *testing.T) {
Tag: "feat", Tag: "feat",
TagString: "Features", TagString: "Features",
Print: true, Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
}, },
{ shared.AnalyzedCommit{
Commit: shared.Commit{ Commit: shared.Commit{
Message: "feat(internal/changelog): my first break: BREAKING CHANGE: change api to v2", Message: "feat(internal/changelog): my first break: BREAKING CHANGE: change api to v2",
Author: "me", Author: "me",
@@ -107,15 +101,6 @@ func TestChangelog(t *testing.T) {
TagString: "Features", TagString: "Features",
Print: true, Print: true,
ParsedBreakingChangeMessage: "change api to v2", ParsedBreakingChangeMessage: "change api to v2",
IsBreaking: true,
Subject: "my first break",
MessageBlocks: map[string][]shared.MessageBlock{
"body": {shared.MessageBlock{
Label: "BREAKING CHANGE",
Content: "change api to v2",
},
},
},
}, },
}, },
}, },
@@ -125,105 +110,6 @@ func TestChangelog(t *testing.T) {
}, },
hasError: false, hasError: false,
}, },
{
testCase: "conventional commits",
analyzedCommits: map[shared.Release][]shared.AnalyzedCommit{
"minor": {
{
Commit: shared.Commit{
Message: "feat!: my first break \n\nBREAKING CHANGE: hey from the change",
Author: "me",
Hash: "12345669",
},
Scope: "",
ParsedMessage: "my first break",
Tag: "feat",
TagString: "Features",
Print: true,
ParsedBreakingChangeMessage: "hey from the change",
IsBreaking: true,
Subject: "my first break",
MessageBlocks: map[string][]shared.MessageBlock{
"body": {shared.MessageBlock{
Label: "BREAKING CHANGE",
Content: "hey from the change",
},
},
},
},
{
Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "internal/changelog",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
{
Commit: shared.Commit{
Message: "feat: my second commit",
Author: "me",
Hash: "12345667",
},
Scope: "",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Print: true,
Subject: "my second commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
{
Commit: shared.Commit{
Message: "feat: my new commit \n\nBREAKING CHANGE: change api to v2",
Author: "me",
Hash: "12345668",
},
Scope: "",
ParsedMessage: "my first break",
Tag: "feat",
TagString: "Features",
Print: true,
ParsedBreakingChangeMessage: "change api to v2",
IsBreaking: true,
Subject: "my new commit",
MessageBlocks: map[string][]shared.MessageBlock{
"body": {shared.MessageBlock{
Label: "BREAKING CHANGE",
Content: "change api to v2",
}},
},
},
{
Commit: shared.Commit{
Message: "feat!: my next commit",
Author: "me",
Hash: "12345668",
},
Scope: "",
ParsedMessage: "",
Tag: "feat",
TagString: "Features",
Print: true,
ParsedBreakingChangeMessage: "my next commit",
IsBreaking: true,
Subject: "my next commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
},
result: &shared.GeneratedChangelog{
Title: "v1.0.0 (2019-07-19)",
Content: "# v1.0.0 (2019-07-19)\n## BREAKING CHANGES\n* hey from the change \nintroduced by commit: \nmy first break ([1234566](https://commit.url))\n* change api to v2 \nintroduced by commit: \nmy first break ([1234566](https://commit.url))\n* my next commit \nintroduced by commit: \n ([1234566](https://commit.url))\n### Features\n* **`internal/changelog`** my first commit ([1234566](https://commit.url))\n* my first commit ([1234566](https://commit.url))\n",
},
hasError: false,
},
} }
cl := changelog.New(&config.ReleaseConfig{}, []analyzer.Rule{ cl := changelog.New(&config.ReleaseConfig{}, []analyzer.Rule{
@@ -249,100 +135,10 @@ func TestChangelog(t *testing.T) {
for _, config := range testConfigs { for _, config := range testConfigs {
t.Run(config.testCase, func(t *testing.T) { t.Run(config.testCase, func(t *testing.T) {
generatedChangelog, err := cl.GenerateChangelog(templateConfig, config.analyzedCommits) generatedChangelog, err := cl.GenerateChanglog(templateConfig, config.analyzedCommits)
assert.Equalf(t, config.hasError, err != nil, "Testcase %s should have error: %t -> %s", config.testCase, config.hasError, err) assert.Equalf(t, config.hasError, err != nil, "Testcase %s should have error: %t -> %s", config.testCase, config.hasError, err)
assert.Equalf(t, config.result, generatedChangelog, "Testcase %s should have generated changelog", config.testCase) assert.Equalf(t, config.result, generatedChangelog, "Testcase %s should have generated changelog", config.testCase)
}) })
} }
} }
func TestChangelogExtensions(t *testing.T) {
testConfigs := []struct {
testCase string
result *shared.GeneratedChangelog
releaseConfig *config.ReleaseConfig
}{
{
testCase: "docker",
releaseConfig: &config.ReleaseConfig{
Changelog: config.ChangelogConfig{
Docker: config.ChangelogDocker{
Latest: true,
Repository: "mydocker.de",
},
NPM: config.ChangelogNPM{},
},
},
result: &shared.GeneratedChangelog{Title: "v1.0.0 (2019-07-19)", Content: "# v1.0.0 (2019-07-19)\n### Features\n* **`internal/changelog`** my first commit ([1234566](https://commit.url))\n\n## Docker image\n\nNew docker image is released under `mydocker.de:1.0.0`\n\n### Usage\n\n`docker run mydocker.de:1.0.0`\n\nor\n\n`docker run mydocker.de:latest`\n"},
},
{
testCase: "npm",
releaseConfig: &config.ReleaseConfig{
Changelog: config.ChangelogConfig{
Docker: config.ChangelogDocker{},
NPM: config.ChangelogNPM{
Repository: "https://github.com/Nightapes/ngx-validators/packages/102720",
PackageName: "ngx-validators",
},
},
},
result: &shared.GeneratedChangelog{Title: "v1.0.0 (2019-07-19)", Content: "# v1.0.0 (2019-07-19)\n### Features\n* **`internal/changelog`** my first commit ([1234566](https://commit.url))\n\n## NodeJS Package\n\nNew NodeJS package is released under [ngx-validators](https://github.com/Nightapes/ngx-validators/packages/102720)\n\n### Usage\n\n`yarn add ngx-validators@1.0.0`\n\nor\n\n`npm install -save ngx-validators@1.0.0`\n\n"},
},
}
analyzedCommits := map[shared.Release][]shared.AnalyzedCommit{
"minor": {
{
Commit: shared.Commit{
Message: "feat(internal/changelog): my first commit",
Author: "me",
Hash: "12345667",
},
Scope: "internal/changelog",
ParsedMessage: "my first commit",
Tag: "feat",
TagString: "Features",
Print: true,
Subject: "my first commit",
MessageBlocks: map[string][]shared.MessageBlock{},
},
},
}
for _, config := range testConfigs {
t.Run(config.testCase, func(t *testing.T) {
templateConfig := shared.ChangelogTemplateConfig{
CommitURL: "https://commit.url",
CompareURL: "https://compare.url",
Hash: "hash",
Version: "1.0.0",
}
cl := changelog.New(config.releaseConfig, []analyzer.Rule{
{
Tag: "feat",
TagString: "Features",
Release: "minor",
Changelog: true,
},
{
Tag: "fix",
TagString: "Bug fixes",
Release: "patch",
Changelog: true,
},
{
Tag: "build",
TagString: "Build",
Release: "none",
Changelog: false,
},
}, time.Date(2019, 7, 19, 0, 0, 0, 0, time.UTC))
generatedChangelog, err := cl.GenerateChangelog(templateConfig, analyzedCommits)
assert.NoError(t, err)
assert.Equalf(t, config.result, generatedChangelog, "Testcase %s should have generated changelog", config.testCase)
})
}
}

View File

@@ -6,11 +6,11 @@ import (
"github.com/Nightapes/go-semantic-release/internal/ci" "github.com/Nightapes/go-semantic-release/internal/ci"
"github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/internal/gitutil"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"gopkg.in/src-d/go-billy.v4/memfs"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing/object"
"gopkg.in/src-d/go-git.v4/storage/memory"
) )
func TestCi(t *testing.T) { func TestCi(t *testing.T) {

View File

@@ -3,16 +3,17 @@ package gitutil
import ( import (
"fmt" "fmt"
"github.com/pkg/errors"
"sort" "sort"
"github.com/pkg/errors"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/storer"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/object"
"gopkg.in/src-d/go-git.v4/plumbing/storer"
) )
// GitUtil struct // GitUtil struct
@@ -134,38 +135,30 @@ func (g *GitUtil) GetCommits(lastTagHash string) ([]shared.Commit, error) {
return nil, err return nil, err
} }
commits := make(map[string]shared.Commit) var commits []shared.Commit
var foundEnd bool var foundEnd bool
err = cIter.ForEach(func(c *object.Commit) error { err = cIter.ForEach(func(c *object.Commit) error {
if c.Hash.String() == lastTagHash { if c.Hash.String() == lastTagHash {
log.Debugf("Found commit with hash %s, will stop here", c.Hash.String()) log.Debugf("Found commit with hash %s, will stop here", c.Hash.String())
foundEnd = true foundEnd = true
return storer.ErrStop return storer.ErrStop
} }
if !foundEnd { if !foundEnd {
log.Tracef("Found commit with hash %s", c.Hash.String()) log.Tracef("Found commit with hash %s", c.Hash.String())
commits[c.Hash.String()] = shared.Commit{ commit := shared.Commit{
Message: c.Message, Message: c.Message,
Author: c.Committer.Name, Author: c.Committer.Name,
Hash: c.Hash.String(), Hash: c.Hash.String(),
} }
commits = append(commits, commit)
} }
return nil return nil
}) })
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Could not read commits, check git clone depth in your ci") return commits, errors.Wrap(err, "Could not read commits, check git clone depth in your ci")
} }
l := make([]shared.Commit, 0) return commits, nil
for _, value := range commits {
l = append(l, value)
}
return l, nil
} }

View File

@@ -2,16 +2,13 @@ package hooks
import ( import (
"bufio" "bufio"
"io"
"os"
"os/exec" "os/exec"
"runtime" "runtime"
"strings" "strings"
log "github.com/sirupsen/logrus"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
log "github.com/sirupsen/logrus"
) )
//Hooks struct //Hooks struct
@@ -64,28 +61,17 @@ func (h *Hooks) runCommand(command string) error {
cmd = exec.Command("sh", "-c", cmdReplaced) cmd = exec.Command("sh", "-c", cmdReplaced)
} }
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "RELEASE_VERSION="+h.version.Next.Version.String())
cmdReader, err := cmd.StdoutPipe() cmdReader, err := cmd.StdoutPipe()
if err != nil { if err != nil {
return err return err
} }
h.printOutput(cmdReader, strings.Fields(cmdReplaced)[0])
cmdErrReader, err := cmd.StderrPipe() scanner := bufio.NewScanner(cmdReader)
if err != nil { go func() {
return err for scanner.Scan() {
} log.WithField("cmd", strings.Fields(cmdReplaced)[0]).Infof("%s\n", scanner.Text())
h.printOutput(cmdErrReader, strings.Fields(cmdReplaced)[0]) }
}()
return cmd.Run() return cmd.Run()
} }
func (h *Hooks) printOutput(read io.ReadCloser, cmd string) {
scanner := bufio.NewScanner(read)
go func() {
for scanner.Scan() {
log.WithField("cmd", cmd).Infof("%s\n", scanner.Text())
}
}()
}

View File

@@ -1,26 +0,0 @@
package integrations
import (
"github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config"
)
// Integrations struct
type Integrations struct {
version *shared.ReleaseVersion
config *config.Integrations
}
func New(config *config.Integrations, version *shared.ReleaseVersion) *Integrations {
return &Integrations{
config: config,
version: version,
}
}
func (i Integrations) Run() error {
if i.config.NPM.Enabled {
return i.updateNPM()
}
return nil
}

View File

@@ -1,28 +0,0 @@
package integrations
import (
log "github.com/sirupsen/logrus"
"github.com/tidwall/sjson"
"io/ioutil"
)
func (i *Integrations) updateNPM() error {
npmConfig := i.config.NPM
if npmConfig.Path == "" {
npmConfig.Path = "./package.json"
}
log.Debugf("Set version %s to %s", i.version.Next.Version, npmConfig.Path)
data, err := ioutil.ReadFile(npmConfig.Path)
if err != nil {
return err
}
newData, err := sjson.Set(string(data), "version", i.version.Next.Version)
if err != nil {
return err
}
return ioutil.WriteFile(npmConfig.Path, []byte(newData), 0777)
}

View File

@@ -1,62 +0,0 @@
package integrations
import (
"github.com/Masterminds/semver"
"github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config"
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"testing"
)
func TestIntegrations_updateNPM(t *testing.T) {
file, err := ioutil.TempFile("", "package")
if err != nil {
t.Fatal(err)
}
defer os.Remove(file.Name())
err = ioutil.WriteFile(file.Name(), []byte(`{
"name": "test",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"nx": "nx"
}
}`), 0777)
if err != nil {
t.Fatal(err)
}
testVersion, err := semver.NewVersion("1.2.0")
if err != nil {
t.Fatal(err)
}
i := New(&config.Integrations{NPM: config.IntegrationNPM{
Enabled: true,
Path: file.Name(),
}}, &shared.ReleaseVersion{
Next: shared.ReleaseVersionEntry{
Version: testVersion,
},
})
assert.NoError(t, i.updateNPM())
updatedFile, err := ioutil.ReadFile(file.Name())
if err != nil {
t.Fatal(err)
}
assert.Equal(t, `{
"name": "test",
"version": "1.2.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"nx": "nx"
}
}`, string(updatedFile))
}

View File

@@ -4,14 +4,13 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/Nightapes/go-semantic-release/internal/assets"
"github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/internal/gitutil"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
"github.com/go-git/go-git/v5" "gopkg.in/src-d/go-git.v4"
gitConfig "github.com/go-git/go-git/v5/config" gitConfig "gopkg.in/src-d/go-git.v4/config"
"github.com/go-git/go-git/v5/plumbing/object" "gopkg.in/src-d/go-git.v4/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport/http" "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@@ -65,14 +64,9 @@ func (g *Client) GetCompareURL(oldVersion, newVersion string) string {
} }
// CreateRelease creates release on remote // CreateRelease creates release on remote
func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog, _ *assets.Set) error { func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error {
tagPrefix := config.DefaultTagPrefix
if g.config.TagPrefix != nil{
tagPrefix = *g.config.TagPrefix
}
tag := tagPrefix + releaseVersion.Next.Version.String()
tag := "v" + releaseVersion.Next.Version.String()
g.log.Infof("create release with version %s", tag) g.log.Infof("create release with version %s", tag)
head, err := g.git.Repository.Head() head, err := g.git.Repository.Head()

View File

@@ -7,7 +7,6 @@ import (
"os" "os"
"strings" "strings"
"github.com/Nightapes/go-semantic-release/internal/assets"
"github.com/Nightapes/go-semantic-release/internal/releaser/util" "github.com/Nightapes/go-semantic-release/internal/releaser/util"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
@@ -79,22 +78,9 @@ func (g *Client) GetCompareURL(oldVersion, newVersion string) string {
} }
// CreateRelease creates release on remote // CreateRelease creates release on remote
func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog, assets *assets.Set) error { func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error {
err := g.makeRelease(releaseVersion, generatedChangelog)
if err != nil {
return err
}
return g.uploadAssets(assets)
}
// CreateRelease creates release on remote tag := "v" + releaseVersion.Next.Version.String()
func (g *Client) makeRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error {
tagPrefix := config.DefaultTagPrefix
if g.config.TagPrefix != nil{
tagPrefix = *g.config.TagPrefix
}
tag := tagPrefix + releaseVersion.Next.Version.String()
g.log.Debugf("create release with version %s", tag) g.log.Debugf("create release with version %s", tag)
prerelease := releaseVersion.Next.Version.Prerelease() != "" prerelease := releaseVersion.Next.Version.Prerelease() != ""
@@ -114,32 +100,34 @@ func (g *Client) makeRelease(releaseVersion *shared.ReleaseVersion, generatedCha
return fmt.Errorf("could not create release: %s", err.Error()) return fmt.Errorf("could not create release: %s", err.Error())
} }
g.release = release g.release = release
g.log.Debugf("Release response: %+v", *release) g.log.Debugf("Release repsone: %+v", *release)
g.log.Infof("Created release") g.log.Infof("Crated release")
return nil return nil
} }
// UploadAssets uploads specified assets // UploadAssets uploads specified assets
func (g *Client) uploadAssets(assets *assets.Set) error { func (g *Client) UploadAssets(repoDir string, assets []config.Asset) error {
if g.release != nil { if g.release != nil {
for _, asset := range assets.All() { filesToUpload, err := util.PrepareAssets(repoDir, assets)
path, err := asset.GetPath() if err != nil {
if err != nil { return err
return err }
} for _, f := range filesToUpload {
file, err := os.Open(path)
if err != nil {
return err
}
_, resp, err := g.client.Repositories.UploadReleaseAsset(g.context, g.config.User, g.config.Repo, g.release.GetID(), &github.UploadOptions{Name: asset.GetName()}, file) file, err := os.Open(*f)
if err != nil {
return err
}
fileInfo, _ := file.Stat()
_, resp, err := g.client.Repositories.UploadReleaseAsset(g.context, g.config.User, g.config.Repo, g.release.GetID(), &github.UploadOptions{Name: fileInfo.Name()}, file)
if err != nil { if err != nil {
return err return err
} }
if resp.StatusCode >= http.StatusBadRequest { if resp.StatusCode >= http.StatusBadRequest {
return fmt.Errorf("could not upload asset %s: %s", asset.GetName(), resp.Status) return fmt.Errorf("could not upload asset %s: %s", file.Name(), resp.Status)
} }
} }
} }

View File

@@ -1,4 +1,4 @@
package github package github_test
import ( import (
"fmt" "fmt"
@@ -11,6 +11,7 @@ import (
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/Nightapes/go-semantic-release/internal/releaser/github"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@@ -31,14 +32,14 @@ type testReleaseStruct struct {
} }
var testNewClient = []testHelperMethodStruct{ var testNewClient = []testHelperMethodStruct{
{config: config.GitHubProvider{ testHelperMethodStruct{config: config.GitHubProvider{
Repo: "foo", Repo: "foo",
User: "bar", User: "bar",
}, },
valid: true, valid: true,
}, },
{config: config.GitHubProvider{ testHelperMethodStruct{config: config.GitHubProvider{
Repo: "foo", Repo: "foo",
User: "bar", User: "bar",
CustomURL: "https://test.com", CustomURL: "https://test.com",
@@ -51,7 +52,7 @@ var lastVersion, _ = semver.NewVersion("1.0.0")
var newVersion, _ = semver.NewVersion("2.0.0") var newVersion, _ = semver.NewVersion("2.0.0")
var testReleases = []testReleaseStruct{ var testReleases = []testReleaseStruct{
{ testReleaseStruct{
config: config.GitHubProvider{ config: config.GitHubProvider{
Repo: "foo", Repo: "foo",
User: "bar", User: "bar",
@@ -75,7 +76,7 @@ var testReleases = []testReleaseStruct{
requestResponseCode: 200, requestResponseCode: 200,
valid: true, valid: true,
}, },
{ testReleaseStruct{
config: config.GitHubProvider{ config: config.GitHubProvider{
Repo: "foo", Repo: "foo",
User: "bar", User: "bar",
@@ -122,7 +123,7 @@ func TestNew(t *testing.T) {
os.Setenv("GITHUB_TOKEN", "XXX") os.Setenv("GITHUB_TOKEN", "XXX")
} }
_, err := New(&testOject.config, true) _, err := github.New(&testOject.config, true)
assert.Equal(t, testOject.valid, err == nil) assert.Equal(t, testOject.valid, err == nil)
os.Unsetenv("GITHUB_TOKEN") os.Unsetenv("GITHUB_TOKEN")
@@ -133,7 +134,7 @@ func TestNew(t *testing.T) {
func TestGetCommitURL(t *testing.T) { func TestGetCommitURL(t *testing.T) {
os.Setenv("GITHUB_TOKEN", "XX") os.Setenv("GITHUB_TOKEN", "XX")
for _, testOject := range testNewClient { for _, testOject := range testNewClient {
client, _ := New(&testOject.config, false) client, _ := github.New(&testOject.config, false)
actualURL := client.GetCommitURL() actualURL := client.GetCommitURL()
if testOject.config.CustomURL != "" { if testOject.config.CustomURL != "" {
expectedURL := fmt.Sprintf("%s/%s/%s/commit/{{hash}}", testOject.config.CustomURL, testOject.config.User, testOject.config.Repo) expectedURL := fmt.Sprintf("%s/%s/%s/commit/{{hash}}", testOject.config.CustomURL, testOject.config.User, testOject.config.Repo)
@@ -151,7 +152,7 @@ func TestGetCommitURL(t *testing.T) {
func TestGetCompareURL(t *testing.T) { func TestGetCompareURL(t *testing.T) {
os.Setenv("GITHUB_TOKEN", "XX") os.Setenv("GITHUB_TOKEN", "XX")
for _, testOject := range testNewClient { for _, testOject := range testNewClient {
client, _ := New(&testOject.config, false) client, _ := github.New(&testOject.config, false)
actualURL := client.GetCompareURL("1", "2") actualURL := client.GetCompareURL("1", "2")
if testOject.config.CustomURL != "" { if testOject.config.CustomURL != "" {
expectedURL := fmt.Sprintf("%s/%s/%s/compare/%s...%s", testOject.config.CustomURL, testOject.config.User, testOject.config.Repo, "1", "2") expectedURL := fmt.Sprintf("%s/%s/%s/compare/%s...%s", testOject.config.CustomURL, testOject.config.User, testOject.config.Repo, "1", "2")
@@ -173,9 +174,9 @@ func TestCreateRelease(t *testing.T) {
if testObejct.valid { if testObejct.valid {
server := initHTTPServer(testObejct.requestResponseCode, testObejct.requestResponseBody) server := initHTTPServer(testObejct.requestResponseCode, testObejct.requestResponseBody)
testObejct.config.CustomURL = server.URL testObejct.config.CustomURL = server.URL
client, _ := New(&testObejct.config, false) client, _ := github.New(&testObejct.config, false)
err := client.makeRelease(testObejct.releaseVersion, testObejct.generatedChangelog) err := client.CreateRelease(testObejct.releaseVersion, testObejct.generatedChangelog)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@@ -185,9 +186,9 @@ func TestCreateRelease(t *testing.T) {
} else { } else {
testObejct.config.CustomURL = "http://foo" testObejct.config.CustomURL = "http://foo"
client, _ := New(&testObejct.config, false) client, _ := github.New(&testObejct.config, false)
err := client.makeRelease(testObejct.releaseVersion, testObejct.generatedChangelog) err := client.CreateRelease(testObejct.releaseVersion, testObejct.generatedChangelog)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }

View File

@@ -12,7 +12,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/Nightapes/go-semantic-release/internal/assets"
"github.com/Nightapes/go-semantic-release/internal/releaser/util" "github.com/Nightapes/go-semantic-release/internal/releaser/util"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
@@ -87,22 +86,9 @@ func (g *Client) GetCompareURL(oldVersion, newVersion string) string {
} }
// CreateRelease creates release on remote // CreateRelease creates release on remote
func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog, assets *assets.Set) error { func (g *Client) CreateRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error {
err := g.makeRelease(releaseVersion, generatedChangelog)
if err != nil {
return err
}
return g.uploadAssets(assets)
}
// CreateRelease creates release on remote tag := "v" + releaseVersion.Next.Version.String()
func (g *Client) makeRelease(releaseVersion *shared.ReleaseVersion, generatedChangelog *shared.GeneratedChangelog) error {
tagPrefix := config.DefaultTagPrefix
if g.config.TagPrefix != nil{
tagPrefix = *g.config.TagPrefix
}
tag := tagPrefix + releaseVersion.Next.Version.String()
g.Release = tag g.Release = tag
g.log.Infof("create release with version %s", tag) g.log.Infof("create release with version %s", tag)
url := fmt.Sprintf("%s/projects/%s/releases", g.apiURL, util.PathEscape(g.config.Repo)) url := fmt.Sprintf("%s/projects/%s/releases", g.apiURL, util.PathEscape(g.config.Repo))
@@ -140,19 +126,23 @@ func (g *Client) makeRelease(releaseVersion *shared.ReleaseVersion, generatedCha
return nil return nil
} }
func (g *Client) uploadAssets(assets *assets.Set) error { // UploadAssets uploads specified assets
for _, asset := range assets.All() { func (g *Client) UploadAssets(repoDir string, assets []config.Asset) error {
path, err := asset.GetPath() filesToUpload, err := util.PrepareAssets(repoDir, assets)
if err != nil { if err != nil {
return err return err
} }
file, err := os.Open(path) for _, f := range filesToUpload {
file, err := os.Open(*f)
if err != nil { if err != nil {
return err return err
} }
defer file.Close() defer file.Close()
result, err := g.uploadFile(asset.GetName(), file) fileInfo, _ := file.Stat()
result, err := g.uploadFile(fileInfo.Name(), file)
if err != nil { if err != nil {
return fmt.Errorf("could not upload asset %s: %s", file.Name(), err.Error()) return fmt.Errorf("could not upload asset %s: %s", file.Name(), err.Error())
} }
@@ -161,9 +151,9 @@ func (g *Client) uploadAssets(assets *assets.Set) error {
g.log.Infof("Uploaded file %s to gitlab can be downloaded under %s", file.Name(), downloadURL) g.log.Infof("Uploaded file %s to gitlab can be downloaded under %s", file.Name(), downloadURL)
uploadURL := fmt.Sprintf("%s/projects/%s/releases/%s/assets/links?name=%s&url=%s", g.apiURL, util.PathEscape(g.config.Repo), g.Release, util.PathEscape(asset.GetName()), downloadURL) path := fmt.Sprintf("%s/projects/%s/releases/%s/assets/links?name=%s&url=%s", g.apiURL, util.PathEscape(g.config.Repo), g.Release, util.PathEscape(fileInfo.Name()), downloadURL)
req, err := http.NewRequest("POST", uploadURL, nil) req, err := http.NewRequest("POST", path, nil)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -1,4 +1,4 @@
package gitlab package gitlab_test
import ( import (
"io/ioutil" "io/ioutil"
@@ -13,7 +13,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/Nightapes/go-semantic-release/internal/assets" "github.com/Nightapes/go-semantic-release/internal/releaser/gitlab"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
) )
@@ -21,7 +21,7 @@ import (
func TestGetCommitURL(t *testing.T) { func TestGetCommitURL(t *testing.T) {
os.Setenv("GITLAB_ACCESS_TOKEN", "XXX") os.Setenv("GITLAB_ACCESS_TOKEN", "XXX")
defer os.Unsetenv("GITLAB_ACCESS_TOKEN") defer os.Unsetenv("GITLAB_ACCESS_TOKEN")
client, err := New(&config.GitLabProvider{ client, err := gitlab.New(&config.GitLabProvider{
CustomURL: "https://localhost/", CustomURL: "https://localhost/",
Repo: "test/test", Repo: "test/test",
}, true) }, true)
@@ -32,7 +32,7 @@ func TestGetCommitURL(t *testing.T) {
func TestGetCompareURL(t *testing.T) { func TestGetCompareURL(t *testing.T) {
os.Setenv("GITLAB_ACCESS_TOKEN", "XXX") os.Setenv("GITLAB_ACCESS_TOKEN", "XXX")
defer os.Unsetenv("GITLAB_ACCESS_TOKEN") defer os.Unsetenv("GITLAB_ACCESS_TOKEN")
client, err := New(&config.GitLabProvider{ client, err := gitlab.New(&config.GitLabProvider{
CustomURL: "https://localhost/", CustomURL: "https://localhost/",
Repo: "test/test", Repo: "test/test",
}, true) }, true)
@@ -43,7 +43,7 @@ func TestGetCompareURL(t *testing.T) {
func TestValidateConfig_EmptyRepro(t *testing.T) { func TestValidateConfig_EmptyRepro(t *testing.T) {
os.Setenv("GITLAB_ACCESS_TOKEN", "XXX") os.Setenv("GITLAB_ACCESS_TOKEN", "XXX")
defer os.Unsetenv("GITLAB_ACCESS_TOKEN") defer os.Unsetenv("GITLAB_ACCESS_TOKEN")
_, err := New(&config.GitLabProvider{ _, err := gitlab.New(&config.GitLabProvider{
CustomURL: "https://localhost/", CustomURL: "https://localhost/",
}, true) }, true)
assert.Error(t, err) assert.Error(t, err)
@@ -55,7 +55,7 @@ func TestValidateConfig_DefaultURL(t *testing.T) {
config := &config.GitLabProvider{ config := &config.GitLabProvider{
Repo: "localhost/test", Repo: "localhost/test",
} }
_, err := New(config, true) _, err := gitlab.New(config, true)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "https://gitlab.com", config.CustomURL) assert.Equal(t, "https://gitlab.com", config.CustomURL)
} }
@@ -67,7 +67,7 @@ func TestValidateConfig_CustomURL(t *testing.T) {
Repo: "/localhost/test/", Repo: "/localhost/test/",
CustomURL: "https://localhost/", CustomURL: "https://localhost/",
} }
_, err := New(config, true) _, err := gitlab.New(config, true)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "https://localhost", config.CustomURL) assert.Equal(t, "https://localhost", config.CustomURL)
assert.Equal(t, "localhost/test", config.Repo) assert.Equal(t, "localhost/test", config.Repo)
@@ -190,10 +190,10 @@ func TestCreateRelease(t *testing.T) {
} }
os.Setenv("GITLAB_ACCESS_TOKEN", "aToken") os.Setenv("GITLAB_ACCESS_TOKEN", "aToken")
defer os.Unsetenv("GITLAB_ACCESS_TOKEN") defer os.Unsetenv("GITLAB_ACCESS_TOKEN")
client, err := New(&testObject.config, false) client, err := gitlab.New(&testObject.config, false)
assert.NoError(t, err) assert.NoError(t, err)
err = client.makeRelease(testObject.releaseVersion, testObject.generatedChangelog) err = client.CreateRelease(testObject.releaseVersion, testObject.generatedChangelog)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }
@@ -239,7 +239,7 @@ func TestUploadAssets(t *testing.T) {
valid: true, valid: true,
testDir: os.TempDir(), testDir: os.TempDir(),
assets: []config.Asset{ assets: []config.Asset{
{ config.Asset{
Name: filepath.Base(file.Name()), Name: filepath.Base(file.Name()),
Compress: false, Compress: false,
}, },
@@ -258,7 +258,7 @@ func TestUploadAssets(t *testing.T) {
valid: false, valid: false,
testDir: os.TempDir(), testDir: os.TempDir(),
assets: []config.Asset{ assets: []config.Asset{
{ config.Asset{
Name: filepath.Base(file.Name()), Name: filepath.Base(file.Name()),
Compress: false, Compress: false,
}, },
@@ -277,7 +277,7 @@ func TestUploadAssets(t *testing.T) {
valid: false, valid: false,
testDir: os.TempDir(), testDir: os.TempDir(),
assets: []config.Asset{ assets: []config.Asset{
{ config.Asset{
Name: filepath.Base(file.Name()), Name: filepath.Base(file.Name()),
Compress: false, Compress: false,
}, },
@@ -317,16 +317,11 @@ func TestUploadAssets(t *testing.T) {
} }
os.Setenv("GITLAB_ACCESS_TOKEN", "aToken") os.Setenv("GITLAB_ACCESS_TOKEN", "aToken")
defer os.Unsetenv("GITLAB_ACCESS_TOKEN") defer os.Unsetenv("GITLAB_ACCESS_TOKEN")
client, err := New(&testObject.config, false) client, err := gitlab.New(&testObject.config, false)
assert.NoError(t, err) assert.NoError(t, err)
client.Release = "1.0.0" client.Release = "1.0.0"
assets := assets.New(testObject.testDir, "") err = client.UploadAssets(testObject.testDir, testObject.assets)
err = assets.Add(testObject.assets...)
if err != nil {
t.Log(err)
}
err = client.uploadAssets(assets)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
} }

View File

@@ -3,7 +3,6 @@ package releaser
import ( import (
"fmt" "fmt"
"github.com/Nightapes/go-semantic-release/internal/assets"
"github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/internal/gitutil"
"github.com/Nightapes/go-semantic-release/internal/releaser/git" "github.com/Nightapes/go-semantic-release/internal/releaser/git"
"github.com/Nightapes/go-semantic-release/internal/releaser/github" "github.com/Nightapes/go-semantic-release/internal/releaser/github"
@@ -22,7 +21,8 @@ type Releasers struct {
// Releaser interface for providers // Releaser interface for providers
type Releaser interface { type Releaser interface {
CreateRelease(*shared.ReleaseVersion, *shared.GeneratedChangelog, *assets.Set) error CreateRelease(*shared.ReleaseVersion, *shared.GeneratedChangelog) error
UploadAssets(repoDir string, assets []config.Asset) error
GetCommitURL() string GetCommitURL() string
GetCompareURL(oldVersion, newVersion string) string GetCompareURL(oldVersion, newVersion string) string
} }

View File

@@ -1,6 +1,7 @@
package util package util
import ( import (
"archive/zip"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
@@ -10,6 +11,7 @@ import (
"os" "os"
"strings" "strings"
"github.com/Nightapes/go-semantic-release/pkg/config"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )
@@ -60,78 +62,74 @@ func GetAccessToken(envName string) (string, error) {
return token, nil return token, nil
} }
// // PrepareAssets prepare all files before uploading // PrepareAssets prepare all files before uploading
// func PrepareAssets(repository string, assets []config.Asset) ([]*string, error) { func PrepareAssets(repository string, assets []config.Asset) ([]*string, error) {
// filesToUpload := []*string{} filesToUpload := []*string{}
// for _, asset := range assets { for _, asset := range assets {
// if asset.Name != "" && asset.Path == "" { if asset.Name == "" {
// log.Warn("Name is deprecated. Please update your config. See https://nightapes.github.io/go-semantic-release/") return nil, fmt.Errorf("asset name declaration is empty, please check your configuration file")
// } } else if asset.Compress {
log.Debugf("Asset %s will now be compressed", asset.Name)
log.Debugf("Repo url %s", repository)
zipNameWithPath, err := zipFile(repository, asset.Name)
if err != nil {
return filesToUpload, err
}
filesToUpload = append(filesToUpload, &zipNameWithPath)
} else {
tmpFileName := fmt.Sprintf("%s/%s", repository, asset.Name)
filesToUpload = append(filesToUpload, &tmpFileName)
}
log.Debugf("Add asset %s to files to upload", asset.Name)
}
return filesToUpload, nil
}
// if asset.Path == "" { // ZipFile compress given file in zip format
// return nil, fmt.Errorf("asset path declaration is empty, please check your configuration file") func zipFile(repository string, file string) (string, error) {
// } else if asset.Compress {
// log.Debugf("Asset %s will now be compressed", asset.Name)
// log.Debugf("Repo url %s", repository)
// zipNameWithPath, err := zipFile(repository, asset.Name)
// if err != nil {
// return filesToUpload, err
// }
// filesToUpload = append(filesToUpload, &zipNameWithPath)
// } else {
// tmpFileName := fmt.Sprintf("%s/%s", repository, asset.Name)
// filesToUpload = append(filesToUpload, &tmpFileName)
// }
// log.Debugf("Add asset %s to files to upload", asset.Name)
// }
// return filesToUpload, nil
// }
// // ZipFile compress given file in zip format fileToZip, err := os.Open(repository + "/" + file)
// func zipFile(repository string, file string) (string, error) { if err != nil {
return "", err
}
defer fileToZip.Close()
// fileToZip, err := os.Open(repository + "/" + file) zipFileName := fmt.Sprintf("%s/%s.zip", strings.TrimSuffix(repository, "/"), file)
// if err != nil { zipFile, err := os.Create(zipFileName)
// return "", err
// }
// defer fileToZip.Close()
// zipFileName := fmt.Sprintf("%s/%s.zip", strings.TrimSuffix(repository, "/"), file) if err != nil {
// zipFile, err := os.Create(zipFileName) return "", err
}
log.Debugf("Created zipfile %s", zipFile.Name())
// if err != nil { defer zipFile.Close()
// return "", err
// }
// log.Debugf("Created zipfile %s", zipFile.Name())
// defer zipFile.Close() fileToZipInfo, err := fileToZip.Stat()
if err != nil {
return "", err
}
// fileToZipInfo, err := fileToZip.Stat() zipWriter := zip.NewWriter(zipFile)
// if err != nil { defer zipWriter.Close()
// return "", err
// }
// zipWriter := zip.NewWriter(zipFile) fileToZipHeader, err := zip.FileInfoHeader(fileToZipInfo)
// defer zipWriter.Close() if err != nil {
return "", err
}
// fileToZipHeader, err := zip.FileInfoHeader(fileToZipInfo) fileToZipHeader.Name = fileToZipInfo.Name()
// if err != nil {
// return "", err
// }
// fileToZipHeader.Name = fileToZipInfo.Name() fileToZipWriter, err := zipWriter.CreateHeader(fileToZipHeader)
if err != nil {
return "", err
}
// fileToZipWriter, err := zipWriter.CreateHeader(fileToZipHeader) if _, err = io.Copy(fileToZipWriter, fileToZip); err != nil {
// if err != nil { return "", err
// return "", err }
// }
// if _, err = io.Copy(fileToZipWriter, fileToZip); err != nil { return zipFileName, nil
// return "", err }
// }
// return zipFileName, nil
// }
//PathEscape to be url save //PathEscape to be url save
func PathEscape(s string) string { func PathEscape(s string) string {

View File

@@ -13,6 +13,8 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/Nightapes/go-semantic-release/pkg/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/Nightapes/go-semantic-release/internal/releaser/util" "github.com/Nightapes/go-semantic-release/internal/releaser/util"
@@ -30,8 +32,8 @@ type testDoubleToken struct {
} }
var testDoubles = []testDoubleToken{ var testDoubles = []testDoubleToken{
{providerName: "test0", token: "foo", valid: true}, testDoubleToken{providerName: "test0", token: "foo", valid: true},
{providerName: "test1", token: "", valid: false}, testDoubleToken{providerName: "test1", token: "", valid: false},
} }
func TestGetAccessToken(t *testing.T) { func TestGetAccessToken(t *testing.T) {
@@ -48,6 +50,80 @@ func TestGetAccessToken(t *testing.T) {
} }
} }
type testDoubleFiles struct {
testFiles []config.Asset
valid bool
}
var files = []testDoubleFiles{
testDoubleFiles{
testFiles: []config.Asset{
config.Asset{
Name: "file0",
Compress: true,
},
config.Asset{
Name: "file1",
Compress: true,
},
},
valid: true,
},
testDoubleFiles{
testFiles: []config.Asset{
config.Asset{
Name: "",
Compress: true,
},
config.Asset{
Name: "",
Compress: false,
},
},
valid: false,
},
}
func TestPrepareAssets(t *testing.T) {
for _, testObject := range files {
workDir, _ := os.Getwd()
filesToDelete := []string{}
for _, testFile := range testObject.testFiles {
if testFile.Name != "" {
filesToDelete = append(filesToDelete, testFile.Name)
file, err := os.Create(testFile.Name)
if err != nil {
fmt.Print(err.Error())
}
defer file.Close()
if testFile.Compress {
filesToDelete = append(filesToDelete, testFile.Name+".zip")
}
}
}
preparedFiles, err := util.PrepareAssets(workDir, testObject.testFiles)
if err == nil {
assert.Equal(t, 2, len(preparedFiles))
}
assert.Equal(t, testObject.valid, err == nil)
for _, file := range filesToDelete {
if err := os.Remove(file); err != nil {
fmt.Println(err.Error())
}
}
}
}
func TestShouldRetry(t *testing.T) { func TestShouldRetry(t *testing.T) {
assert.True(t, util.ShouldRetry(&http.Response{StatusCode: 429})) assert.True(t, util.ShouldRetry(&http.Response{StatusCode: 429}))
assert.False(t, util.ShouldRetry(&http.Response{StatusCode: 200})) assert.False(t, util.ShouldRetry(&http.Response{StatusCode: 200}))

View File

@@ -37,22 +37,13 @@ type ChangelogTemplateConfig struct {
type AnalyzedCommit struct { type AnalyzedCommit struct {
Commit Commit `yaml:"commit"` Commit Commit `yaml:"commit"`
ParsedMessage string `yaml:"parsedMessage"` ParsedMessage string `yaml:"parsedMessage"`
Scope Scope `yaml:"scope"`
ParsedBreakingChangeMessage string `yaml:"parsedBreakingChangeMessage"` ParsedBreakingChangeMessage string `yaml:"parsedBreakingChangeMessage"`
Tag string `yaml:"tag"` Tag string `yaml:"tag"`
TagString string `yaml:"tagString"` TagString string `yaml:"tagString"`
Scope Scope `yaml:"scope"`
Subject string `yaml:"subject"`
MessageBlocks map[string][]MessageBlock `yaml:"messageBlocks"`
IsBreaking bool `yaml:"isBreaking"`
Print bool `yaml:"print"` Print bool `yaml:"print"`
} }
// MessageBlock represents a block in the body section of a commit message
type MessageBlock struct {
Label string `yaml:"label"`
Content string `yaml:"content"`
}
//Scope of the commit, like feat, fix,.. //Scope of the commit, like feat, fix,..
type Scope string type Scope string

View File

@@ -9,15 +9,6 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
const (
DefaultTagPrefix = "v"
)
// AnalyzerConfig struct
type AnalyzerConfig struct {
TokenSeparators []string `yaml:"tokenSeparators"`
}
// ChangelogConfig struct // ChangelogConfig struct
type ChangelogConfig struct { type ChangelogConfig struct {
PrintAll bool `yaml:"printAll,omitempty"` PrintAll bool `yaml:"printAll,omitempty"`
@@ -35,15 +26,13 @@ type ChangelogDocker struct {
//ChangelogNPM type struct //ChangelogNPM type struct
type ChangelogNPM struct { type ChangelogNPM struct {
Repository string `yaml:"repository"` YARN bool `yaml:"latest"`
PackageName string `yaml:"name"` Repository string `yaml:"repository"`
} }
//Asset type struct //Asset type struct
type Asset struct { type Asset struct {
Path string `yaml:"path"` Name string `yaml:"name"`
Rename string `yaml:"rename,omitempty"`
Name string `yaml:"name,omitempty"` // Deprecated
Compress bool `yaml:"compress"` Compress bool `yaml:"compress"`
} }
@@ -53,7 +42,6 @@ type GitHubProvider struct {
User string `yaml:"user"` User string `yaml:"user"`
CustomURL string `yaml:"customUrl,omitempty"` CustomURL string `yaml:"customUrl,omitempty"`
AccessToken string AccessToken string
TagPrefix *string `yaml:"tagPrefix,omitempty"`
} }
// GitLabProvider struct // GitLabProvider struct
@@ -61,16 +49,14 @@ type GitLabProvider struct {
Repo string `yaml:"repo"` Repo string `yaml:"repo"`
CustomURL string `yaml:"customUrl,omitempty"` CustomURL string `yaml:"customUrl,omitempty"`
AccessToken string AccessToken string
TagPrefix *string `yaml:"tagPrefix,omitempty"`
} }
// GitProvider struct // GitProvider struct
type GitProvider struct { type GitProvider struct {
Email string `yaml:"email"` Email string `yaml:"email"`
Username string `yaml:"user"` Username string `yaml:"user"`
Auth string `yaml:"auth"` Auth string `yaml:"auth"`
SSH bool `yaml:"ssh"` SSH bool `yaml:"ssh"`
TagPrefix *string `yaml:"tagPrefix,omitempty"`
} }
// Hooks struct // Hooks struct
@@ -79,36 +65,17 @@ type Hooks struct {
PostRelease []string `yaml:"postRelease"` PostRelease []string `yaml:"postRelease"`
} }
// Checksum struct
type Checksum struct {
Algorithm string `yaml:"algorithm"`
}
// Checksum struct
type Integrations struct {
NPM IntegrationNPM `yaml:"npm"`
}
// Checksum struct
type IntegrationNPM struct {
Enabled bool `yaml:"enabled"`
Path string `yaml:"path"`
}
// ReleaseConfig struct // ReleaseConfig struct
type ReleaseConfig struct { type ReleaseConfig struct {
CommitFormat string `yaml:"commitFormat"` CommitFormat string `yaml:"commitFormat"`
Branch map[string]string `yaml:"branch"` Branch map[string]string `yaml:"branch"`
Analyzer AnalyzerConfig `yaml:"analyzer"`
Changelog ChangelogConfig `yaml:"changelog,omitempty"` Changelog ChangelogConfig `yaml:"changelog,omitempty"`
Release string `yaml:"release,omitempty"` Release string `yaml:"release,omitempty"`
GitHubProvider GitHubProvider `yaml:"github,omitempty"` GitHubProvider GitHubProvider `yaml:"github,omitempty"`
GitLabProvider GitLabProvider `yaml:"gitlab,omitempty"` GitLabProvider GitLabProvider `yaml:"gitlab,omitempty"`
GitProvider GitProvider `yaml:"git,omitempty"` GitProvider GitProvider `yaml:"git,omitempty"`
Assets []Asset `yaml:"assets"` Assets []Asset `yaml:"assets"`
Checksum Checksum `yaml:"checksum,omitempty"`
Hooks Hooks `yaml:"hooks"` Hooks Hooks `yaml:"hooks"`
Integrations Integrations `yaml:"integrations"`
ReleaseTitle string `yaml:"title"` ReleaseTitle string `yaml:"title"`
IsPreRelease bool IsPreRelease bool
} }

View File

@@ -95,12 +95,11 @@ github:
}, },
}, },
Assets: []config.Asset{ Assets: []config.Asset{
{ config.Asset{
Name: "./build/go-semantic-release", Name: "./build/go-semantic-release",
Compress: false}}, Compress: false}},
ReleaseTitle: "go-semantic-release release", ReleaseTitle: "go-semantic-release release",
IsPreRelease: false, IsPreRelease: false,
Analyzer: config.AnalyzerConfig{TokenSeparators: []string{}},
}, result) }, result)
} }

View File

@@ -1,15 +1,11 @@
package semanticrelease package semanticrelease
import ( import (
"github.com/Nightapes/go-semantic-release/internal/integrations"
"io/ioutil" "io/ioutil"
"time" "time"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
log "github.com/sirupsen/logrus"
"github.com/Nightapes/go-semantic-release/internal/analyzer" "github.com/Nightapes/go-semantic-release/internal/analyzer"
"github.com/Nightapes/go-semantic-release/internal/assets"
"github.com/Nightapes/go-semantic-release/internal/cache" "github.com/Nightapes/go-semantic-release/internal/cache"
"github.com/Nightapes/go-semantic-release/internal/calculator" "github.com/Nightapes/go-semantic-release/internal/calculator"
"github.com/Nightapes/go-semantic-release/internal/changelog" "github.com/Nightapes/go-semantic-release/internal/changelog"
@@ -17,18 +13,19 @@ import (
"github.com/Nightapes/go-semantic-release/internal/gitutil" "github.com/Nightapes/go-semantic-release/internal/gitutil"
"github.com/Nightapes/go-semantic-release/internal/hooks" "github.com/Nightapes/go-semantic-release/internal/hooks"
"github.com/Nightapes/go-semantic-release/internal/releaser" "github.com/Nightapes/go-semantic-release/internal/releaser"
"github.com/Nightapes/go-semantic-release/internal/releaser/util"
"github.com/Nightapes/go-semantic-release/internal/shared" "github.com/Nightapes/go-semantic-release/internal/shared"
"github.com/Nightapes/go-semantic-release/pkg/config" "github.com/Nightapes/go-semantic-release/pkg/config"
log "github.com/sirupsen/logrus"
) )
// SemanticRelease struct // SemanticRelease struct
type SemanticRelease struct { type SemanticRelease struct {
config *config.ReleaseConfig config *config.ReleaseConfig
gitUtil *gitutil.GitUtil gitutil *gitutil.GitUtil
analyzer *analyzer.Analyzer analyzer *analyzer.Analyzer
calculator *calculator.Calculator calculator *calculator.Calculator
releaser releaser.Releaser releaser releaser.Releaser
assets *assets.Set
repository string repository string
checkConfig bool checkConfig bool
} }
@@ -40,7 +37,7 @@ func New(c *config.ReleaseConfig, repository string, checkConfig bool) (*Semanti
return nil, err return nil, err
} }
analyzer, err := analyzer.New(c.CommitFormat, c.Analyzer, c.Changelog) analyzer, err := analyzer.New(c.CommitFormat, c.Changelog)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -49,8 +46,6 @@ func New(c *config.ReleaseConfig, repository string, checkConfig bool) (*Semanti
log.Infof("Ignore config checks!. No guarantee to run without issues") log.Infof("Ignore config checks!. No guarantee to run without issues")
} }
assets := assets.New(repository, c.Checksum.Algorithm)
releaser, err := releaser.New(c, util).GetReleaser(checkConfig) releaser, err := releaser.New(c, util).GetReleaser(checkConfig)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -58,19 +53,18 @@ func New(c *config.ReleaseConfig, repository string, checkConfig bool) (*Semanti
return &SemanticRelease{ return &SemanticRelease{
config: c, config: c,
gitUtil: util, gitutil: util,
releaser: releaser, releaser: releaser,
analyzer: analyzer, analyzer: analyzer,
repository: repository, repository: repository,
assets: assets,
checkConfig: checkConfig, checkConfig: checkConfig,
calculator: calculator.New(), calculator: calculator.New(),
}, nil }, nil
} }
// GetCIProvider result with ci config //GetCIProvider result with ci config
func (s *SemanticRelease) GetCIProvider() (*ci.ProviderConfig, error) { func (s *SemanticRelease) GetCIProvider() (*ci.ProviderConfig, error) {
return ci.GetCIProvider(s.gitUtil, s.checkConfig, ci.ReadAllEnvs()) return ci.GetCIProvider(s.gitutil, s.checkConfig, ci.ReadAllEnvs())
} }
// GetNextVersion from .version or calculate new from commits // GetNextVersion from .version or calculate new from commits
@@ -87,7 +81,7 @@ func (s *SemanticRelease) GetNextVersion(provider *ci.ProviderConfig, force bool
} }
} }
lastVersion, lastVersionHash, err := s.gitUtil.GetLastVersion() lastVersion, lastVersionHash, err := s.gitutil.GetLastVersion()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -100,7 +94,7 @@ func (s *SemanticRelease) GetNextVersion(provider *ci.ProviderConfig, force bool
firstRelease = true firstRelease = true
} }
commits, err := s.gitUtil.GetCommits(lastVersionHash) commits, err := s.gitutil.GetCommits(lastVersionHash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -150,14 +144,15 @@ func (s *SemanticRelease) GetNextVersion(provider *ci.ProviderConfig, force bool
return &releaseVersion, err return &releaseVersion, err
} }
// SetVersion for git repository //SetVersion for git repository
func (s *SemanticRelease) SetVersion(provider *ci.ProviderConfig, version string) error { func (s *SemanticRelease) SetVersion(provider *ci.ProviderConfig, version string) error {
newVersion, err := semver.NewVersion(version) newVersion, err := semver.NewVersion(version)
if err != nil { if err != nil {
return err return err
} }
lastVersion, lastVersionHash, err := s.gitUtil.GetLastVersion() lastVersion, lastVersionHash, err := s.gitutil.GetLastVersion()
if err != nil { if err != nil {
return err return err
} }
@@ -181,21 +176,23 @@ func (s *SemanticRelease) SetVersion(provider *ci.ProviderConfig, version string
// GetChangelog from last version till now // GetChangelog from last version till now
func (s *SemanticRelease) GetChangelog(releaseVersion *shared.ReleaseVersion) (*shared.GeneratedChangelog, error) { func (s *SemanticRelease) GetChangelog(releaseVersion *shared.ReleaseVersion) (*shared.GeneratedChangelog, error) {
c := changelog.New(s.config, s.analyzer.GetRules(), time.Now()) c := changelog.New(s.config, s.analyzer.GetRules(), time.Now())
return c.GenerateChangelog(shared.ChangelogTemplateConfig{ return c.GenerateChanglog(shared.ChangelogTemplateConfig{
Version: releaseVersion.Next.Version.String(), Version: releaseVersion.Next.Version.String(),
Hash: releaseVersion.Last.Commit, Hash: releaseVersion.Last.Commit,
CommitURL: s.releaser.GetCommitURL(), CommitURL: s.releaser.GetCommitURL(),
CompareURL: s.releaser.GetCompareURL(releaseVersion.Last.Version.String(), releaseVersion.Next.Version.String()), CompareURL: s.releaser.GetCompareURL(releaseVersion.Last.Version.String(), releaseVersion.Next.Version.String()),
}, releaseVersion.Commits) }, releaseVersion.Commits)
} }
// WriteChangeLog writes changelog content to the given file // WriteChangeLog wirtes changelog content to the given file
func (s *SemanticRelease) WriteChangeLog(changelogContent, file string) error { func (s *SemanticRelease) WriteChangeLog(changelogContent, file string) error {
return ioutil.WriteFile(file, []byte(changelogContent), 0644) return ioutil.WriteFile(file, []byte(changelogContent), 0644)
} }
// Release publish release to provider // Release publish release to provider
func (s *SemanticRelease) Release(provider *ci.ProviderConfig, force bool) error { func (s *SemanticRelease) Release(provider *ci.ProviderConfig, force bool) error {
if provider.IsPR { if provider.IsPR {
log.Infof("Will not perform a new release. This is a pull request") log.Infof("Will not perform a new release. This is a pull request")
return nil return nil
@@ -206,10 +203,6 @@ func (s *SemanticRelease) Release(provider *ci.ProviderConfig, force bool) error
return nil return nil
} }
if err := s.assets.Add(s.config.Assets...); err != nil {
return err
}
releaseVersion, err := s.GetNextVersion(provider, force) releaseVersion, err := s.GetNextVersion(provider, force)
if err != nil { if err != nil {
log.Debugf("Could not get next version") log.Debugf("Could not get next version")
@@ -221,43 +214,30 @@ func (s *SemanticRelease) Release(provider *ci.ProviderConfig, force bool) error
return nil return nil
} }
hook := hooks.New(s.config, releaseVersion)
generatedChangelog, err := s.GetChangelog(releaseVersion) generatedChangelog, err := s.GetChangelog(releaseVersion)
if err != nil { if err != nil {
log.Debugf("Could not get changelog") log.Debugf("Could not get changelog")
return err return err
} }
integrations := integrations.New(&s.config.Integrations, releaseVersion) err = hook.PreRelease()
if err := integrations.Run(); err != nil { if err != nil {
log.Debugf("Error during integrations run")
return err
}
hook := hooks.New(s.config, releaseVersion)
if err := hook.PreRelease(); err != nil {
log.Debugf("Error during pre release hook") log.Debugf("Error during pre release hook")
return err return err
} }
if s.config.Checksum.Algorithm != "" { if err = s.releaser.CreateRelease(releaseVersion, generatedChangelog); err != nil {
if err := s.assets.GenerateChecksum(); err != nil {
return err
}
}
for _, asset := range s.assets.All() {
if asset.IsCompressed() {
if _, err := asset.ZipFile(); err != nil {
return err
}
}
}
if err = s.releaser.CreateRelease(releaseVersion, generatedChangelog, s.assets); err != nil {
return err return err
} }
if err := hook.PostRelease(); err != nil { if err = s.releaser.UploadAssets(s.repository, s.config.Assets); err != nil {
return err
}
err = hook.PostRelease()
if err != nil {
log.Debugf("Error during post release hook") log.Debugf("Error during post release hook")
return err return err
} }
@@ -267,21 +247,12 @@ func (s *SemanticRelease) Release(provider *ci.ProviderConfig, force bool) error
// ZipFiles zip files configured in release config // ZipFiles zip files configured in release config
func (s *SemanticRelease) ZipFiles() error { func (s *SemanticRelease) ZipFiles() error {
assets := assets.New(s.repository, "") for _, file := range s.config.Assets {
if file.Compress {
if err := assets.Add(s.config.Assets...); err != nil { if _, err := util.PrepareAssets(s.repository, s.config.Assets); err != nil {
return err return err
} }
if err := assets.GenerateChecksum(); err != nil {
return err
}
for _, asset := range assets.All() {
path, err := asset.GetPath()
if err != nil {
return err
} }
log.Infof("File %s under %s is zipped %t", asset.GetName(), path, asset.IsCompressed())
} }
return nil return nil
} }