Merge pull request #325 from jesseduffield/use-github-actions

This commit is contained in:
Jesse Duffield 2022-05-09 21:42:54 +10:00 committed by GitHub
commit 31435c68f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 251 additions and 93 deletions

31
.github/workflows/cd.yml vendored Normal file
View file

@ -0,0 +1,31 @@
name: Continuous Delivery
on:
push:
tags:
- 'v*'
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Unshallow repo
run: git fetch --prune --unshallow
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.18.x
- name: Run goreleaser
uses: goreleaser/goreleaser-action@v1
env:
GITHUB_TOKEN: ${{secrets.API_TOKEN}}
homebrew:
runs-on: ubuntu-latest
steps:
- name: Bump Homebrew formula
uses: dawidd6/action-homebrew-bump-formula@v3
with:
token: ${{secrets.API_TOKEN}}
formula: lazydocker

99
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,99 @@
name: Continuous Integration
env:
GO_VERSION: 1.18
on:
push:
branches:
- master
pull_request:
jobs:
ci:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
name: ci - ${{matrix.os}}
runs-on: ${{matrix.os}}
env:
GOFLAGS: -mod=vendor
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.18.x
- name: Cache build
uses: actions/cache@v1
with:
path: ~/.cache/go-build
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
restore-keys: |
${{runner.os}}-go-
- name: Test code
run: |
bash ./test.sh
build:
runs-on: ubuntu-latest
env:
GOFLAGS: -mod=vendor
GOARCH: amd64
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.18.x
- name: Cache build
uses: actions/cache@v1
with:
path: ~/.cache/go-build
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-build
restore-keys: |
${{runner.os}}-go-
- name: Build linux binary
run: |
GOOS=linux go build
- name: Build windows binary
run: |
GOOS=windows go build
- name: Build darwin binary
run: |
GOOS=darwin go build
lint:
runs-on: ubuntu-latest
env:
GOFLAGS: -mod=vendor
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.18.x
- name: Cache build
uses: actions/cache@v1
with:
path: ~/.cache/go-build
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
restore-keys: |
${{runner.os}}-go-
- name: Lint
uses: golangci/golangci-lint-action@v3.1.0
with:
version: latest
- name: Format code
run: |
if [ $(find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \;|wc -l) -gt 0 ]; then
find . ! -path "./vendor/*" -name "*.go" -exec gofmt -s -d {} \;
exit 1
fi
- name: errors
run: golangci-lint run
if: ${{ failure() }}

29
.golangci.yml Normal file
View file

@ -0,0 +1,29 @@
linters:
disable:
- structcheck # gives false positives
enable:
- gofumpt
- thelper
- goimports
- tparallel
- wastedassign
- exportloopref
- unparam
- prealloc
- unconvert
- exhaustive
- makezero
- nakedret
# - goconst # TODO: enable and fix issues
fast: false
linters-settings:
exhaustive:
default-signifies-exhaustive: true
nakedret:
# the gods will judge me but I just don't like naked returns at all
max-func-lines: 0
run:
go: 1.18

View file

