Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
zcapitalz committed Jun 24, 2024
0 parents commit ac1a766
Show file tree
Hide file tree
Showing 16 changed files with 913 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/golangci-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: golangci-lint
on:
push:
branches:
- master
pull_request:

permissions:
contents: read

jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.59
23 changes: 23 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: test

on:
push:
branches:
- master
pull_request:

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'

- name: Run tests
run: go test -v .
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
run:
tests: false
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Go Test Retryer

CLI tool that runs `go test`(or another command from `--test-command-name`) with arguments from `--test-args`, parses test results from output and retries failed tests according to `--retries-per-test` and `--total-reries` limits. If `--total-retries` is 0, then no global limit is applied.

**Usage of go-test-retryer**:
- --test-args string
  test arguments
- --test-command-name string
  test command name (default "go test")
- --retries-per-test int
  maximum retries per test
- --total-retries int
  maximum retries for all tests
- --json bool
  parse go test output as json
- --verbose bool
  verbose mode

**Return values**:
- `0`: if all tests that failed during any run are successfuly retried
- `1`: for unexpected error
- `*`: whateve was returned by last run otherwise

<br>
26 changes: 26 additions & 0 deletions buffer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package retryer

import (
"bytes"
"sync"
)

type buffer struct {
buffer bytes.Buffer
locker sync.Mutex
}

func (b *buffer) Read(p []byte) (n int, err error) {
return b.buffer.Read(p)
}

func (b *buffer) Write(p []byte) (n int, err error) {
b.locker.Lock()
n, err = b.buffer.Write(p)
b.locker.Unlock()
return
}

func (b *buffer) String() string {
return b.buffer.String()
}
33 changes: 33 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"log"
"os"

rt "go-test-retryer"
)

func main() {
errorLogger := log.New(os.Stderr, "", 0)

cfg, err := rt.NewConfigFromArgs(os.Args)
if err != nil {
errorLogger.Println(err)
os.Exit(2)
}

retryer := rt.NewRetryer(cfg, os.Stdout, os.Stderr)

err = retryer.Run()
if _, isTestError := err.(rt.TestError); err != nil && !isTestError {
errorLogger.Println(err)
}
switch err := err.(type) {
case nil:
os.Exit(0)
case rt.TestError:
os.Exit(err.TestExitCode())
default:
os.Exit(1)
}
}
34 changes: 34 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package retryer

import "flag"

type Config struct {
testOutputTypeJSON bool
maxRetriesPerTest int
maxTotalRetries int
testCommandName string
testArgs string
verbose bool
}

func NewConfigFromArgs(args []string) (Config, error) {
cfg := Config{}

flag.BoolVar(&cfg.testOutputTypeJSON, "json", false, "parse go test output as json")
flag.IntVar(&cfg.maxRetriesPerTest, "retries-per-test", 0, "maximum retries per test")
flag.IntVar(&cfg.maxTotalRetries, "total-retries", 0, "maximum retries for all tests")
flag.BoolVar(&cfg.verbose, "verbose", false, "verbose mode")
flag.StringVar(&cfg.testCommandName, "test-command-name", "go test", `test command name`)
flag.StringVar(&cfg.testArgs, "test-args", "", "test arguments")
flag.Parse()

if cfg.maxTotalRetries < 0 || cfg.maxRetriesPerTest < 0 {
return Config{}, InvalidParameterError{"Retries amount should be non-negative"}
}

return cfg, nil
}

func (cfg *Config) isTotalRetriesLimitEnabled() bool {
return cfg.maxTotalRetries != 0
}
16 changes: 16 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package retryer

import "fmt"

type TestError struct {
exitCode int
}

func (err TestError) Error() string { return fmt.Sprintf("exit code: %v", int(err.exitCode)) }
func (err TestError) TestExitCode() int { return int(err.exitCode) }

type InvalidParameterError struct {
message string
}

func (err InvalidParameterError) Error() string { return err.message }
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module go-test-retryer

go 1.22.3

require (
github.com/jstemmer/go-junit-report/v2 v2.1.0
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.9.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
)
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
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/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jstemmer/go-junit-report/v2 v2.1.0 h1:X3+hPYlSczH9IMIpSC9CQSZA0L+BipYafciZUWHEmsc=
github.com/jstemmer/go-junit-report/v2 v2.1.0/go.mod h1:mgHVr7VUo5Tn8OLVr1cKnLuEy0M92wdRntM99h7RkgQ=
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading

0 comments on commit ac1a766

Please sign in to comment.