Skip to content

Commit bbf4ecf

Browse files
vvbogdanov87christophwitzko
authored andcommitted
feat: switch to urfave/cli
1 parent 02affe1 commit bbf4ecf

File tree

6 files changed

+159
-72
lines changed

6 files changed

+159
-72
lines changed

cmd/semantic-release/main.go

Lines changed: 33 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@ package main
22

33
import (
44
"context"
5-
"encoding/json"
65
"errors"
7-
"flag"
86
"fmt"
97
"github.com/go-semantic-release/semantic-release/pkg/condition"
8+
"github.com/go-semantic-release/semantic-release/pkg/config"
109
"github.com/go-semantic-release/semantic-release/pkg/semrel"
1110
"github.com/go-semantic-release/semantic-release/pkg/update"
11+
"github.com/urfave/cli/v2"
1212
"io/ioutil"
1313
"log"
1414
"os"
1515
"strings"
1616
)
1717

18+
// SRVERSION is the semantic-release version (added at compile time)
1819
var SRVERSION string
1920

2021
func errorHandler(logger *log.Logger) func(error, ...int) {
@@ -30,60 +31,30 @@ func errorHandler(logger *log.Logger) func(error, ...int) {
3031
}
3132
}
3233

33-
type SemRelConfig struct {
34-
MaintainedVersion string `json:"maintainedVersion"`
35-
}
36-
37-
func loadConfig() *SemRelConfig {
38-
f, err := os.OpenFile(".semrelrc", os.O_RDONLY, 0)
34+
func main() {
35+
app := cli.NewApp()
36+
app.Name = "semantic-release"
37+
app.Usage = "automates the package release workflow including: determining the next version number and generating the change log"
38+
app.Version = SRVERSION
39+
app.Flags = config.CliFlags
40+
app.Action = cliHandler
41+
42+
err := app.Run(os.Args)
3943
if err != nil {
40-
return &SemRelConfig{}
44+
log.Fatal(err)
4145
}
42-
src := &SemRelConfig{}
43-
json.NewDecoder(f).Decode(src)
44-
f.Close()
45-
return src
4646
}
4747

48-
func main() {
49-
token := flag.String("token", os.Getenv("GITHUB_TOKEN"), "github token")
50-
slug := flag.String("slug", condition.GetDefaultRepoSlug(), "slug of the repository")
51-
changelogFile := flag.String("changelog", "", "creates a changelog file")
52-
ghr := flag.Bool("ghr", false, "create a .ghr file with the parameters for ghr")
53-
noci := flag.Bool("noci", false, "run semantic-release locally")
54-
dry := flag.Bool("dry", false, "do not create release")
55-
vFile := flag.Bool("vf", false, "create a .version file")
56-
showVersion := flag.Bool("version", false, "outputs the semantic-release version")
57-
updateFile := flag.String("update", "", "updates the version of a certain file")
58-
gheHost := flag.String("ghe-host", os.Getenv("GITHUB_ENTERPRISE_HOST"), "github enterprise host")
59-
isPrerelease := flag.Bool("prerelease", false, "flags the release as a prerelease")
60-
isTravisCom := flag.Bool("travis-com", false, "force semantic-release to use the travis-ci.com API endpoint")
61-
flag.Parse()
62-
63-
if *showVersion {
64-
fmt.Printf("semantic-release v%s", SRVERSION)
65-
return
66-
}
48+
func cliHandler(c *cli.Context) error {
49+
conf := config.NewConfig(c)
6750

6851
logger := log.New(os.Stderr, "[semantic-release]: ", 0)
6952
exitIfError := errorHandler(logger)
7053

71-
if val, ok := os.LookupEnv("GH_TOKEN"); *token == "" && ok {
72-
*token = val
73-
}
74-
75-
if *token == "" {
76-
exitIfError(errors.New("github token missing"))
77-
}
78-
7954
ci := condition.NewCI()
8055
logger.Printf("detected CI: %s\n", ci.Name())
8156

82-
if *slug == "" {
83-
exitIfError(errors.New("slug missing"))
84-
}
85-
86-
repo, err := semrel.NewRepository(context.TODO(), *gheHost, *slug, *token)
57+
repo, err := semrel.NewRepository(context.TODO(), conf.GheHost, conf.Slug, conf.Token)
8758
exitIfError(err)
8859

8960
logger.Println("getting default branch...")
@@ -100,35 +71,34 @@ func main() {
10071
}
10172
logger.Println("found current branch: " + currentBranch)
10273

103-
config := loadConfig()
104-
if config.MaintainedVersion != "" && currentBranch == defaultBranch {
74+
if conf.BetaRelease.MaintainedVersion != "" && currentBranch == defaultBranch {
10575
exitIfError(fmt.Errorf("maintained version not allowed on default branch"))
10676
}
10777

108-
if config.MaintainedVersion != "" {
109-
logger.Println("found maintained version: " + config.MaintainedVersion)
78+
if conf.BetaRelease.MaintainedVersion != "" {
79+
logger.Println("found maintained version: " + conf.BetaRelease.MaintainedVersion)
11080
defaultBranch = "*"
11181
}
11282

11383
currentSha := ci.GetCurrentSHA()
11484
logger.Println("found current sha: " + currentSha)
11585

116-
if !*noci {
86+
if !conf.Noci {
11787
logger.Println("running CI condition...")
11888
config := condition.CIConfig{
119-
"token": *token,
89+
"token": conf.Token,
12090
"defaultBranch": defaultBranch,
121-
"private": isPrivate || *isTravisCom,
91+
"private": isPrivate || conf.TravisCom,
12292
}
12393
exitIfError(ci.RunCondition(config), 66)
12494
}
12595

12696
logger.Println("getting latest release...")
127-
release, err := repo.GetLatestRelease(config.MaintainedVersion)
97+
release, err := repo.GetLatestRelease(conf.BetaRelease.MaintainedVersion)
12898
exitIfError(err)
12999
logger.Println("found version: " + release.Version.String())
130100

131-
if strings.Contains(config.MaintainedVersion, "-") && release.Version.Prerelease() == "" {
101+
if strings.Contains(conf.BetaRelease.MaintainedVersion, "-") && release.Version.Prerelease() == "" {
132102
exitIfError(fmt.Errorf("no pre-release for this version possible"))
133103
}
134104

@@ -143,30 +113,31 @@ func main() {
143113
}
144114
logger.Println("new version: " + newVer.String())
145115

146-
if *dry {
116+
if conf.Dry {
147117
exitIfError(errors.New("DRY RUN: no release was created"), 65)
148118
}
149119

150120
logger.Println("generating changelog...")
151121
changelog := semrel.GetChangelog(commits, release, newVer)
152-
if *changelogFile != "" {
153-
exitIfError(ioutil.WriteFile(*changelogFile, []byte(changelog), 0644))
122+
if conf.Changelog != "" {
123+
exitIfError(ioutil.WriteFile(conf.Changelog, []byte(changelog), 0644))
154124
}
155125

156126
logger.Println("creating release...")
157-
exitIfError(repo.CreateRelease(changelog, newVer, *isPrerelease, currentBranch, currentSha))
127+
exitIfError(repo.CreateRelease(changelog, newVer, conf.Prerelease, currentBranch, currentSha))
158128

159-
if *ghr {
129+
if conf.Ghr {
160130
exitIfError(ioutil.WriteFile(".ghr", []byte(fmt.Sprintf("-u %s -r %s v%s", repo.Owner, repo.Repo, newVer.String())), 0644))
161131
}
162132

163-
if *vFile {
133+
if conf.Vf {
164134
exitIfError(ioutil.WriteFile(".version", []byte(newVer.String()), 0644))
165135
}
166136

167-
if *updateFile != "" {
168-
exitIfError(update.Apply(*updateFile, newVer.String()))
137+
if conf.Update != "" {
138+
exitIfError(update.Apply(conf.Update, newVer.String()))
169139
}
170140

171141
logger.Println("done.")
142+
return nil
172143
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ require (
99
github.com/google/go-github/v30 v30.1.0
1010
github.com/oleiade/reflections v1.0.0 // indirect
1111
github.com/stretchr/testify v1.5.1 // indirect
12+
github.com/urfave/cli/v2 v2.2.0
1213
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
1314
)

go.sum

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2+
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
23
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
34
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
45
github.com/christophwitzko/go-travis v0.0.0-20180115212951-5311d81d834b h1:YKFJ/MSTMtRCR7UeF4I2Ovi8HDwsVA7F/qWxwr7J6tU=
56
github.com/christophwitzko/go-travis v0.0.0-20180115212951-5311d81d834b/go.mod h1:0PHJRx/NZav97xUaOdeXLPZmPKBjSHVBAeiFFkaRSmc=
7+
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
8+
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
69
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
710
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
811
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
@@ -18,9 +21,15 @@ github.com/oleiade/reflections v1.0.0 h1:0ir4pc6v8/PJ0yw5AEtMddfXpWBXg9cnG7SgSoJ
1821
github.com/oleiade/reflections v1.0.0/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w=
1922
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2023
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
24+
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
25+
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
26+
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
27+
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
2128
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
2229
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
2330
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
31+
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
32+
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
2433
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
2534
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
2635
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

pkg/condition/condition.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,6 @@ func ReadGitHead() string {
1414
return strings.TrimSpace(strings.TrimPrefix(string(data), "ref: refs/heads/"))
1515
}
1616

17-
func GetDefaultRepoSlug() string {
18-
if val := os.Getenv("TRAVIS_REPO_SLUG"); val != "" {
19-
return val
20-
}
21-
if val := os.Getenv("GITHUB_REPOSITORY"); val != "" {
22-
return val
23-
}
24-
return ""
25-
}
26-
2717
type CIConfig map[string]interface{}
2818

2919
type CI interface {

pkg/config/config.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package config
2+
3+
import (
4+
"encoding/json"
5+
"github.com/urfave/cli/v2"
6+
"os"
7+
)
8+
9+
type (
10+
// Config is a complete set of app configuration
11+
Config struct {
12+
Token string
13+
Slug string
14+
Changelog string
15+
Ghr bool
16+
Noci bool
17+
Dry bool
18+
Vf bool
19+
Update string
20+
GheHost string
21+
Prerelease bool
22+
TravisCom bool
23+
BetaRelease BetaRelease
24+
}
25+
26+
BetaRelease struct {
27+
MaintainedVersion string `json:"maintainedVersion"`
28+
}
29+
)
30+
31+
// NewConfig returns a new Config instance
32+
func NewConfig(c *cli.Context) *Config {
33+
conf := &Config{
34+
Token: c.String("token"),
35+
Slug: c.String("slug"),
36+
Changelog: c.String("changelog"),
37+
Ghr: c.Bool("ghr"),
38+
Noci: c.Bool("noci"),
39+
Dry: c.Bool("dry"),
40+
Vf: c.Bool("vf"),
41+
Update: c.String("update"),
42+
GheHost: c.String("ghe-host"),
43+
Prerelease: c.Bool("prerelease"),
44+
TravisCom: c.Bool("travis-com"),
45+
}
46+
47+
f, err := os.OpenFile(".semrelrc", os.O_RDONLY, 0)
48+
if err != nil {
49+
return conf
50+
}
51+
defer f.Close()
52+
53+
src := &BetaRelease{}
54+
json.NewDecoder(f).Decode(src)
55+
conf.BetaRelease = *src
56+
57+
return conf
58+
}

pkg/config/flags.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package config
2+
3+
import (
4+
"github.com/urfave/cli/v2"
5+
)
6+
7+
// CliFlags cli flags
8+
var CliFlags = []cli.Flag{
9+
&cli.StringFlag{
10+
Name: "token",
11+
Usage: "github token",
12+
EnvVars: []string{"GITHUB_TOKEN", "GH_TOKEN"},
13+
Required: true,
14+
},
15+
&cli.StringFlag{
16+
Name: "slug",
17+
Usage: "slug of the repository",
18+
EnvVars: []string{"GITHUB_REPOSITORY", "TRAVIS_REPO_SLUG"},
19+
Required: true,
20+
},
21+
&cli.StringFlag{
22+
Name: "changelog",
23+
Usage: "creates a changelog file",
24+
},
25+
&cli.BoolFlag{
26+
Name: "ghr",
27+
Usage: "create a .ghr file with the parameters for ghr",
28+
},
29+
&cli.BoolFlag{
30+
Name: "noci",
31+
Usage: "run semantic-release locally",
32+
},
33+
&cli.BoolFlag{
34+
Name: "dry",
35+
Usage: "do not create release",
36+
},
37+
&cli.BoolFlag{
38+
Name: "vf",
39+
Usage: "create a .version file",
40+
},
41+
&cli.StringFlag{
42+
Name: "update",
43+
Usage: "updates the version of a certain file",
44+
},
45+
&cli.StringFlag{
46+
Name: "ghe-host",
47+
Usage: "github enterprise host",
48+
EnvVars: []string{"GITHUB_ENTERPRISE_HOST"},
49+
},
50+
&cli.BoolFlag{
51+
Name: "prerelease",
52+
Usage: "flags the release as a prerelease",
53+
},
54+
&cli.BoolFlag{
55+
Name: "travis-com",
56+
Usage: "force semantic-release to use the travis-ci.com API endpoint",
57+
},
58+
}

0 commit comments

Comments
 (0)