@ -83,13 +83,11 @@ type Details struct {
Binds []string `json:"Binds"` Binds []string `json:"Binds"`
ContainerIDFile string `json:"ContainerIDFile"` ContainerIDFile string `json:"ContainerIDFile"`
LogConfig struct { LogConfig struct {
Type string `json:"Type"` Type string `json:"Type"`
Config struct { Config struct{} `json:"Config"`
} `json:"Config"`
} `json:"LogConfig"` } `json:"LogConfig"`
NetworkMode string `json:"NetworkMode"` NetworkMode string `json:"NetworkMode"`
PortBindings struct { PortBindings struct{} `json:"PortBindings"`
} `json:"PortBindings"`
RestartPolicy struct { RestartPolicy struct {
Name string `json:"Name"` Name string `json:"Name"`
MaximumRetryCount int `json:"MaximumRetryCount"` MaximumRetryCount int `json:"MaximumRetryCount"`
@ -185,10 +183,8 @@ type Details struct {
Cmd []string `json:"Cmd"` Cmd []string `json:"Cmd"`
Image string `json:"Image"` Image string `json:"Image"`
Volumes struct { Volumes struct {
APIBundle struct { APIBundle struct{} `json:"/api-bundle"`
} `json:"/api-bundle"` App struct{} `json:"/app"`
App struct {
} `json:"/app"`
} `json:"Volumes"` } `json:"Volumes"`
WorkingDir string `json:"WorkingDir"` WorkingDir string `json:"WorkingDir"`
Entrypoint interface{} `json:"Entrypoint"` Entrypoint interface{} `json:"Entrypoint"`

View file

@ -56,10 +56,9 @@ type ContainerStats struct {
IoTimeRecursive []interface{} `json:"io_time_recursive"` IoTimeRecursive []interface{} `json:"io_time_recursive"`
SectorsRecursive []interface{} `json:"sectors_recursive"` SectorsRecursive []interface{} `json:"sectors_recursive"`
} `json:"blkio_stats"` } `json:"blkio_stats"`
NumProcs int `json:"num_procs"` NumProcs int `json:"num_procs"`
StorageStats struct { StorageStats struct{} `json:"storage_stats"`
} `json:"storage_stats"` CPUStats struct {
CPUStats struct {
CPUUsage struct { CPUUsage struct {
TotalUsage int64 `json:"total_usage"` TotalUsage int64 `json:"total_usage"`
PercpuUsage []int64 `json:"percpu_usage"` PercpuUsage []int64 `json:"percpu_usage"`
@ -161,7 +160,6 @@ func (s *ContainerStats) CalculateContainerCPUPercentage() float64 {
// CalculateContainerMemoryUsage calculates the memory usage of the container as a percent of total available memory // CalculateContainerMemoryUsage calculates the memory usage of the container as a percent of total available memory
func (s *ContainerStats) CalculateContainerMemoryUsage() float64 { func (s *ContainerStats) CalculateContainerMemoryUsage() float64 {
value := float64(s.MemoryStats.Usage*100) / float64(s.MemoryStats.Limit) value := float64(s.MemoryStats.Usage*100) / float64(s.MemoryStats.Limit)
if math.IsNaN(value) { if math.IsNaN(value) {
return 0 return 0

View file

@ -68,7 +68,7 @@ type CommandObject struct {
// NewCommandObject takes a command object and returns a default command object with the passed command object merged in // NewCommandObject takes a command object and returns a default command object with the passed command object merged in
func (c *DockerCommand) NewCommandObject(obj CommandObject) CommandObject { func (c *DockerCommand) NewCommandObject(obj CommandObject) CommandObject {
defaultObj := CommandObject{DockerCompose: c.Config.UserConfig.CommandTemplates.DockerCompose} defaultObj := CommandObject{DockerCompose: c.Config.UserConfig.CommandTemplates.DockerCompose}
mergo.Merge(&defaultObj, obj) _ = mergo.Merge(&defaultObj, obj)
return defaultObj return defaultObj
} }
@ -139,7 +139,7 @@ func (c *DockerCommand) MonitorCLIContainerStats() {
return return
} }
cmd.Start() _ = cmd.Start()
scanner := bufio.NewScanner(r) scanner := bufio.NewScanner(r)
scanner.Split(bufio.ScanLines) scanner.Split(bufio.ScanLines)
@ -160,7 +160,7 @@ func (c *DockerCommand) MonitorCLIContainerStats() {
c.ContainerMutex.Unlock() c.ContainerMutex.Unlock()
} }
cmd.Wait() _ = cmd.Wait()
} }
// MonitorClientContainerStats is a function // MonitorClientContainerStats is a function
@ -192,7 +192,7 @@ func (c *DockerCommand) createClientStatMonitor(container *Container) {
for scanner.Scan() { for scanner.Scan() {
data := scanner.Bytes() data := scanner.Bytes()
var stats ContainerStats var stats ContainerStats
json.Unmarshal(data, &stats) _ = json.Unmarshal(data, &stats)
recordedStats := RecordedStats{ recordedStats := RecordedStats{
ClientStats: stats, ClientStats: stats,

View file

@ -2,9 +2,10 @@ package commands
import ( import (
"context" "context"
"github.com/docker/docker/api/types/image"
"strings" "strings"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client" "github.com/docker/docker/client"
@ -27,7 +28,6 @@ type Image struct {
// GetDisplayStrings returns the display string of Image // GetDisplayStrings returns the display string of Image
func (i *Image) GetDisplayStrings(isFocused bool) []string { func (i *Image) GetDisplayStrings(isFocused bool) []string {
return []string{i.Name, i.Tag, utils.FormatDecimalBytes(int(i.Image.Size))} return []string{i.Name, i.Tag, utils.FormatDecimalBytes(int(i.Image.Size))}
} }
@ -87,7 +87,6 @@ func (l *Layer) GetDisplayStrings(isFocused bool) []string {
// RenderHistory renders the history of the image // RenderHistory renders the history of the image
func (i *Image) RenderHistory() (string, error) { func (i *Image) RenderHistory() (string, error) {
history, err := i.Client.ImageHistory(context.Background(), i.ID) history, err := i.Client.ImageHistory(context.Background(), i.ID)
if err != nil { if err != nil {
return "", err return "", err

View file

@ -190,7 +190,7 @@ func (c *OSCommand) Unquote(message string) string {
// AppendLineToFile adds a new line in file // AppendLineToFile adds a new line in file
func (c *OSCommand) AppendLineToFile(filename, line string) error { func (c *OSCommand) AppendLineToFile(filename, line string) error {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600)
if err != nil { if err != nil {
return WrapError(err) return WrapError(err)
} }
@ -272,7 +272,6 @@ func (c *OSCommand) RunCustomCommand(command string) *exec.Cmd {
// PipeCommands runs a heap of commands and pipes their inputs/outputs together like A | B | C // PipeCommands runs a heap of commands and pipes their inputs/outputs together like A | B | C
func (c *OSCommand) PipeCommands(commandStrings ...string) error { func (c *OSCommand) PipeCommands(commandStrings ...string) error {
cmds := make([]*exec.Cmd, len(commandStrings)) cmds := make([]*exec.Cmd, len(commandStrings))
for i, str := range commandStrings { for i, str := range commandStrings {

View file

@ -169,6 +169,8 @@ func TestOSCommandQuoteSingleQuote(t *testing.T) {
osCommand := NewDummyOSCommand() osCommand := NewDummyOSCommand()
osCommand.Platform.os = "linux" osCommand.Platform.os = "linux"
osCommand.Platform.fallbackEscapedQuote = "\""
osCommand.Platform.escapedQuote = "'"
actual := osCommand.Quote("hello 'test'") actual := osCommand.Quote("hello 'test'")
@ -235,7 +237,7 @@ func TestOSCommandFileType(t *testing.T) {
{ {
"testDirectory", "testDirectory",
func() { func() {
if err := os.Mkdir("testDirectory", 0644); err != nil { if err := os.Mkdir("testDirectory", 0o644); err != nil {
panic(err) panic(err)
} }
}, },

View file

@ -23,7 +23,6 @@ type Service struct {
// GetDisplayStrings returns the dispaly string of Container // GetDisplayStrings returns the dispaly string of Container
func (s *Service) GetDisplayStrings(isFocused bool) []string { func (s *Service) GetDisplayStrings(isFocused bool) []string {
if s.Container == nil { if s.Container == nil {
return []string{utils.ColoredString("none", color.FgBlue), "", s.Name, ""} return []string{utils.ColoredString("none", color.FgBlue), "", s.Name, ""}
} }

View file

@ -1,10 +1,11 @@
package commands package commands
import ( import (
"testing"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/jesseduffield/lazydocker/pkg/config" "github.com/jesseduffield/lazydocker/pkg/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
func sampleContainers(userConfig *config.AppConfig) []*Container { func sampleContainers(userConfig *config.AppConfig) []*Container {
@ -119,6 +120,7 @@ func expectedLegacySortedContainers(appConfig *config.AppConfig) []*Container {
} }
func assertEqualContainers(t *testing.T, left *Container, right *Container) { func assertEqualContainers(t *testing.T, left *Container, right *Container) {
t.Helper()
assert.Equal(t, left.Container.State, right.Container.State) assert.Equal(t, left.Container.State, right.Container.State)
assert.Equal(t, left.Container.ID, right.Container.ID) assert.Equal(t, left.Container.ID, right.Container.ID)
assert.Equal(t, left.Name, right.Name) assert.Equal(t, left.Name, right.Name)

View file

@ -10,7 +10,6 @@ import (
func TestDockerComposeCommandNoFiles(t *testing.T) { func TestDockerComposeCommandNoFiles(t *testing.T) {
composeFiles := []string{} composeFiles := []string{}
conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir") conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir")
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %s", err) t.Fatalf("Unexpected error: %s", err)
} }
@ -25,7 +24,6 @@ func TestDockerComposeCommandNoFiles(t *testing.T) {
func TestDockerComposeCommandSingleFile(t *testing.T) { func TestDockerComposeCommandSingleFile(t *testing.T) {
composeFiles := []string{"one.yml"} composeFiles := []string{"one.yml"}
conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir") conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir")
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %s", err) t.Fatalf("Unexpected error: %s", err)
} }
@ -40,7 +38,6 @@ func TestDockerComposeCommandSingleFile(t *testing.T) {
func TestDockerComposeCommandMultipleFiles(t *testing.T) { func TestDockerComposeCommandMultipleFiles(t *testing.T) {
composeFiles := []string{"one.yml", "two.yml", "three.yml"} composeFiles := []string{"one.yml", "two.yml", "three.yml"}
conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir") conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir")
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %s", err) t.Fatalf("Unexpected error: %s", err)
} }
@ -53,14 +50,15 @@ func TestDockerComposeCommandMultipleFiles(t *testing.T) {
} }
func TestWritingToConfigFile(t *testing.T) { func TestWritingToConfigFile(t *testing.T) {
//init the AppConfig // init the AppConfig
emptyComposeFiles := []string{} emptyComposeFiles := []string{}
conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, emptyComposeFiles, "projectDir") conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, emptyComposeFiles, "projectDir")
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %s", err) t.Fatalf("Unexpected error: %s", err)
} }
testFn := func(ac *AppConfig, newValue bool, t *testing.T) { testFn := func(t *testing.T, ac *AppConfig, newValue bool) {
t.Helper()
updateFn := func(uc *UserConfig) error { updateFn := func(uc *UserConfig) error {
uc.ConfirmOnQuit = newValue uc.ConfirmOnQuit = newValue
return nil return nil
@ -71,7 +69,7 @@ func TestWritingToConfigFile(t *testing.T) {
t.Fatalf("Unexpected error: %s", err) t.Fatalf("Unexpected error: %s", err)
} }
file, err := os.OpenFile(ac.ConfigFilename(), os.O_RDONLY, 0660) file, err := os.OpenFile(ac.ConfigFilename(), os.O_RDONLY, 0o660)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %s", err) t.Fatalf("Unexpected error: %s", err)
} }
@ -93,8 +91,8 @@ func TestWritingToConfigFile(t *testing.T) {
} }
// insert value into an empty file // insert value into an empty file
testFn(conf, true, t) testFn(t, conf, true)
// modifying an existing file that already has 'ConfirmOnQuit' // modifying an existing file that already has 'ConfirmOnQuit'
testFn(conf, false, t) testFn(t, conf, false)
} }

View file

@ -90,9 +90,11 @@ func (gui *Gui) prepareConfirmationPanel(currentView *gocui.View, title, prompt
} }
func (gui *Gui) onNewPopupPanel() { func (gui *Gui) onNewPopupPanel() {
viewNames := []string{"commitMessage", viewNames := []string{
"commitMessage",
"credentials", "credentials",
"menu"} "menu",
}
for _, viewName := range viewNames { for _, viewName := range viewNames {
_, _ = gui.g.SetViewOnBottom(viewName) _, _ = gui.g.SetViewOnBottom(viewName)
} }

View file

@ -120,7 +120,7 @@ func (gui *Gui) renderContainerEnv(container *commands.Container) error {
} }
} }
return gui.T.NewTask(func(stop chan struct{}) { return gui.T.NewTask(func(stop chan struct{}) {
gui.renderString(gui.g, "main", renderedTable) _ = gui.renderString(gui.g, "main", renderedTable)
}) })
} }
@ -170,7 +170,7 @@ func (gui *Gui) renderContainerConfig(container *commands.Container) error {
output += fmt.Sprintf("\nFull details:\n\n%s", string(data)) output += fmt.Sprintf("\nFull details:\n\n%s", string(data))
return gui.T.NewTask(func(stop chan struct{}) { return gui.T.NewTask(func(stop chan struct{}) {
gui.renderString(gui.g, "main", output) _ = gui.renderString(gui.g, "main", output)
}) })
} }
@ -184,10 +184,10 @@ func (gui *Gui) renderContainerStats(container *commands.Container) error {
contents, err := container.RenderStats(width) contents, err := container.RenderStats(width)
if err != nil { if err != nil {
gui.createErrorPanel(gui.g, err.Error()) _ = gui.createErrorPanel(gui.g, err.Error())
} }
gui.reRenderString(gui.g, "main", contents) _ = gui.reRenderString(gui.g, "main", contents)
}) })
} }
@ -199,10 +199,10 @@ func (gui *Gui) renderContainerTop(container *commands.Container) error {
return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) { return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) {
contents, err := container.RenderTop() contents, err := container.RenderTop()
if err != nil { if err != nil {
gui.reRenderString(gui.g, "main", err.Error()) _ = gui.reRenderString(gui.g, "main", err.Error())
} }
gui.reRenderString(gui.g, "main", contents) _ = gui.reRenderString(gui.g, "main", contents)
}) })
} }
@ -234,7 +234,7 @@ func (gui *Gui) renderContainerLogsAux(container *commands.Container, stop, noti
cmd.Stdout = mainView cmd.Stdout = mainView
cmd.Stderr = mainView cmd.Stderr = mainView
cmd.Start() _ = cmd.Start()
go func() { go func() {
<-stop <-stop
@ -245,7 +245,7 @@ func (gui *Gui) renderContainerLogsAux(container *commands.Container, stop, noti
return return
}() }()
cmd.Wait() _ = cmd.Wait()
// if we are here because the task has been stopped, we should return // if we are here because the task has been stopped, we should return
// if we are here then the container must have exited, meaning we should wait until it's back again before // if we are here then the container must have exited, meaning we should wait until it's back again before
@ -389,7 +389,7 @@ func (gui *Gui) handleContainersNextContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Containers.ContextIndex++ gui.State.Panels.Containers.ContextIndex++
} }
gui.handleContainerSelect(gui.g, v) _ = gui.handleContainerSelect(gui.g, v)
return nil return nil
} }
@ -402,7 +402,7 @@ func (gui *Gui) handleContainersPrevContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Containers.ContextIndex-- gui.State.Panels.Containers.ContextIndex--
} }
gui.handleContainerSelect(gui.g, v) _ = gui.handleContainerSelect(gui.g, v)
return nil return nil
} }

View file

@ -93,7 +93,7 @@ func (gui *Gui) renderImageConfig(mainView *gocui.View, image *commands.Image) e
mainView.Autoscroll = false mainView.Autoscroll = false
mainView.Wrap = false // don't care what your config is this page is ugly without wrapping mainView.Wrap = false // don't care what your config is this page is ugly without wrapping
gui.renderString(gui.g, "main", output) _ = gui.renderString(gui.g, "main", output)
}) })
} }
@ -174,7 +174,7 @@ func (gui *Gui) handleImagesNextContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Images.ContextIndex++ gui.State.Panels.Images.ContextIndex++
} }
gui.handleImageSelect(gui.g, v) _ = gui.handleImageSelect(gui.g, v)
return nil return nil
} }
@ -187,7 +187,7 @@ func (gui *Gui) handleImagesPrevContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Images.ContextIndex-- gui.State.Panels.Images.ContextIndex--
} }
gui.handleImageSelect(gui.g, v) _ = gui.handleImageSelect(gui.g, v)
return nil return nil
} }

View file

@ -152,7 +152,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
} }
_, _ = g.SetViewOnBottom("limit") _, _ = g.SetViewOnBottom("limit")
g.DeleteView("limit") _ = g.DeleteView("limit")
v, err := g.SetView("main", leftSideWidth+1, 0, width-1, height-2, gocui.LEFT) v, err := g.SetView("main", leftSideWidth+1, 0, width-1, height-2, gocui.LEFT)
if err != nil { if err != nil {

View file

@ -9,9 +9,7 @@ import (
) )
func (gui *Gui) getBindings(v *gocui.View) []*Binding { func (gui *Gui) getBindings(v *gocui.View) []*Binding {
var ( var bindingsGlobal, bindingsPanel []*Binding
bindingsGlobal, bindingsPanel []*Binding
)
bindings := gui.GetInitialKeybindings() bindings := gui.GetInitialKeybindings()

View file

@ -108,7 +108,7 @@ func (gui *Gui) renderCredits() error {
mainView.Wrap = gui.Config.UserConfig.Gui.WrapMainPanel mainView.Wrap = gui.Config.UserConfig.Gui.WrapMainPanel
var configBuf bytes.Buffer var configBuf bytes.Buffer
yaml.NewEncoder(&configBuf, yaml.IncludeOmitted).Encode(gui.Config.UserConfig) _ = yaml.NewEncoder(&configBuf, yaml.IncludeOmitted).Encode(gui.Config.UserConfig)
dashboardString := strings.Join( dashboardString := strings.Join(
[]string{ []string{
@ -122,7 +122,7 @@ func (gui *Gui) renderCredits() error {
configBuf.String(), configBuf.String(),
}, "\n\n") }, "\n\n")
gui.renderString(gui.g, "main", dashboardString) _ = gui.renderString(gui.g, "main", dashboardString)
}) })
} }
@ -145,7 +145,7 @@ func (gui *Gui) renderAllLogs() error {
cmd.Stderr = mainView cmd.Stderr = mainView
gui.OSCommand.PrepareForChildren(cmd) gui.OSCommand.PrepareForChildren(cmd)
cmd.Start() _ = cmd.Start()
go func() { go func() {
<-stop <-stop
@ -154,7 +154,7 @@ func (gui *Gui) renderAllLogs() error {
} }
}() }()
cmd.Wait() _ = cmd.Wait()
}) })
} }
@ -165,7 +165,7 @@ func (gui *Gui) renderDockerComposeConfig() error {
mainView.Wrap = gui.Config.UserConfig.Gui.WrapMainPanel mainView.Wrap = gui.Config.UserConfig.Gui.WrapMainPanel
config := gui.DockerCommand.DockerComposeConfig() config := gui.DockerCommand.DockerComposeConfig()
gui.renderString(gui.g, "main", config) _ = gui.renderString(gui.g, "main", config)
}) })
} }
@ -198,7 +198,7 @@ func (gui *Gui) handleProjectNextContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Project.ContextIndex++ gui.State.Panels.Project.ContextIndex++
} }
gui.handleProjectSelect(gui.g, v) _ = gui.handleProjectSelect(gui.g, v)
return nil return nil
} }
@ -211,7 +211,7 @@ func (gui *Gui) handleProjectPrevContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Project.ContextIndex-- gui.State.Panels.Project.ContextIndex--
} }
gui.handleProjectSelect(gui.g, v) _ = gui.handleProjectSelect(gui.g, v)
return nil return nil
} }

