From 33c72ecaf8be360acf7fcea6d677d451b58b15cb Mon Sep 17 00:00:00 2001 From: sha1n Date: Wed, 7 Jan 2026 21:31:56 +0200 Subject: [PATCH] build & ci improvements * Dockerfile: Rewrote the Dockerfile to use a multi-stage build. The builder stage uses golang:1.24-alpine to compile the binary, and the runtime stage uses alpine:latest, significantly reducing the final image size and improving security. * Makefile: Added all common targets to .PHONY to prevent conflicts with local files/directories. * GitHub Actions: Integrated golangci-lint-action into the CI workflow to enforce code quality and best practice automatically on every push. * Fixed lint issues --- .github/workflows/go.yml | 7 ++- Dockerfile | 20 +++++++- Makefile | 48 +++++++++++++++++-- cmd/main.go | 2 +- internal/cli/abor_on_error_listener.go | 2 +- internal/cli/config_runner.go | 6 ++- internal/cli/config_runner_test.go | 7 ++- internal/cli/input.go | 5 +- internal/cli/main_runner.go | 8 ++-- internal/cli/main_runner_test.go | 25 ++++++---- internal/report/markdown.go | 8 +++- internal/report/md_rawdata_report_writer.go | 4 +- .../report/md_rawdata_report_writer_test.go | 3 +- .../report/md_summary_report_writer_test.go | 3 +- internal/report/text_report_writer.go | 4 +- pkg/exec/benchmark_exec.go | 28 +++++------ pkg/ui/progress_view_listener.go | 2 +- pkg/ui/progress_view_listener_test.go | 3 +- 18 files changed, 129 insertions(+), 56 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 597c602..59a6625 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -17,8 +17,13 @@ jobs: with: go-version: 1.24 + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: latest + - name: Build - run: make lint build + run: make build - name: Test run: | diff --git a/Dockerfile b/Dockerfile index d3cc76a..6f0928b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,23 @@ -FROM golang:1.24 +# Stage 1: Build +FROM golang:1.24-alpine AS builder -ADD . /bert +# Install make and git (required for Makefile and versioning) +RUN apk add --no-cache make git WORKDIR /bert +COPY . . +# Build the linux amd64 binary RUN make go-build-linux-amd64 + +# Stage 2: Runtime +FROM alpine:latest + +RUN apk add --no-cache ca-certificates + +WORKDIR /bert +COPY --from=builder /bert/bin/bert-linux-amd64 /bert/bin/bert-linux-amd64 +COPY --from=builder /bert/test /bert/test + +# Set the binary as the entrypoint +ENTRYPOINT ["/bert/bin/bert-linux-amd64"] diff --git a/Makefile b/Makefile index 39a9205..a0f6d44 100644 --- a/Makefile +++ b/Makefile @@ -36,14 +36,22 @@ PID := $(GOBUILD)/.$(PROJECTNAME).pid # Make is verbose in Linux. Make it silent. MAKEFLAGS += --silent +.PHONY: default default: install lint format test build +## install: Checks for missing dependencies and installs them +.PHONY: install install: go-get +## format: Formats Go source files +.PHONY: format format: go-format -lint: go-lint +## lint: Runs all linters including go vet and golangci-lint +.PHONY: lint +lint: go-lint golangci-lint +## build: Builds binaries for all supported platforms .PHONY: build build: @[ -d $(GOBUILD) ] || mkdir -p $(GOBUILD) @@ -56,84 +64,113 @@ build: bin/bert-$(GOHOSTOS)-$(GOHOSTARCH) completion bash > $(GOBUILD)/completions/bert.bash bin/bert-$(GOHOSTOS)-$(GOHOSTARCH) completion fish > $(GOBUILD)/completions/bert.fish - #@cat $(STDERR) | sed -e '1s/.*/\nError:\n/' | sed 's/make\[.*/ /' | sed "/^/s/^/ /" 1>&2 + #@cat $(STDERR) | sed -e '1s/.*/\nError:\n/' | sed 's/make\[.*\]/ /' | sed "/^/s/^/ /" 1>&2 +## test: Runs all Go tests +.PHONY: test test: install go-test +## clean: Removes build artifacts +.PHONY: clean clean: @-rm $(GOBIN)/$(PROGRAMNAME)* 2> /dev/null @-$(MAKE) go-clean +.PHONY: go-lint go-lint: @echo " > Linting source files..." go vet $(MODFLAGS) -c=10 `go list $(MODFLAGS) ./...` +## golangci-lint: Runs golangci-lint +.PHONY: golangci-lint +golangci-lint: + @echo " > Running golangci-lint..." + golangci-lint run + +.PHONY: go-format go-format: @echo " > Formating source files..." gofmt -s -w $(GOFILES) +.PHONY: go-build-current go-build-current: @echo " > Building $(GOHOSTOS)/$(GOHOSTARCH) binaries..." @GOPATH=$(GOPATH) GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME) $(GOBASE)/cmd +.PHONY: go-build go-build: go-get go-build-linux-amd64 go-build-linux-arm64 go-build-linux-arm go-build-darwin-amd64 go-build-darwin-arm64 go-build-windows-amd64 go-build-windows-arm +.PHONY: go-test go-test: @echo " > Running Go tests..." go test $(MODFLAGS) -covermode=count `go list $(MODFLAGS) ./...` +.PHONY: go-build-linux-amd64 go-build-linux-amd64: @echo " > Building linux amd64 binaries..." @GOPATH=$(GOPATH) GOOS=$(GOOS_LINUX) GOARCH=$(GOARCH_AMD64) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME)-$(GOOS_LINUX)-$(GOARCH_AMD64) $(GOBASE)/cmd +.PHONY: go-build-linux-arm64 go-build-linux-arm64: @echo " > Building linux arm64 binaries..." @GOPATH=$(GOPATH) GOOS=$(GOOS_LINUX) GOARCH=$(GOARCH_ARM64) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME)-$(GOOS_LINUX)-$(GOARCH_ARM64) $(GOBASE)/cmd +.PHONY: go-build-linux-arm go-build-linux-arm: @echo " > Building linux arm binaries..." @GOPATH=$(GOPATH) GOOS=$(GOOS_LINUX) GOARCH=$(GOARCH_ARM) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME)-$(GOOS_LINUX)-$(GOARCH_ARM) $(GOBASE)/cmd +.PHONY: go-build-darwin-amd64 go-build-darwin-amd64: @echo " > Building darwin amd64 binaries..." @GOPATH=$(GOPATH) GOOS=$(GOOS_DARWIN) GOARCH=$(GOARCH_AMD64) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME)-$(GOOS_DARWIN)-$(GOARCH_AMD64) $(GOBASE)/cmd +.PHONY: go-build-darwin-arm64 go-build-darwin-arm64: @echo " > Building darwin arm64 binaries..." @GOPATH=$(GOPATH) GOOS=$(GOOS_DARWIN) GOARCH=$(GOARCH_ARM64) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME)-$(GOOS_DARWIN)-$(GOARCH_ARM64) $(GOBASE)/cmd +.PHONY: go-build-windows-amd64 go-build-windows-amd64: @echo " > Building windows amd64 binaries..." @GOPATH=$(GOPATH) GOOS=$(GOOS_WINDOWS) GOARCH=$(GOARCH_AMD64) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME)-$(GOOS_WINDOWS)-$(GOARCH_AMD64).exe $(GOBASE)/cmd +.PHONY: go-build-windows-arm go-build-windows-arm: @echo " > Building windows arm binaries..." @GOPATH=$(GOPATH) GOOS=$(GOOS_WINDOWS) GOARCH=$(GOARCH_ARM) GOBIN=$(GOBIN) go build $(MODFLAGS) $(LDFLAGS) -o $(GOBIN)/$(PROGRAMNAME)-$(GOOS_WINDOWS)-$(GOARCH_ARM).exe $(GOBASE)/cmd +.PHONY: go-generate go-generate: @echo " > Generating dependency files..." @GOPATH=$(GOPATH) GOBIN=$(GOBIN) go generate $(generate) +.PHONY: go-get go-get: @echo " > Checking if there is any missing dependencies..." @GOPATH=$(GOPATH) GOBIN=$(GOBIN) go mod tidy +.PHONY: go-install go-install: @GOPATH=$(GOPATH) GOBIN=$(GOBIN) go install $(GOFILES) +.PHONY: go-clean go-clean: @echo " > Cleaning build cache" @GOPATH=$(GOPATH) GOBIN=$(GOBIN) go clean $(MODFLAGS) $(GOBASE)/cmd @GOPATH=$(GOPATH) GOBIN=$(GOBIN) go clean -modcache +.PHONY: run-sanity-tests run-sanity-tests: build-docker run-linux-dockerized-tests +.PHONY: build-docker build-docker: @echo " > Building docker image..." docker build -t sha1n/$(PROJECTNAME):latest . docker tag sha1n/$(PROJECTNAME):latest sha1n/$(PROJECTNAME):$(VERSION:v%=%) +.PHONY: run-linux-dockerized-tests run-linux-dockerized-tests: @echo " > Running with experimental UI..." docker run --rm -ti sha1n/bert /bert/bin/bert-linux-amd64 -c /bert/test/data/spec_test_load.yaml @@ -148,6 +185,7 @@ run-linux-dockerized-tests: @echo " > Running with ad-hoc commands..." docker run --rm -ti sha1n/bert /bert/bin/bert-linux-amd64 'ls' 'ls -laH' --executions 10 +.PHONY: release release: ifdef GITHUB_TOKEN @echo " > Releasing..." @@ -156,11 +194,13 @@ else $(error GITHUB_TOKEN is not set) endif -.PHONY: help +.PHONY: all all: help + +.PHONY: help help: Makefile @echo @echo " Choose a command run in "$(PROJECTNAME)":" @echo @sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /' - @echo \ No newline at end of file + @echo diff --git a/cmd/main.go b/cmd/main.go index 3cf0ef0..5b9e5a7 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -66,7 +66,7 @@ func handlePanics(exitFn func(int)) { ) + "&labels=bug" yellow := color.New(color.FgYellow) - yellow.Println("\nOh no... Please kindly report this issue by following this URL:") + _, _ = yellow.Println("\nOh no... Please kindly report this issue by following this URL:") fmt.Printf(` %s diff --git a/internal/cli/abor_on_error_listener.go b/internal/cli/abor_on_error_listener.go index cc33def..85b24b6 100644 --- a/internal/cli/abor_on_error_listener.go +++ b/internal/cli/abor_on_error_listener.go @@ -36,5 +36,5 @@ func NewAbortOnErrorListener(delegate api.Listener) api.Listener { func (l abortOnErrorListener) OnError(id api.ID, err error) { defer panic(NewAbortionError(id, err)) l.Listener.OnError(id, err) - l.Listener.OnScenarioEnd(id) + l.OnScenarioEnd(id) } diff --git a/internal/cli/config_runner.go b/internal/cli/config_runner.go index 46bc229..266aa93 100644 --- a/internal/cli/config_runner.go +++ b/internal/cli/config_runner.go @@ -35,10 +35,12 @@ func runConfigToolFn(ctx api.IOContext) func(*cobra.Command, []string) { configureOutput(cmd, slog.LevelError, ctx) writeCloser := ResolveOutputArg(cmd, ArgNameOutputFile, ctx) - defer writeCloser.Close() + defer func() { + _ = writeCloser.Close() + }() if GetBool(cmd, ArgNameConfigExample) { - io.WriteString(writeCloser, getExampleSpec()) + _, _ = io.WriteString(writeCloser, getExampleSpec()) } else { printHints() diff --git a/internal/cli/config_runner_test.go b/internal/cli/config_runner_test.go index 7722067..08dc4f8 100644 --- a/internal/cli/config_runner_test.go +++ b/internal/cli/config_runner_test.go @@ -3,7 +3,6 @@ package cli import ( "bytes" "fmt" - "io/ioutil" "os" "strings" "testing" @@ -97,7 +96,7 @@ func configureExampleCommandWithOutFile(t *testing.T, ctx api.IOContext) (rootCm rootCmd.SetArgs(args) - return rootCmd, configPath, func() { os.Remove(tmpFile.Name()) } + return rootCmd, configPath, func() { _ = os.Remove(tmpFile.Name()) } } func configureCommand(t *testing.T, ctx api.IOContext) (rootCmd *cobra.Command, configPath string, teardown func()) { @@ -105,12 +104,12 @@ func configureCommand(t *testing.T, ctx api.IOContext) (rootCmd *cobra.Command, cmd := CreateConfigCommand(ctx) rootCmd.AddCommand(cmd) - tmpFile, err := ioutil.TempFile("", "configureCommand") + tmpFile, err := os.CreateTemp("", "configureCommand") assert.NoError(t, err) rootCmd.SetArgs([]string{"config", "--out-file", tmpFile.Name()}) - return rootCmd, tmpFile.Name(), func() { os.Remove(tmpFile.Name()) } + return rootCmd, tmpFile.Name(), func() { _ = os.Remove(tmpFile.Name()) } } func userInput() string { diff --git a/internal/cli/input.go b/internal/cli/input.go index 0345804..794d67c 100644 --- a/internal/cli/input.go +++ b/internal/cli/input.go @@ -54,9 +54,10 @@ func questionYN(prompt string, ctx api.IOContext) bool { displayPrompt() str, _ = reader.ReadString('\n') str = strings.TrimSpace(strings.ToLower(str)) - if str == "y" { + switch str { + case "y": return true - } else if str == "n" || str == "" { + case "n", "": return false } } diff --git a/internal/cli/main_runner.go b/internal/cli/main_runner.go index 8ea3554..68e1526 100644 --- a/internal/cli/main_runner.go +++ b/internal/cli/main_runner.go @@ -114,7 +114,9 @@ func runFn(ctx api.IOContext) func(*cobra.Command, []string) { var reportHandler api.ReportHandler reportHandler, closer, err = resolveReportHandler(cmd, spec, ctx) - defer closer.Close() + defer func() { + _ = closer.Close() + }() if err == nil { tracer := exec.NewTracer(spec.Executions * len(spec.Scenarios)) @@ -215,7 +217,7 @@ func resolveReportHandler(cmd *cobra.Command, spec api.BenchmarkSpec, ctx api.IO handler = reporthandlers.NewSummaryReportHandler(spec, reportCtx, report.NewTextReportWriter(writer, colorsOn)) default: - err = fmt.Errorf("Invalid report format '%s'", reportFormat) + err = fmt.Errorf("invalid report format '%s'", reportFormat) } return handler, writeCloser, err @@ -263,7 +265,7 @@ func enableTerminalGUI(cmd *cobra.Command, ctx api.IOContext) bool { pipeOutputsMode := GetBool(cmd, ArgNamePipeStdout) pipeOutputsMode = pipeOutputsMode || GetBool(cmd, ArgNamePipeStderr) - return ctx.Tty && enableRichOut && !(silentMode || debugMode || pipeOutputsMode) + return ctx.Tty && enableRichOut && !silentMode && !debugMode && !pipeOutputsMode } func terminalDimensionsOrFake() (int, int) { diff --git a/internal/cli/main_runner_test.go b/internal/cli/main_runner_test.go index 68cb7d1..31e3e76 100644 --- a/internal/cli/main_runner_test.go +++ b/internal/cli/main_runner_test.go @@ -11,7 +11,6 @@ import ( "github.com/sha1n/bert/api" "github.com/sha1n/bert/pkg/specs" - "github.com/sha1n/gommons/pkg/test" gommonstest "github.com/sha1n/gommons/pkg/test" "github.com/spf13/cobra" "github.com/stretchr/testify/assert" @@ -97,8 +96,10 @@ func TestWithMissingConfigFile(t *testing.T) { func TestWithWDConfigFile(t *testing.T) { wd, _ := os.Getwd() - os.Chdir("../../test/data") // expecting '../../test/data/.bertconfig' to be loaded - defer os.Chdir(wd) + _ = os.Chdir("../../test/data") // expecting '../../test/data/.bertconfig' to be loaded + defer func() { + _ = os.Chdir(wd) + }() expectedSpec, _ := specs.LoadSpec(itConfigFilePath) expectedSpec.Executions = 1 @@ -113,8 +114,10 @@ func TestWithWDConfigFile(t *testing.T) { func TestWithWDConfigFileAndExecutionsOptionOverride(t *testing.T) { wd, _ := os.Getwd() - os.Chdir("../../test/data") // expecting '../../test/data/.bertconfig' to be loaded - defer os.Chdir(wd) + _ = os.Chdir("../../test/data") // expecting '../../test/data/.bertconfig' to be loaded + defer func() { + _ = os.Chdir(wd) + }() expectedSpec, _ := specs.LoadSpec(itConfigFilePath) expectedSpec.Executions = expectedSpec.Executions + rand.Intn(10) @@ -129,8 +132,10 @@ func TestWithWDConfigFileAndExecutionsOptionOverride(t *testing.T) { func TestWithWDConfigFileAndAlternateOptionOverride(t *testing.T) { wd, _ := os.Getwd() - os.Chdir("../../test/data") // expecting '../../test/data/.bertconfig' to be loaded - defer os.Chdir(wd) + _ = os.Chdir("../../test/data") // expecting '../../test/data/.bertconfig' to be loaded + defer func() { + _ = os.Chdir(wd) + }() expectedSpec, _ := specs.LoadSpec(itConfigFilePath) expectedSpec.Executions = 1 @@ -257,7 +262,7 @@ func Test_validatePositionalArgs(t *testing.T) { name: "call with positional and no executions param", args: args{ cmd: newDummyCommandWith("-c", "/some-file"), - args: []string{test.RandomString(), test.RandomString()}, + args: []string{gommonstest.RandomString(), gommonstest.RandomString()}, }, wantErr: true, }, @@ -265,7 +270,7 @@ func Test_validatePositionalArgs(t *testing.T) { name: "call with positional and invalid executions param", args: args{ cmd: newDummyCommandWith("--executions", "-1"), - args: []string{test.RandomString(), test.RandomString()}, + args: []string{gommonstest.RandomString(), gommonstest.RandomString()}, }, wantErr: true, }, @@ -273,7 +278,7 @@ func Test_validatePositionalArgs(t *testing.T) { name: "call with positional and valid executions param", args: args{ cmd: newDummyCommandWith("--executions", "100"), - args: []string{test.RandomString(), test.RandomString()}, + args: []string{gommonstest.RandomString(), gommonstest.RandomString()}, }, wantErr: false, }, diff --git a/internal/report/markdown.go b/internal/report/markdown.go index 67be41d..17233be 100644 --- a/internal/report/markdown.go +++ b/internal/report/markdown.go @@ -26,7 +26,9 @@ func NewMarkdownTableWriter(writer io.Writer) MarkdownTableWriter { // WriteHeaders writes table headers line func (tw MarkdownTableWriter) WriteHeaders(headers []string) (err error) { - defer tw.writer.Flush() + defer func() { + _ = tw.writer.Flush() + }() if err = tw.WriteRow(headers); err == nil { err = tw.writeString(fmt.Sprintf("%s|\r\n", strings.Repeat("|----", len(headers)))) } @@ -37,7 +39,9 @@ func (tw MarkdownTableWriter) WriteHeaders(headers []string) (err error) { // WriteRow writes a row line func (tw MarkdownTableWriter) WriteRow(row []string) (err error) { // TODO theoretically we need to escape '|' chars - defer tw.writer.Flush() + defer func() { + _ = tw.writer.Flush() + }() return tw.writeString(fmt.Sprintf("|%s|\r\n", strings.Join(row, "|"))) } diff --git a/internal/report/md_rawdata_report_writer.go b/internal/report/md_rawdata_report_writer.go index 9a9a076..fa94b4a 100644 --- a/internal/report/md_rawdata_report_writer.go +++ b/internal/report/md_rawdata_report_writer.go @@ -35,7 +35,7 @@ func NewMarkdownStreamReportWriter(writer io.Writer, ctx api.ReportContext) RawD // Handle handles a real time trace event func (rw *MarkdownStreamReportWriter) Handle(trace api.Trace) (err error) { - _, err = rw.writer.WriteString(fmt.Sprintf("| %s | %s | %s | %s | %s | %s | %t |\n", + _, err = fmt.Fprintf(rw.writer, "| %s | %s | %s | %s | %s | %s | %t |\n", FormatDateTime(time.Now(), rw.ctx), trace.ID(), strings.Join(rw.ctx.Labels, ","), @@ -43,7 +43,7 @@ func (rw *MarkdownStreamReportWriter) Handle(trace api.Trace) (err error) { FormatReportDuration(func() (time.Duration, error) { return trace.UserCPUTime(), nil }), FormatReportDuration(func() (time.Duration, error) { return trace.SystemCPUTime(), nil }), trace.Error() != nil, - )) + ) if err == nil { err = rw.writer.Flush() diff --git a/internal/report/md_rawdata_report_writer_test.go b/internal/report/md_rawdata_report_writer_test.go index 398f0ec..d6d1399 100644 --- a/internal/report/md_rawdata_report_writer_test.go +++ b/internal/report/md_rawdata_report_writer_test.go @@ -3,7 +3,6 @@ package report import ( "fmt" "io" - "io/ioutil" "strings" "testing" "time" @@ -50,7 +49,7 @@ func writeMdRawReport(t *testing.T, includeHeaders bool, traces ...api.Trace) [] readRecords := func(r io.Reader) (records [][]string, err error) { records = make([][]string, expectedRows) var mdBytes []byte - if mdBytes, err = ioutil.ReadAll(r); err == nil { + if mdBytes, err = io.ReadAll(r); err == nil { lines := strings.Split(strings.TrimSpace(string(mdBytes)), "\n") for i, line := range lines { line = strings.Trim(line, "|") diff --git a/internal/report/md_summary_report_writer_test.go b/internal/report/md_summary_report_writer_test.go index 4f09605..9646296 100644 --- a/internal/report/md_summary_report_writer_test.go +++ b/internal/report/md_summary_report_writer_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/sha1n/bert/api" - "github.com/sha1n/gommons/pkg/test" gommonstest "github.com/sha1n/gommons/pkg/test" "github.com/stretchr/testify/assert" ) @@ -74,7 +73,7 @@ func generateTestMdReport(t *testing.T, includeHeaders bool) ([]string, api.Summ func aTwoScenarioSpec() api.BenchmarkSpec { return api.BenchmarkSpec{ - Executions: int(test.RandomUint()), + Executions: int(gommonstest.RandomUint()), Scenarios: []api.ScenarioSpec{ { Name: gommonstest.RandomString(), diff --git a/internal/report/text_report_writer.go b/internal/report/text_report_writer.go index 531a33d..09fdbb2 100644 --- a/internal/report/text_report_writer.go +++ b/internal/report/text_report_writer.go @@ -71,7 +71,9 @@ func NewTextReportWriter(writer io.Writer, colorsOn bool) api.WriteSummaryReport } func (trw textReportWriter) Write(summary api.Summary, config api.BenchmarkSpec, ctx api.ReportContext) (err error) { - defer trw.writer.Flush() + defer func() { + _ = trw.writer.Flush() + }() trw.writeNewLine() trw.writeTitle(" BENCHMARK SUMMARY") diff --git a/pkg/exec/benchmark_exec.go b/pkg/exec/benchmark_exec.go index 83e3ecc..430a12f 100644 --- a/pkg/exec/benchmark_exec.go +++ b/pkg/exec/benchmark_exec.go @@ -8,8 +8,8 @@ import ( // Execute executes a benchmark and returns an object that provides access to collected stats. func Execute(ctx context.Context, spec api.BenchmarkSpec, execCtx api.ExecutionContext) { - execCtx.Listener.OnBenchmarkStart() - defer execCtx.Listener.OnBenchmarkEnd() + execCtx.OnBenchmarkStart() + defer execCtx.OnBenchmarkEnd() if spec.Alternate { executeAlternately(ctx, spec, execCtx) @@ -27,7 +27,7 @@ func executeAlternately(ctx context.Context, spec api.BenchmarkSpec, execCtx api scenario := spec.Scenarios[si] - execCtx.Listener.OnScenarioStart(scenario.ID()) + execCtx.OnScenarioStart(scenario.ID()) if i == 1 { executeScenarioSetup(ctx, scenario, execCtx) } @@ -36,7 +36,7 @@ func executeAlternately(ctx context.Context, spec api.BenchmarkSpec, execCtx api executeScenarioTeardown(ctx, scenario, execCtx) } - execCtx.Listener.OnScenarioEnd(scenario.ID()) + execCtx.OnScenarioEnd(scenario.ID()) } } } @@ -50,7 +50,7 @@ func executeSequentially(ctx context.Context, spec api.BenchmarkSpec, execCtx ap return } - execCtx.Listener.OnScenarioStart(scenario.ID()) + execCtx.OnScenarioStart(scenario.ID()) if i == 1 { executeScenarioSetup(ctx, scenario, execCtx) } @@ -60,33 +60,33 @@ func executeSequentially(ctx context.Context, spec api.BenchmarkSpec, execCtx ap if i == spec.Executions { executeScenarioTeardown(ctx, scenario, execCtx) } - execCtx.Listener.OnScenarioEnd(scenario.ID()) + execCtx.OnScenarioEnd(scenario.ID()) } } } func executeScenarioSetup(ctx context.Context, scenario api.ScenarioSpec, execCtx api.ExecutionContext) { if scenario.BeforeAll != nil { - execCtx.Listener.OnMessagef(scenario.ID(), "running 'beforeAll' command %v...", scenario.BeforeAll.Cmd) + execCtx.OnMessagef(scenario.ID(), "running 'beforeAll' command %v...", scenario.BeforeAll.Cmd) reportIfExecError(execCtx.Executor.ExecuteFn(ctx, scenario.BeforeAll, scenario.WorkingDirectory, scenario.Env), scenario.ID(), execCtx) } } func executeScenarioTeardown(ctx context.Context, scenario api.ScenarioSpec, execCtx api.ExecutionContext) { if scenario.AfterAll != nil { - execCtx.Listener.OnMessagef(scenario.ID(), "running 'afterAll' command %v...", scenario.AfterAll.Cmd) + execCtx.OnMessagef(scenario.ID(), "running 'afterAll' command %v...", scenario.AfterAll.Cmd) reportIfExecError(execCtx.Executor.ExecuteFn(ctx, scenario.AfterAll, scenario.WorkingDirectory, scenario.Env), scenario.ID(), execCtx) } } func executeScenarioCommand(ctx context.Context, scenario api.ScenarioSpec, execIndex int, totalExec int, execCtx api.ExecutionContext) { - execCtx.Listener.OnMessagef(scenario.ID(), "run %d of %d", execIndex, totalExec) + execCtx.OnMessagef(scenario.ID(), "run %d of %d", execIndex, totalExec) if scenario.BeforeEach != nil { - execCtx.Listener.OnMessagef(scenario.ID(), "running 'beforeEach' command %v", scenario.BeforeEach.Cmd) + execCtx.OnMessagef(scenario.ID(), "running 'beforeEach' command %v", scenario.BeforeEach.Cmd) reportIfExecError(execCtx.Executor.ExecuteFn(ctx, scenario.BeforeEach, scenario.WorkingDirectory, scenario.Env), scenario.ID(), execCtx) } - execCtx.Listener.OnMessagef(scenario.ID(), "running benchmark command %v", scenario.Command.Cmd) + execCtx.OnMessagef(scenario.ID(), "running benchmark command %v", scenario.Command.Cmd) executeFn := execCtx.Executor.ExecuteFn(ctx, scenario.Command, scenario.WorkingDirectory, scenario.Env) endTrace := execCtx.Tracer.Start(scenario) @@ -96,19 +96,19 @@ func executeScenarioCommand(ctx context.Context, scenario api.ScenarioSpec, exec reportIfError(err, scenario.ID(), execCtx) if scenario.AfterEach != nil { - execCtx.Listener.OnMessagef(scenario.ID(), "running 'afterEach' command %v", scenario.AfterEach.Cmd) + execCtx.OnMessagef(scenario.ID(), "running 'afterEach' command %v", scenario.AfterEach.Cmd) reportIfExecError(execCtx.Executor.ExecuteFn(ctx, scenario.AfterEach, scenario.WorkingDirectory, scenario.Env), scenario.ID(), execCtx) } } func reportIfError(err error, id api.ID, ctx api.ExecutionContext) { if err != nil { - ctx.Listener.OnError(id, err) + ctx.OnError(id, err) } } func reportIfExecError(exec api.ExecCommandFn, id api.ID, ctx api.ExecutionContext) { if _, err := exec(); err != nil { - ctx.Listener.OnError(id, err) + ctx.OnError(id, err) } } diff --git a/pkg/ui/progress_view_listener.go b/pkg/ui/progress_view_listener.go index 14926bc..0b3158a 100644 --- a/pkg/ui/progress_view_listener.go +++ b/pkg/ui/progress_view_listener.go @@ -68,7 +68,7 @@ func NewProgressView(spec api.BenchmarkSpec, termDimensionsFn func() (int, int), return w } if len(rows)+1 > termHeight { - yellow.Printf("Your terminal window is too small to dispaly full progress information...\n\n") + _, _ = yellow.Printf("Your terminal window is too small to dispaly full progress information...\n\n") return NewMinimalProgressView(spec, termDimensionsFn, ioc) } diff --git a/pkg/ui/progress_view_listener_test.go b/pkg/ui/progress_view_listener_test.go index 6cc16be..bfcb948 100644 --- a/pkg/ui/progress_view_listener_test.go +++ b/pkg/ui/progress_view_listener_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/sha1n/bert/api" - "github.com/sha1n/gommons/pkg/test" gommonstest "github.com/sha1n/gommons/pkg/test" "github.com/stretchr/testify/assert" ) @@ -161,7 +160,7 @@ func aSpec(alternate bool, executions int) api.BenchmarkSpec { Alternate: alternate, Scenarios: []api.ScenarioSpec{ { - Name: test.RandomString(), + Name: gommonstest.RandomString(), Command: &api.CommandSpec{ Cmd: []string{"cmd"}, },