Skip to content

Commit eebb44e

Browse files
authored
Merge pull request #9 from happypork/non-zero-exit-code
Non zero exit code on outdated dependencies
2 parents 758f6b1 + ec66cbd commit eebb44e

File tree

6 files changed

+125
-6
lines changed

6 files changed

+125
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
55

66
## [0.3.0] unreleased
77
### Added
8-
- osx in travis
8+
- osx in travis
9+
- Flag '-ci' to exit with non-zero exit code when an outdated dependency is found
910
### Removed
1011
- tip version in travis
1112

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,23 @@ If you want to see only the direct depedencies that have updates run
7474
go list -u -m -json all | go-mod-outdated -update -direct
7575
```
7676

77+
If you want to make your CI pipeline fail
78+
79+
```
80+
go list -u -m -json all | go-mod-outdated -direct -ci
81+
```
82+
### CI pipelines
83+
84+
Using the -ci flag will the make the command exit with none zero code, breaking this way your ci pipelines.
85+
86+
If you want to make your CI pipeline fail if any direct or indirect dependency is outdated use the following:
87+
```
88+
go list -u -m -json all | go-mod-outdated -ci
89+
```
90+
If you want to make your CI pipeline fail only if a direct dependency is outdated use the following:
91+
```
92+
go list -u -m -json all | go-mod-outdated -direct -ci
93+
```
7794
### Help
7895

7996
In order to see details about the usage of the command use the **-h** or **-help** flag
@@ -86,6 +103,8 @@ Usage of go-mod-outdated:
86103
List only direct modules
87104
-update
88105
List only modules with updates
106+
-ci
107+
Exit with non-zero exit code when outdated dependencies are found
89108
```
90109