View file

@ -118,10 +118,10 @@ func (gui *Gui) renderServiceTop(service *commands.Service) error {
return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) { return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) {
contents, err := service.RenderTop() contents, err := service.RenderTop()
if err != nil { if err != nil {
gui.reRenderString(gui.g, "main", err.Error()) _ = gui.reRenderString(gui.g, "main", err.Error())
} }
gui.reRenderString(gui.g, "main", contents) _ = gui.reRenderString(gui.g, "main", contents)
}) })
} }
@ -170,7 +170,7 @@ func (gui *Gui) handleServicesNextContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Services.ContextIndex++ gui.State.Panels.Services.ContextIndex++
} }
gui.handleServiceSelect(gui.g, v) _ = gui.handleServiceSelect(gui.g, v)
return nil return nil
} }
@ -183,7 +183,7 @@ func (gui *Gui) handleServicesPrevContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Services.ContextIndex-- gui.State.Panels.Services.ContextIndex--
} }
gui.handleServiceSelect(gui.g, v) _ = gui.handleServiceSelect(gui.g, v)
return nil return nil
} }

View file

@ -354,8 +354,8 @@ func (gui *Gui) popupPanelFocused() bool {
func (gui *Gui) clearMainView() { func (gui *Gui) clearMainView() {
mainView := gui.getMainView() mainView := gui.getMainView()
mainView.Clear() mainView.Clear()
mainView.SetOrigin(0, 0) _ = mainView.SetOrigin(0, 0)
mainView.SetCursor(0, 0) _ = mainView.SetCursor(0, 0)
} }
func (gui *Gui) handleClick(v *gocui.View, itemCount int, selectedLine *int, handleSelect func(*gocui.Gui, *gocui.View) error) error { func (gui *Gui) handleClick(v *gocui.View, itemCount int, selectedLine *int, handleSelect func(*gocui.Gui, *gocui.View) error) error {

View file

@ -99,7 +99,7 @@ func (gui *Gui) renderVolumeConfig(mainView *gocui.View, volume *commands.Volume
output += utils.WithPadding("Size: ", padding) + utils.FormatBinaryBytes(int(volume.Volume.UsageData.Size)) + "\n" output += utils.WithPadding("Size: ", padding) + utils.FormatBinaryBytes(int(volume.Volume.UsageData.Size)) + "\n"
} }
gui.renderString(gui.g, "main", output) _ = gui.renderString(gui.g, "main", output)
}) })
} }
@ -168,7 +168,7 @@ func (gui *Gui) handleVolumesNextContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Volumes.ContextIndex++ gui.State.Panels.Volumes.ContextIndex++
} }
gui.handleVolumeSelect(gui.g, v) _ = gui.handleVolumeSelect(gui.g, v)
return nil return nil
} }
@ -181,7 +181,7 @@ func (gui *Gui) handleVolumesPrevContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Volumes.ContextIndex-- gui.State.Panels.Volumes.ContextIndex--
} }
gui.handleVolumeSelect(gui.g, v) _ = gui.handleVolumeSelect(gui.g, v)
return nil return nil
} }