91110
### Shortcut
@@ -390,3 +409,19 @@ $ go list -u -m -json all | go-mod-outdated -update -direct
390409
| golang.org/x/sync | v0.0.0-20180314180146-1d60e4601c6f | v0.0.0-20190412183630-56d357773e84 | true | true |
391410
+------------------------------------+--------------------------------------+------------------------------------+--------+------------------+
392411
```
412+
### Table view of go list -u -m -json all command using go-mod-outdated (with -ci flag, only direct dependencies with updates)
413+
414+
```
415+
$ go list -u -m -json all | go-mod-outdated -update -direct -ci
416+
+------------------------------------+--------------------------------------+------------------------------------+--------+------------------+
417+
| MODULE | VERSION | NEW VERSION | DIRECT | VALID TIMESTAMPS |
418+
+------------------------------------+--------------------------------------+------------------------------------+--------+------------------+
419+
| github.com/BurntSushi/toml | v0.0.0-20170626110600-a368813c5e64 | v0.3.1 | true | true |
420+
| github.com/PuerkitoBio/purell | v1.1.0 | v1.1.1 | true | true |
421+
| github.com/alecthomas/chroma | v0.6.0 | v0.6.3 | true | true |
422+
...
423+
| golang.org/x/sync | v0.0.0-20180314180146-1d60e4601c6f | v0.0.0-20190412183630-56d357773e84 | true | true |
424+
+------------------------------------+--------------------------------------+------------------------------------+--------+------------------+
425+
$ echo $?
426+
1
427+
```

internal/runner/runner.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ package runner
33
import (
44
"encoding/json"
55
"io"
6+
"os"
67
"strconv"
78

89
"github.com/psampaz/go-mod-outdated/internal/mod"
910

1011
"github.com/olekukonko/tablewriter"
1112
)
1213

14+
var OsExit = os.Exit
15+
1316
// Run converts the the json output of go list -u -m -json all to table format
14-
func Run(in io.Reader, out io.Writer, update, direct bool) error {
17+
func Run(in io.Reader, out io.Writer, update, direct, exitWithNonZero bool) error {
1518
var modules []mod.Module
1619
dec := json.NewDecoder(in)
1720

@@ -21,7 +24,11 @@ func Run(in io.Reader, out io.Writer, update, direct bool) error {
2124

2225
if err != nil {
2326
if err == io.EOF {
24-
renderTable(out, mod.FilterModules(modules, update, direct))
27+
filteredModules := mod.FilterModules(modules, update, direct)
28+
renderTable(out, filteredModules)
29+
if hasOutdated(filteredModules) && exitWithNonZero {
30+
OsExit(1)
31+
}
2532
return nil
2633
}
2734
return err
@@ -30,6 +37,15 @@ func Run(in io.Reader, out io.Writer, update, direct bool) error {
3037
}
3138
}
3239

40+
func hasOutdated(filteredModules []mod.Module) bool {
41+
for m := range filteredModules {
42+
if filteredModules[m].HasUpdate() {
43+
return true
44+
}
45+
}
46+
return false
47+
}
48+
3349
func renderTable(writer io.Writer, modules []mod.Module) {
3450
table := tablewriter.NewWriter(writer)
3551
table.SetHeader([]string{"Module", "Version", "New Version", "Direct", "Valid Timestamps"})

internal/runner/runner_test.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func TestRun(t *testing.T) {
1919
outBytes, _ := ioutil.ReadFile("testdata/out.txt")
2020
wantOut := bytes.NewBuffer(outBytes)
2121

22-
err := runner.Run(in, &gotOut, false, false)
22+
err := runner.Run(in, &gotOut, false, false, false)
2323

2424
if err != nil {
2525
t.Errorf("Error should be nil, got %s", err.Error())
@@ -38,11 +38,59 @@ func TestRunWithError(t *testing.T) {
3838
inBytes, _ := ioutil.ReadFile("testdata/err.txt")
3939
in := bytes.NewBuffer(inBytes)
4040

41-
gotErr := runner.Run(in, &out, false, false)
41+
gotErr := runner.Run(in, &out, false, false, false)
4242
wantErr := errors.New("unexpected EOF")
4343

4444
if gotErr.Error() != wantErr.Error() {
4545
t.Errorf("Wanted %s, got %s", wantErr, gotErr)
4646
}
4747

4848
}
49+
50+
func TestRunExitWithNonZero(t *testing.T) {
51+
var out bytes.Buffer
52+
53+
inBytes, _ := ioutil.ReadFile("testdata/in.txt")
54+
in := bytes.NewBuffer(inBytes)
55+
56+
oldOsExit := runner.OsExit
57+
defer func() { runner.OsExit = oldOsExit }()
58+
59+
var got int
60+
testExit := func(code int) {
61+
got = code
62+
}
63+
64+
runner.OsExit = testExit
65+
err := runner.Run(in, &out, false, false, true)
66+
if err != nil {
67+
t.Errorf("Error should be nil, got %s", err.Error())
68+
}
69+
if exp := 1; got != exp {
70+
t.Errorf("Expected exit code: %d, got: %d", exp, got)
71+
}
72+
}
73+
74+
func TestRunExitWithNonZeroIndirectsOnly(t *testing.T) {
75+
76+
inBytes, _ := ioutil.ReadFile("testdata/update_indirect.txt")
77+
in := bytes.NewBuffer(inBytes)
78+
79+
oldOsExit := runner.OsExit
80+
defer func() { runner.OsExit = oldOsExit }()
81+
82+
var got int
83+
testExit := func(code int) {
84+
got = code
85+
}
86+
87+
runner.OsExit = testExit
88+
var out bytes.Buffer
89+
err := runner.Run(in, &out, false, true, true)
90+
if err != nil {
91+
t.Errorf("Error should be nil, got %s", err.Error())
92+
}
93+
if exp := 0; got != exp {
94+
t.Errorf("Expected exit code: %d, got: %d", exp, got)
95+
}
96+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"Path": "github.com/gohugoio/hugo",
3+
"Main": true,
4+
"Dir": "/home/mojo/Code/go/hugo",
5+
"GoMod": "/home/mojo/Code/go/hugo/go.mod"
6+
}
7+
{
8+
"Path": "github.com/muesli/smartcrop",
9+
"Version": "v0.0.0-20180228075044-f6ebaa786a12",
10+
"Time": "2018-02-28T07:50:44Z",
11+
"Indirect": true,
12+
"Update": {
13+
"Path": "github.com/muesli/smartcrop",
14+
"Version": "v0.2.0",
15+
"Time": "2017-08-09T19:13:04Z"
16+
},
17+
"GoMod": "/home/user/go/pkg/mod/cache/download/github.com/muesli/smartcrop/@v/v0.0.0-20180228075044-f6ebaa786a12.mod"
18+
}

main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ func main() {
1212

1313
withUpdate := flag.Bool("update", false, "List only modules with updates")
1414
onlyDirect := flag.Bool("direct", false, "List only direct modules")
15+
exitNonZero := flag.Bool("ci", false, "Non-zero exit code when at least one outdated dependency was found")
1516
flag.Parse()
1617

17-
err := runner.Run(os.Stdin, os.Stdout, *withUpdate, *onlyDirect)
18+
err := runner.Run(os.Stdin, os.Stdout, *withUpdate, *onlyDirect, *exitNonZero)
1819

1920
if err != nil {
2021
log.Print(err)

0 commit comments

Comments
 (0)