View file

@ -43,7 +43,7 @@ func getLogLevel() logrus.Level {
func newDevelopmentLogger(config *config.AppConfig) *logrus.Logger { func newDevelopmentLogger(config *config.AppConfig) *logrus.Logger {
log := logrus.New() log := logrus.New()
log.SetLevel(getLogLevel()) log.SetLevel(getLogLevel())
file, err := os.OpenFile(filepath.Join(config.ConfigDir, "development.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) file, err := os.OpenFile(filepath.Join(config.ConfigDir, "development.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o666)
if err != nil { if err != nil {
fmt.Println("unable to log to file") fmt.Println("unable to log to file")
os.Exit(1) os.Exit(1)

View file

@ -269,7 +269,7 @@ func FormatDecimalBytes(b int) string {
func ApplyTemplate(str string, object interface{}) string { func ApplyTemplate(str string, object interface{}) string {
var buf bytes.Buffer var buf bytes.Buffer
template.Must(template.New("").Parse(str)).Execute(&buf, object) _ = template.Must(template.New("").Parse(str)).Execute(&buf, object)
return buf.String() return buf.String()
} }

View file

@ -68,7 +68,7 @@ func TestNormalizeLinefeeds(t *testing.T) {
byteArray []byte byteArray []byte
expected []byte expected []byte
} }
var scenarios = []scenario{ scenarios := []scenario{
{ {
// \r\n // \r\n
[]byte{97, 115, 100, 102, 13, 10}, []byte{97, 115, 100, 102, 13, 10},

View file

@ -12,7 +12,6 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"strings"
"github.com/jesseduffield/lazydocker/pkg/app" "github.com/jesseduffield/lazydocker/pkg/app"
"github.com/jesseduffield/lazydocker/pkg/config" "github.com/jesseduffield/lazydocker/pkg/config"
@ -135,11 +134,3 @@ func formatSections(mApp *app.App, bindingSections []*bindingSection) string {
return content return content
} }
func getProjectRoot() string {
dir, err := os.Getwd()
if err != nil {
panic(err)
}
return strings.Split(dir, "lazydocker")[0] + "lazydocker"
}

26
test.sh Normal file
View file

@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
echo "" > coverage.txt
export GOFLAGS=-mod=vendor
use_go_test=false
if command -v gotest; then
use_go_test=true
fi
for d in $( find ./* -maxdepth 10 ! -path "./vendor*" ! -path "./.git*" ! -path "./scripts*" -type d); do
if ls $d/*.go &> /dev/null; then
args="-race -coverprofile=profile.out -covermode=atomic $d"
if [ "$use_go_test" == true ]; then
gotest $args
else
go test $args
fi
if [ -f profile.out ]; then
cat profile.out >> coverage.txt
rm profile.out
fi
fi
done

View file

@ -1,11 +0,0 @@
dependencies:
post:
# install golint
- go get golang.org/x/lint/golint
test:
pre:
# run analysis before tests
- go vet ./...
- test -z "$(golint ./... | tee /dev/stderr)"
- test -z "$(gofmt -s -l . | tee /dev/stderr)"