From 2bd8beb83695f10ab4fea06dfbe2de9427698a21 Mon Sep 17 00:00:00 2001 From: Augustas Verbickas Date: Mon, 3 Aug 2020 19:56:29 +0300 Subject: [PATCH 1/3] Golang CI integration, linter fixes --- .golangci.yml | 62 +++++++ Makefile | 181 +++------------------ build/custom.mk | 2 +- build/deploy/main.go | 41 +++-- build/manifest/.gitignore | 0 build/manifest/main.go | 4 +- server/command/command.go | 4 +- server/command/command_flags.go | 4 +- server/command/fair_test.go | 2 +- server/command/rotation_archive_test.go | 4 +- server/command/rotation_list.go | 2 +- server/command/rotation_show.go | 2 +- server/command/skill.go | 6 +- server/command/task_unassign_test.go | 2 +- server/command/user_join.go | 3 +- server/sl/filler/solarlottery/fill_test.go | 34 ++-- server/sl/filler/solarlottery/pick.go | 2 +- server/sl/filler/solarlottery/pick_test.go | 66 ++++---- server/sl/sl.go | 22 +-- server/sl/test/guess_test.gogo | 8 +- server/sl/test/needs.go | 92 +++++------ server/sl/test/needs_test.go | 11 +- server/utils/types/time_test.go | 2 - 23 files changed, 246 insertions(+), 310 deletions(-) create mode 100644 .golangci.yml create mode 100644 build/manifest/.gitignore diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..59cd641 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,62 @@ +run: + timeout: 5m + modules-download-mode: readonly + +linters-settings: + goconst: + min-len: 2 + min-occurrences: 2 + gofmt: + simplify: true + goimports: + local-prefixes: https://github.com/mattermost/mattermost-plugin-solar-lottery + golint: + min-confidence: 0 + govet: + check-shadowing: true + enable-all: true + misspell: + locale: US + +linters: + disable-all: true + enable: + - bodyclose + - deadcode + # - errcheck + # - goconst + - gocritic + # - gofmt + # - goimports + # - golint + # - gosec + # - gosimple + # - govet + # - ineffassign + # - interfacer + # - misspell + - nakedret + # - staticcheck + - structcheck + # - stylecheck + - typecheck + - unconvert + # - unused + - varcheck + - whitespace + +issues: + exclude-rules: + - path: server/manifest.go + linters: + - deadcode + - unused + - varcheck + - path: server/configuration.go + linters: + - unused + - path: _test\.go + linters: + - bodyclose + - goconst + - scopelint # https://github.com/kyoh86/scopelint/issues/4 diff --git a/Makefile b/Makefile index 673b073..3782f03 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,14 @@ -OS := $(shell uname 2> /dev/null) -GO ?= $(shell command -v go 2> /dev/null) + +O ?= $(shell command -v go 2> /dev/null) NPM ?= $(shell command -v npm 2> /dev/null) CURL ?= $(shell command -v curl 2> /dev/null) MANIFEST_FILE ?= plugin.json GOPATH ?= $(shell go env GOPATH) +GO_TEST_FLAGS ?= -race +GO_BUILD_FLAGS ?= MM_UTILITIES_DIR ?= ../mattermost-utilities export GO111MODULE=on -MINIMUM_SUPPORTED_GO_MAJOR_VERSION = 1 -MINIMUM_SUPPORTED_GO_MINOR_VERSION = 12 -GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1) -GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2) -GO_VERSION_VALIDATION_ERR_MSG = Golang version is not supported, please update to at least $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION).$(MINIMUM_SUPPORTED_GO_MINOR_VERSION) -BUILD_DATE = $(shell date -u) -BUILD_HASH = $(shell git rev-parse HEAD) -BUILD_HASH_SHORT = $(shell git rev-parse --short HEAD) -LDFLAGS += -X "main.BuildDate=$(BUILD_DATE)" -LDFLAGS += -X "main.BuildHash=$(BUILD_HASH)" -LDFLAGS += -X "main.BuildHashShort=$(BUILD_HASH_SHORT)" -GO_TEST_FLAGS ?= -race -GO_BUILD_FLAGS ?= -GOBUILD = $(GO) build $(GOFLAGS) -ldflags '$(LDFLAGS)' -GOTEST = $(GO) test $(GOFLAGS) -ldflags '$(LDFLAGS)' # You can include assets this directory into the bundle. This can be e.g. used to include profile pictures. ASSETS_DIR ?= assets @@ -44,81 +31,34 @@ all: check-style test dist apply: ./build/bin/manifest apply -## Runs govet and gofmt against all packages. +## Runs golangci-lint and eslint. .PHONY: check-style -check-style: webapp/.npminstall gofmt govet +check-style: webapp/.npminstall golangci-lint @echo Checking for style guide compliance ifneq ($(HAS_WEBAPP),) cd webapp && npm run lint endif -## Runs gofmt against all packages. -.PHONY: gofmt -gofmt: -ifneq ($(HAS_SERVER),) - @echo Running gofmt - @for package in $$(go list ./...); do \ - echo "Checking "$$package; \ - files=$$(go list -f '{{range .GoFiles}}{{$$.Dir}}/{{.}} {{end}}' $$package); \ - if [ "$$files" ]; then \ - gofmt_output=$$(gofmt -d -s $$files 2>&1); \ - if [ "$$gofmt_output" ]; then \ - echo "$$gofmt_output"; \ - echo "Gofmt failure"; \ - exit 1; \ - fi; \ - fi; \ - done - @echo Gofmt success -endif - -## Runs govet against all packages. -.PHONY: govet -govet: -ifneq ($(HAS_SERVER),) - @echo Running govet - @# Workaround because you can't install binaries without adding them to go.mod - env GO111MODULE=off $(GO) get golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow - $(GO) vet ./... - $(GO) vet -vettool=$(GOPATH)/bin/shadow ./... - @echo Govet success -endif +## Run golangci-lint on codebase. +.PHONY: golangci-lint +golangci-lint: + @if ! [ -x "$$(command -v golangci-lint)" ]; then \ + echo "golangci-lint is not installed. Please see https://github.com/golangci/golangci-lint#install for installation instructions."; \ + exit 1; \ + fi; \ -## Runs golint against all packages. -.PHONY: golint -golint: - @echo Running lint - env GO111MODULE=off $(GO) get golang.org/x/lint/golint - $(GOPATH)/bin/golint -set_exit_status ./... - @echo lint success - -## Generates mock golang interfaces for testing -mock: -ifneq ($(HAS_SERVER),) - go install github.com/golang/mock/mockgen - mockgen -destination server/sl/mock_sl/mock_plugin_api.go github.com/mattermost/mattermost-plugin-solar-lottery/server/sl PluginAPI - # mockgen -destination server/utils/bot/mock_bot/mock_poster.go github.com/mattermost/mattermost-plugin-solar-lottery/server/utils/bot Poster - # mockgen -destination server/utils/bot/mock_bot/mock_admin.go github.com/mattermost/mattermost-plugin-solar-lottery/server/utils/bot Admin - # mockgen -destination server/store/mock_store/mock_store.go github.com/mattermost/mattermost-plugin-solar-lottery/server/store Store -endif - -## Generates mock golang interfaces for testing -clean_mock: -ifneq ($(HAS_SERVER),) - rm -rf ./server/solarlottery/mock_solarlottery - rm -rf ./server/utils/bot/mock_bot - rm -rf ./server/store/mock_store -endif + @echo Running golangci-lint + golangci-lint run ./... ## Builds the server, if it exists, including support for multiple architectures. .PHONY: server server: ifneq ($(HAS_SERVER),) mkdir -p server/dist; - cd server && env GOOS=linux GOARCH=amd64 $(GOBUILD) -o dist/plugin-linux-amd64; - cd server && env GOOS=darwin GOARCH=amd64 $(GOBUILD) -o dist/plugin-darwin-amd64; - cd server && env GOOS=windows GOARCH=amd64 $(GOBUILD) -o dist/plugin-windows-amd64.exe; + cd server && env GOOS=linux GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -o dist/plugin-linux-amd64; + cd server && env GOOS=darwin GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -o dist/plugin-darwin-amd64; + cd server && env GOOS=windows GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -o dist/plugin-windows-amd64.exe; endif ## Ensures NPM dependencies are installed without having to run this all the time. @@ -136,6 +76,7 @@ ifneq ($(HAS_WEBAPP),) endif ## Builds the webapp in debug mode, if it exists. +.PHONY: webapp-debug webapp-debug: webapp/.npminstall ifneq ($(HAS_WEBAPP),) cd webapp && \ @@ -171,23 +112,11 @@ endif dist: apply server webapp bundle ## Installs the plugin to a (development) server. +## It uses the API if appropriate environment variables are defined, +## and otherwise falls back to trying to copy the plugin to a sibling mattermost-server directory. .PHONY: deploy deploy: dist -## It uses the API if appropriate environment variables are defined, -## or copying the files directly to a sibling mattermost-server directory. -ifneq ($(and $(MM_SERVICESETTINGS_SITEURL),$(MM_ADMIN_USERNAME),$(MM_ADMIN_PASSWORD),$(CURL)),) - @echo "Installing plugin via API" - $(eval TOKEN := $(shell curl -i --post301 --location $(MM_SERVICESETTINGS_SITEURL) -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/login -d '{"login_id": "$(MM_ADMIN_USERNAME)", "password": "$(MM_ADMIN_PASSWORD)"}' | grep Token | cut -f2 -d' ' 2> /dev/null)) - @curl -s --post301 --location $(MM_SERVICESETTINGS_SITEURL) -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins -F "plugin=@dist/$(BUNDLE_NAME)" -F "force=true" > /dev/null && \ - curl -s --post301 --location $(MM_SERVICESETTINGS_SITEURL) -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/enable > /dev/null && \ - echo "OK." || echo "Sorry, something went wrong." -else ifneq ($(wildcard ../mattermost-server/.*),) - @echo "Installing plugin via filesystem. Server restart and manual plugin enabling required" - mkdir -p ../mattermost-server/plugins - tar -C ../mattermost-server/plugins -zxvf dist/$(BUNDLE_NAME) -else - @echo "No supported deployment method available. Install plugin manually." -endif + ./build/bin/deploy $(PLUGIN_ID) dist/$(BUNDLE_NAME) .PHONY: debug-deploy debug-deploy: debug-dist deploy @@ -229,10 +158,12 @@ endif clean: rm -fr dist/ ifneq ($(HAS_SERVER),) + rm -fr server/coverage.txt rm -fr server/dist endif ifneq ($(HAS_WEBAPP),) rm -fr webapp/.npminstall + rm -fr webapp/junit.xml rm -fr webapp/dist rm -fr webapp/node_modules endif @@ -241,67 +172,3 @@ endif # Help documentation à la https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html help: @cat Makefile | grep -v '\.PHONY' | grep -v '\help:' | grep -B1 -E '^[a-zA-Z0-9_.-]+:.*' | sed -e "s/:.*//" | sed -e "s/^## //" | grep -v '\-\-' | sed '1!G;h;$$!d' | awk 'NR%2{printf "\033[36m%-30s\033[0m",$$0;next;}1' | sort - -# sd is an easier-to-type alias for server-debug -.PHONY: sd -sd: server-debug - -# server-debug builds and deploys a debug version of the plugin for your architecture. -# Then resets the plugin to pick up the changes. -.PHONY: server-debug -server-debug: server-debug-deploy reset - -.PHONY: server-debug-deploy -server-debug-deploy: validate-go-version - ./build/bin/manifest apply - mkdir -p server/dist -ifeq ($(OS),Darwin) - cd server && env GOOS=darwin GOARCH=amd64 $(GOBUILD) -gcflags "all=-N -l" -o dist/plugin-darwin-amd64; -else ifeq ($(OS),Linux) - cd server && env GOOS=linux GOARCH=amd64 $(GOBUILD) -gcflags "all=-N -l" -o dist/plugin-linux-amd64; -else ifeq ($(OS),Windows_NT) - cd server && env GOOS=windows GOARCH=amd64 $(GOBUILD) -gcflags "all=-N -l" -o dist/plugin-windows-amd64.exe; -else - $(error make debug depends on uname to return your OS. If it does not return 'Darwin' (meaning OSX), 'Linux', or 'Windows_NT' (all recent versions of Windows), you will need to edit the Makefile for your own OS.) -endif - rm -rf dist/ - mkdir -p dist/$(PLUGIN_ID)/server/dist - cp $(MANIFEST_FILE) dist/$(PLUGIN_ID)/ - cp -r server/dist/* dist/$(PLUGIN_ID)/server/dist/ - mkdir -p ../mattermost-server/plugins - cp -r dist/* ../mattermost-server/plugins/ - -.PHONY: validate-go-version -validate-go-version: ## Validates the installed version of go against Mattermost's minimum requirement. - @if [ $(GO_MAJOR_VERSION) -gt $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION) ]; then \ - exit 0 ;\ - elif [ $(GO_MAJOR_VERSION) -lt $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION) ]; then \ - echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\ - exit 1; \ - elif [ $(GO_MINOR_VERSION) -lt $(MINIMUM_SUPPORTED_GO_MINOR_VERSION) ] ; then \ - echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\ - exit 1; \ - fi - -# Reset the plugin -.PHONY: reset -reset: -ifeq ($(and $(MM_SERVICESETTINGS_SITEURL),$(MM_ADMIN_USERNAME),$(MM_ADMIN_PASSWORD),$(CURL)),) - $(error In order to use make reset, the following environment variables need to be defined: MM_SERVICESETTINGS_SITEURL, MM_ADMIN_USERNAME, MM_ADMIN_PASSWORD, and you need to have curl installed.) -endif - -# If we were debugging, we have to unattach the delve process or else we can't disable the plugin. -# NOTE: we are assuming the dlv was listening on port 2346, as in the debug-plugin.sh script. - @DELVE_PID=$(shell ps aux | grep "dlv attach.*2346" | grep -v "grep" | awk -F " " '{print $$2}') && \ - if [ "$$DELVE_PID" -gt 0 ] > /dev/null 2>&1 ; then \ - echo "Located existing delve process running with PID: $$DELVE_PID. Killing." ; \ - kill -9 $$DELVE_PID ; \ - fi - - @echo "\nRestarting plugin via API" - $(eval TOKEN := $(shell curl -i -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/login -d '{"login_id": "$(MM_ADMIN_USERNAME)", "password": "$(MM_ADMIN_PASSWORD)"}' | grep -o "Token: [0-9a-z]*" | cut -f2 -d' ' 2> /dev/null)) - @curl -s -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/disable > /dev/null && \ - curl -s -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/enable > /dev/null && \ - echo "OK." || echo "Sorry, something went wrong. Check that MM_ADMIN_USERNAME and MM_ADMIN_PASSWORD env variables are set correctly." - - diff --git a/build/custom.mk b/build/custom.mk index 743e6a4..efad4fb 100644 --- a/build/custom.mk +++ b/build/custom.mk @@ -1 +1 @@ -# Include custom targets and environment variables here +# Include custome targets and environment variables here diff --git a/build/deploy/main.go b/build/deploy/main.go index 7be98d2..186bb49 100644 --- a/build/deploy/main.go +++ b/build/deploy/main.go @@ -34,18 +34,38 @@ func deploy() error { bundlePath := os.Args[2] siteURL := os.Getenv("MM_SERVICESETTINGS_SITEURL") + adminToken := os.Getenv("MM_ADMIN_TOKEN") adminUsername := os.Getenv("MM_ADMIN_USERNAME") adminPassword := os.Getenv("MM_ADMIN_PASSWORD") copyTargetDirectory, _ := filepath.Abs("../mattermost-server") - if siteURL != "" && adminUsername != "" && adminPassword != "" { - return uploadPlugin(pluginID, bundlePath, siteURL, adminUsername, adminPassword) + + if siteURL != "" { + client := model.NewAPIv4Client(siteURL) + + if adminToken != "" { + log.Printf("Authenticating using token against %s.", siteURL) + client.SetToken(adminToken) + + return uploadPlugin(client, pluginID, bundlePath) + } + + if adminUsername != "" && adminPassword != "" { + client := model.NewAPIv4Client(siteURL) + log.Printf("Authenticating as %s against %s.", adminUsername, siteURL) + _, resp := client.Login(adminUsername, adminPassword) + if resp.Error != nil { + return errors.Wrapf(resp.Error, "failed to login as %s", adminUsername) + } + + return uploadPlugin(client, pluginID, bundlePath) + } } _, err := os.Stat(copyTargetDirectory) if os.IsNotExist(err) { return errors.New("no supported deployment method available, please install plugin manually") } else if err != nil { - return errors.Errorf("Failed to stat %s", copyTargetDirectory) + return errors.Wrapf(err, "failed to stat %s", copyTargetDirectory) } log.Printf("Installing plugin to mattermost-server found in %s.", copyTargetDirectory) @@ -55,14 +75,7 @@ func deploy() error { // uploadPlugin attempts to upload and enable a plugin via the Client4 API. // It will fail if plugin uploads are disabled. -func uploadPlugin(pluginID, bundlePath, siteURL, adminUsername, adminPassword string) error { - client := model.NewAPIv4Client(siteURL) - log.Printf("Authenticating as %s against %s.", adminUsername, siteURL) - _, resp := client.Login(adminUsername, adminPassword) - if resp.Error != nil { - return fmt.Errorf("Failed to login as %s: %s", adminUsername, resp.Error.Error()) - } - +func uploadPlugin(client *model.Client4, pluginID, bundlePath string) error { pluginBundle, err := os.Open(bundlePath) if err != nil { return errors.Wrapf(err, "failed to open %s", bundlePath) @@ -70,15 +83,15 @@ func uploadPlugin(pluginID, bundlePath, siteURL, adminUsername, adminPassword st defer pluginBundle.Close() log.Print("Uploading plugin via API.") - _, resp = client.UploadPluginForced(pluginBundle) + _, resp := client.UploadPluginForced(pluginBundle) if resp.Error != nil { - return fmt.Errorf("Failed to upload plugin bundle: %s", resp.Error.Error()) + return errors.Wrap(resp.Error, "failed to upload plugin bundle") } log.Print("Enabling plugin.") _, resp = client.EnablePlugin(pluginID) if resp.Error != nil { - return fmt.Errorf("Failed to enable plugin: %s", resp.Error.Error()) + return errors.Wrap(resp.Error, "Failed to enable plugin") } return nil diff --git a/build/manifest/.gitignore b/build/manifest/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/build/manifest/main.go b/build/manifest/main.go index 89a397c..3227c2a 100644 --- a/build/manifest/main.go +++ b/build/manifest/main.go @@ -106,7 +106,7 @@ func applyManifest(manifest *model.Manifest) error { if err := ioutil.WriteFile( "server/manifest.go", []byte(fmt.Sprintf(pluginIDGoFileTemplate, manifest.Id, manifest.Version)), - 0644, + 0600, ); err != nil { return errors.Wrap(err, "failed to write server/manifest.go") } @@ -116,7 +116,7 @@ func applyManifest(manifest *model.Manifest) error { if err := ioutil.WriteFile( "webapp/src/manifest.js", []byte(fmt.Sprintf(pluginIDJSFileTemplate, manifest.Id, manifest.Version)), - 0644, + 0600, ); err != nil { return errors.Wrap(err, "failed to open webapp/src/manifest.js") } diff --git a/server/command/command.go b/server/command/command.go index 9d94517..0546133 100644 --- a/server/command/command.go +++ b/server/command/command.go @@ -29,7 +29,7 @@ type Command struct { ChannelID string actualTrigger string - outputJson bool + outputJSON bool fs *pflag.FlagSet now *types.Time } @@ -109,7 +109,7 @@ func (c *Command) normalOut(out md.Markdowner, err error) (md.MD, error) { if err != nil { return "", err } - if c.outputJson { + if c.outputJSON { out = md.JSONBlock(out) } return out.Markdown(), nil diff --git a/server/command/command_flags.go b/server/command/command_flags.go index abddfb4..58b8408 100644 --- a/server/command/command_flags.go +++ b/server/command/command_flags.go @@ -43,7 +43,7 @@ func (c *Command) parse(parameters []string) error { return err } - if (*c.now).IsZero() { + if c.now.IsZero() { now := types.NewTime(time.Now()) c.now = &now } @@ -53,7 +53,7 @@ func (c *Command) parse(parameters []string) error { func (c *Command) flags() *pflag.FlagSet { if c.fs == nil { c.fs = pflag.NewFlagSet("", pflag.ContinueOnError) - c.fs.BoolVar(&c.outputJson, "json", false, "output as JSON") + c.fs.BoolVar(&c.outputJSON, "json", false, "output as JSON") c.now, _ = c.withTimeFlag("now", "specify the transaction time (default: now)") } return c.fs diff --git a/server/command/fair_test.go b/server/command/fair_test.go index cda882b..3b0b554 100644 --- a/server/command/fair_test.go +++ b/server/command/fair_test.go @@ -54,7 +54,7 @@ func TestFairSimple(t *testing.T) { } // TODO TestFairSET is effectively failing; for some reason preferring the -// "MOBILE" team. Need to do some careful analisys, the skills structure may +// "MOBILE" team. Need to do some careful analysis, the skills structure may // indeed be skewed towards non-mobile, but would think randomization would // help? Need a better "fairness" test harness anyway. // diff --git a/server/command/rotation_archive_test.go b/server/command/rotation_archive_test.go index c1cbe63..78304d8 100644 --- a/server/command/rotation_archive_test.go +++ b/server/command/rotation_archive_test.go @@ -49,7 +49,6 @@ func TestRotationArchive(t *testing.T) { _, err = run(t, SL, `/lotto rotation show test-123`) require.Equal(t, kvstore.ErrNotFound, err) }) - } func TestRotationDelete(t *testing.T) { @@ -83,5 +82,4 @@ func TestRotationDelete(t *testing.T) { _, err = run(t, SL, `/lotto rotation show test-123`) require.Equal(t, kvstore.ErrNotFound, err) }) - -} +} \ No newline at end of file diff --git a/server/command/rotation_list.go b/server/command/rotation_list.go index aef2f36..29fdeac 100644 --- a/server/command/rotation_list.go +++ b/server/command/rotation_list.go @@ -19,7 +19,7 @@ func (c *Command) rotationList(parameters []string) (md.MD, error) { return "", err } - if c.outputJson { + if c.outputJSON { return md.JSONBlock(rotations), nil } if rotations.Len() == 0 { diff --git a/server/command/rotation_show.go b/server/command/rotation_show.go index 20f8f07..743004f 100644 --- a/server/command/rotation_show.go +++ b/server/command/rotation_show.go @@ -21,7 +21,7 @@ func (c *Command) rotationShow(parameters []string) (md.MD, error) { return "", err } - if c.outputJson { + if c.outputJSON { return md.JSONBlock(r), nil } return r.MarkdownBullets(), nil diff --git a/server/command/skill.go b/server/command/skill.go index 23d4869..ed488c8 100644 --- a/server/command/skill.go +++ b/server/command/skill.go @@ -25,7 +25,7 @@ func (c *Command) skillNew(parameters []string) (md.MD, error) { return "", err } - if c.outputJson { + if c.outputJSON { return md.JSONBlock(skill), nil } return md.Markdownf("Added **%s** to known skills.", skill), nil @@ -45,7 +45,7 @@ func (c *Command) skillDelete(parameters []string) (md.MD, error) { if err != nil { return "", err } - if c.outputJson { + if c.outputJSON { return md.JSONBlock(skill), nil } return md.Markdownf("Deleted **%s** from known skills. User profiles are not changed.", skill), nil @@ -60,7 +60,7 @@ func (c *Command) skillList(parameters []string) (md.MD, error) { if err != nil { return "", err } - if c.outputJson { + if c.outputJSON { return md.JSONBlock(skills), nil } return "Known skills: " + md.JSONBlock(skills), nil diff --git a/server/command/task_unassign_test.go b/server/command/task_unassign_test.go index beb3190..99e381f 100644 --- a/server/command/task_unassign_test.go +++ b/server/command/task_unassign_test.go @@ -85,7 +85,7 @@ func TestTaskUnassign(t *testing.T) { } force := " " if tc.force { - force = force + "--force" + force += "--force" } _, err := runJSON(t, SL, "/lotto task unassign test-rotation#1 "+tc.unassign+force, &out) if tc.expectError { diff --git a/server/command/user_join.go b/server/command/user_join.go index 6245d84..d3a39f9 100644 --- a/server/command/user_join.go +++ b/server/command/user_join.go @@ -4,7 +4,6 @@ package command import ( - "fmt" "github.com/mattermost/mattermost-plugin-solar-lottery/server/sl" "github.com/mattermost/mattermost-plugin-solar-lottery/server/utils/md" @@ -12,7 +11,7 @@ import ( func (c *Command) userJoin(parameters []string) (md.MD, error) { c.withFlagRotation() - starting, err := c.withTimeFlag("starting", fmt.Sprintf("time for user to start participating")) + starting, err := c.withTimeFlag("starting", "time for user to start participating") if err != nil { return c.flagUsage(), err } diff --git a/server/sl/filler/solarlottery/fill_test.go b/server/sl/filler/solarlottery/fill_test.go index 035fc5e..3bb262f 100644 --- a/server/sl/filler/solarlottery/fill_test.go +++ b/server/sl/filler/solarlottery/fill_test.go @@ -41,13 +41,13 @@ func TestFill(t *testing.T) { }{ { name: "happy", - require: sl.NewNeeds(test.C1_Mobile_L1(), test.C1_Server_L1(), test.C1_Webapp_L1()), + require: sl.NewNeeds(test.C1MobileL1(), test.C1ServerL1(), test.C1WebappL1()), pool: test.AllUsers(), skipSucessResultValidation: true, }, { name: "happy accepted", - require: sl.NewNeeds(test.C1_Mobile_L1()), + require: sl.NewNeeds(test.C1MobileL1()), pool: sl.NewUsers( test.UserMobile1().WithLastServed(test.RotationID, longTimeAgo), test.UserMobile2().WithLastServed(test.RotationID, recently), @@ -58,11 +58,11 @@ func TestFill(t *testing.T) { { name: "accepted another maxed out", require: sl.NewNeeds( - test.C1_Mobile_L1(), - test.C1_Server_L1(), + test.C1MobileL1(), + test.C1ServerL1(), ), limit: sl.NewNeeds( - test.C1_Server_L1(), + test.C1ServerL1(), ), assigned: sl.NewUsers( test.UserServer1(), // meets and maxes out the server need, leaving only mobile @@ -78,35 +78,35 @@ func TestFill(t *testing.T) { }, { name: "Err Insufficient simple", - require: sl.NewNeeds(test.C2_Mobile_L1()), + require: sl.NewNeeds(test.C2MobileL1()), pool: sl.NewUsers(test.UserServer1(), test.UserMobile1()), expectFillError: sl.ErrFillInsufficient, - expectUnmetNeeds: sl.NewNeeds(test.C1_Mobile_L1()), - expectFailedNeed: test.C1_Mobile_L1(), + expectUnmetNeeds: sl.NewNeeds(test.C1MobileL1()), + expectFailedNeed: test.C1MobileL1(), }, { name: "Err Insufficient with assigned", - require: sl.NewNeeds(test.C2_Mobile_L1()), + require: sl.NewNeeds(test.C2MobileL1()), assigned: sl.NewUsers(test.UserMobile1()), pool: sl.NewUsers(test.UserServer1(), test.UserServer2()), expectFillError: sl.ErrFillInsufficient, - expectUnmetNeeds: sl.NewNeeds(test.C1_Mobile_L1()), - expectFailedNeed: test.C1_Mobile_L1(), + expectUnmetNeeds: sl.NewNeeds(test.C1MobileL1()), + expectFailedNeed: test.C1MobileL1(), }, { name: "Err Limit", - limit: sl.NewNeeds(test.C1_Any()), - require: sl.NewNeeds(test.C2_Mobile_L1()), + limit: sl.NewNeeds(test.C1Any()), + require: sl.NewNeeds(test.C2MobileL1()), assigned: sl.NewUsers(test.UserMobile1()), pool: sl.NewUsers(test.UserMobile2(), test.UserGuru()), expectFillError: sl.ErrFillInsufficient, - expectUnmetNeeds: sl.NewNeeds(test.C1_Mobile_L1()), - expectFailedNeed: test.C1_Mobile_L1(), + expectUnmetNeeds: sl.NewNeeds(test.C1MobileL1()), + expectFailedNeed: test.C1MobileL1(), }, { name: "Noop on preassigned", - limit: sl.NewNeeds(test.C2_Any()), - require: sl.NewNeeds(test.C2_Mobile_L1()), + limit: sl.NewNeeds(test.C2Any()), + require: sl.NewNeeds(test.C2MobileL1()), assigned: sl.NewUsers(test.UserMobile1(), test.UserMobile2()), pool: sl.NewUsers(test.UserWebapp2(), test.UserGuru()), expectPool: sl.NewUsers(test.UserWebapp2(), test.UserGuru()), diff --git a/server/sl/filler/solarlottery/pick.go b/server/sl/filler/solarlottery/pick.go index 965a3e7..bdf76c7 100644 --- a/server/sl/filler/solarlottery/pick.go +++ b/server/sl/filler/solarlottery/pick.go @@ -112,7 +112,7 @@ func (f *fill) requireWeight(need sl.Need) float64 { // Boost needs that have limits if f.limit.Contains(need.ID) { - total = total * 10 + total *= 10 } return total / float64(len(users)) diff --git a/server/sl/filler/solarlottery/pick_test.go b/server/sl/filler/solarlottery/pick_test.go index 3ac8409..25833fc 100644 --- a/server/sl/filler/solarlottery/pick_test.go +++ b/server/sl/filler/solarlottery/pick_test.go @@ -132,54 +132,54 @@ func TestPickNeed(t *testing.T) { { name: "happy 2", require: sl.NewNeeds( - test.C3_Server_L1(), - test.C1_Webapp_L2(), + test.C3_ServerL1(), + test.C1WebappL2(), ), requirePools: map[types.ID]*sl.Users{ - test.C3_Server_L1().GetID(): usersServer1, - test.C1_Webapp_L2().GetID(): usersWebapp2, + test.C3_ServerL1().GetID(): usersServer1, + test.C1WebappL2().GetID(): usersWebapp2, }, - expectedHighest: test.C1_Webapp_L2(), - expectedRandom: test.C3_Server_L1(), - expectedWeightedRandom: test.C1_Webapp_L2(), + expectedHighest: test.C1WebappL2(), + expectedRandom: test.C3_ServerL1(), + expectedWeightedRandom: test.C1WebappL2(), }, { name: "happy 3", require: sl.NewNeeds( - test.C3_Server_L1(), - test.C2_Server_L2(), - test.C1_Webapp_L2(), + test.C3_ServerL1(), + test.C2ServerL2(), + test.C1WebappL2(), ), requirePools: map[types.ID]*sl.Users{ - test.C3_Server_L1().GetID(): usersServer1, - test.C2_Server_L2().GetID(): usersServer2, - test.C1_Webapp_L2().GetID(): usersWebapp2, + test.C3_ServerL1().GetID(): usersServer1, + test.C2ServerL2().GetID(): usersServer2, + test.C1WebappL2().GetID(): usersWebapp2, }, - // testNeedServer_L2_Min2 is selected since it has the lowest weight/headcount - expectedHighest: test.C2_Server_L2(), - expectedRandom: test.C3_Server_L1(), - expectedWeightedRandom: test.C1_Webapp_L2(), + // testNeedServerL2_Min2 is selected since it has the lowest weight/headcount + expectedHighest: test.C2ServerL2(), + expectedRandom: test.C3_ServerL1(), + expectedWeightedRandom: test.C1WebappL2(), }, { name: "happy 3 with constraint", require: sl.NewNeeds( - test.C3_Server_L1(), - test.C2_Server_L2(), - test.C1_Webapp_L2(), + test.C3_ServerL1(), + test.C2ServerL2(), + test.C1WebappL2(), ), limit: sl.NewNeeds( - test.C1_Webapp_L2(), + test.C1WebappL2(), ), requirePools: map[types.ID]*sl.Users{ - test.C3_Server_L1().GetID(): usersServer1, - test.C2_Server_L2().GetID(): usersServer2, - test.C1_Webapp_L2().GetID(): usersWebapp2, + test.C3_ServerL1().GetID(): usersServer1, + test.C2ServerL2().GetID(): usersServer2, + test.C1WebappL2().GetID(): usersWebapp2, }, - expectedHighest: test.C1_Webapp_L2(), - expectedRandom: test.C3_Server_L1(), - expectedWeightedRandom: test.C1_Webapp_L2(), + expectedHighest: test.C1WebappL2(), + expectedRandom: test.C3_ServerL1(), + expectedWeightedRandom: test.C1WebappL2(), }, } { t.Run(tc.name, func(t *testing.T) { @@ -216,21 +216,21 @@ func TestNeedWeight(t *testing.T) { { name: "happy", require: sl.NewNeeds( - test.C3_Server_L1(), - test.C1_Webapp_L2(), + test.C3_ServerL1(), + test.C1WebappL2(), ), requirePools: map[types.ID]*sl.Users{ - test.C3_Server_L1().GetID(): usersServer, - test.C1_Webapp_L2().GetID(): usersWebapp, + test.C3_ServerL1().GetID(): usersServer, + test.C1WebappL2().GetID(): usersWebapp, }, }, } { t.Run(tc.name, func(t *testing.T) { f := makeTestFiller(t, nil, nil, tc.require, tc.limit) f.requirePools = tc.requirePools - w := f.requireWeight(test.C1_Webapp_L2()) + w := f.requireWeight(test.C1WebappL2()) require.Equal(t, 1.3724873597089898e+15, w) - w = f.requireWeight(test.C3_Server_L1()) + w = f.requireWeight(test.C3_ServerL1()) require.Equal(t, 1.8299831462785262e+15, w) }) } diff --git a/server/sl/sl.go b/server/sl/sl.go index 3665df5..9b6bfeb 100644 --- a/server/sl/sl.go +++ b/server/sl/sl.go @@ -16,19 +16,19 @@ const ( ctxActingUsername = "ActingUsername" ctxAPI = "API" ctxInput = "Input" - ctxFill = "Fill" - ctxForce = "Force" - ctxInterval = "Interval" + // ctxFill = "Fill" + // ctxForce = "Force" + // ctxInterval = "Interval" ctxRotationID = "RotationID" - ctxSkill = "Skill" - ctxSkillLevel = "SkillLevel" - ctxSourceName = "SourceName" - ctxStarting = "Starting" + // ctxSkill = "Skill" + // ctxSkillLevel = "SkillLevel" + // ctxSourceName = "SourceName" + // ctxStarting = "Starting" ctxTaskID = "TaskID" - ctxUnavailable = "Unavailable" - ctxUserIDs = "UserIDs" - ctxUsernames = "Usernames" - ctxUsers = "Users" + // ctxUnavailable = "Unavailable" + // ctxUserIDs = "UserIDs" + // ctxUsernames = "Usernames" + // ctxUsers = "Users" ) var ErrMultipleResults = errors.New("multiple results found") diff --git a/server/sl/test/guess_test.gogo b/server/sl/test/guess_test.gogo index 3a9d20d..dca2d7c 100644 --- a/server/sl/test/guess_test.gogo +++ b/server/sl/test/guess_test.gogo @@ -92,9 +92,9 @@ func TestPrepareShiftHappy(t *testing.T) { rotation.Period = sl.EveryMonth rotation.Size = 3 rotation.Needs = store.Needs{ - NeedServer_L1_Min1(), - NeedWebapp_L2_Min1(), - NeedMobile_L1_Min1(), + NeedServerL1_Min1(), + NeedWebappL2_Min1(), + NeedMobileL1_Min1(), } rotation = rotation.WithUsers(AllUsers()) rotation = rotation.WithStart("2020-01-16") @@ -115,7 +115,7 @@ func TestPrepareShiftEvenDistribution(t *testing.T) { rotation.Period = sl.EveryMonth rotation.Size = 1 rotation.Needs = store.Needs{ - NeedWebapp_L1_Min1(), + NeedWebappL1_Min1(), } rotation = rotation.WithUsers(AllUsers()) rotation = rotation.WithStart("2020-01-16") diff --git a/server/sl/test/needs.go b/server/sl/test/needs.go index 4810fac..b70cd84 100644 --- a/server/sl/test/needs.go +++ b/server/sl/test/needs.go @@ -12,49 +12,49 @@ const ( Plugins = "plugins" ) -func Mobile_L1() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 1) } -func Mobile_L2() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 2) } -func Mobile_L3() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 3) } -func Mobile_L4() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 4) } - -func Server_L1() sl.SkillLevel { return sl.NewSkillLevel(Server, 1) } -func Server_L2() sl.SkillLevel { return sl.NewSkillLevel(Server, 2) } -func Server_L3() sl.SkillLevel { return sl.NewSkillLevel(Server, 3) } -func Server_L4() sl.SkillLevel { return sl.NewSkillLevel(Server, 4) } - -func Webapp_L1() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 1) } -func Webapp_L2() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 2) } -func Webapp_L3() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 3) } -func Webapp_L4() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 4) } - -func C1_Any() sl.Need { return sl.NewNeed(1, sl.AnySkillLevel) } -func C2_Any() sl.Need { return sl.NewNeed(1, sl.AnySkillLevel) } -func C3_Any() sl.Need { return sl.NewNeed(1, sl.AnySkillLevel) } - -func C1_Mobile_L1() sl.Need { return sl.NewNeed(1, Mobile_L1()) } -func C1_Mobile_L2() sl.Need { return sl.NewNeed(1, Mobile_L2()) } -func C1_Mobile_L3() sl.Need { return sl.NewNeed(1, Mobile_L3()) } -func C1_Mobile_L4() sl.Need { return sl.NewNeed(1, Mobile_L4()) } -func C2_Mobile_L1() sl.Need { return sl.NewNeed(2, Mobile_L1()) } -func C2_Mobile_L2() sl.Need { return sl.NewNeed(2, Mobile_L2()) } -func C2_Mobile_L3() sl.Need { return sl.NewNeed(2, Mobile_L3()) } -func C2_Mobile_L4() sl.Need { return sl.NewNeed(2, Mobile_L4()) } - -func C1_Server_L1() sl.Need { return sl.NewNeed(1, Server_L1()) } -func C1_Server_L2() sl.Need { return sl.NewNeed(1, Server_L2()) } -func C1_Server_L3() sl.Need { return sl.NewNeed(1, Server_L3()) } -func C1_Server_L4() sl.Need { return sl.NewNeed(1, Server_L4()) } -func C2_Server_L1() sl.Need { return sl.NewNeed(2, Server_L1()) } -func C2_Server_L2() sl.Need { return sl.NewNeed(2, Server_L2()) } -func C2_Server_L3() sl.Need { return sl.NewNeed(2, Server_L3()) } -func C2_Server_L4() sl.Need { return sl.NewNeed(2, Server_L4()) } -func C3_Server_L1() sl.Need { return sl.NewNeed(3, Server_L1()) } - -func C1_Webapp_L1() sl.Need { return sl.NewNeed(1, Webapp_L1()) } -func C1_Webapp_L2() sl.Need { return sl.NewNeed(1, Webapp_L2()) } -func C1_Webapp_L3() sl.Need { return sl.NewNeed(1, Webapp_L3()) } -func C1_Webapp_L4() sl.Need { return sl.NewNeed(1, Webapp_L4()) } -func C2_Webapp_L1() sl.Need { return sl.NewNeed(2, Webapp_L1()) } -func C2_Webapp_L2() sl.Need { return sl.NewNeed(2, Webapp_L2()) } -func C2_Webapp_L3() sl.Need { return sl.NewNeed(2, Webapp_L3()) } -func C2_Webapp_L4() sl.Need { return sl.NewNeed(2, Webapp_L4()) } +func MobileL1() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 1) } +func MobileL2() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 2) } +func MobileL3() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 3) } +func MobileL4() sl.SkillLevel { return sl.NewSkillLevel(Mobile, 4) } + +func ServerL1() sl.SkillLevel { return sl.NewSkillLevel(Server, 1) } +func ServerL2() sl.SkillLevel { return sl.NewSkillLevel(Server, 2) } +func ServerL3() sl.SkillLevel { return sl.NewSkillLevel(Server, 3) } +func ServerL4() sl.SkillLevel { return sl.NewSkillLevel(Server, 4) } + +func WebappL1() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 1) } +func WebappL2() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 2) } +func WebappL3() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 3) } +func WebappL4() sl.SkillLevel { return sl.NewSkillLevel(Webapp, 4) } + +func C1Any() sl.Need { return sl.NewNeed(1, sl.AnySkillLevel) } +func C2Any() sl.Need { return sl.NewNeed(1, sl.AnySkillLevel) } +func C3Any() sl.Need { return sl.NewNeed(1, sl.AnySkillLevel) } + +func C1MobileL1() sl.Need { return sl.NewNeed(1, MobileL1()) } +func C1MobileL2() sl.Need { return sl.NewNeed(1, MobileL2()) } +func C1MobileL3() sl.Need { return sl.NewNeed(1, MobileL3()) } +func C1MobileL4() sl.Need { return sl.NewNeed(1, MobileL4()) } +func C2MobileL1() sl.Need { return sl.NewNeed(2, MobileL1()) } +func C2MobileL2() sl.Need { return sl.NewNeed(2, MobileL2()) } +func C2MobileL3() sl.Need { return sl.NewNeed(2, MobileL3()) } +func C2MobileL4() sl.Need { return sl.NewNeed(2, MobileL4()) } + +func C1ServerL1() sl.Need { return sl.NewNeed(1, ServerL1()) } +func C1ServerL2() sl.Need { return sl.NewNeed(1, ServerL2()) } +func C1ServerL3() sl.Need { return sl.NewNeed(1, ServerL3()) } +func C1ServerL4() sl.Need { return sl.NewNeed(1, ServerL4()) } +func C2ServerL1() sl.Need { return sl.NewNeed(2, ServerL1()) } +func C2ServerL2() sl.Need { return sl.NewNeed(2, ServerL2()) } +func C2ServerL3() sl.Need { return sl.NewNeed(2, ServerL3()) } +func C2ServerL4() sl.Need { return sl.NewNeed(2, ServerL4()) } +func C3_ServerL1() sl.Need { return sl.NewNeed(3, ServerL1()) } + +func C1WebappL1() sl.Need { return sl.NewNeed(1, WebappL1()) } +func C1WebappL2() sl.Need { return sl.NewNeed(1, WebappL2()) } +func C1WebappL3() sl.Need { return sl.NewNeed(1, WebappL3()) } +func C1WebappL4() sl.Need { return sl.NewNeed(1, WebappL4()) } +func C2WebappL1() sl.Need { return sl.NewNeed(2, WebappL1()) } +func C2WebappL2() sl.Need { return sl.NewNeed(2, WebappL2()) } +func C2WebappL3() sl.Need { return sl.NewNeed(2, WebappL3()) } +func C2WebappL4() sl.Need { return sl.NewNeed(2, WebappL4()) } diff --git a/server/sl/test/needs_test.go b/server/sl/test/needs_test.go index cdb47da..10fb690 100644 --- a/server/sl/test/needs_test.go +++ b/server/sl/test/needs_test.go @@ -23,7 +23,7 @@ func TestQualifiedForNeed(t *testing.T) { }{ { name: "Guru server 2", - need: C1_Server_L2(), + need: C1ServerL2(), user: UserGuru(), expected: true, }, @@ -35,13 +35,13 @@ func TestQualifiedForNeed(t *testing.T) { }, { name: "Webapp1 server 1", - need: C1_Server_L1(), + need: C1ServerL1(), user: UserWebapp1(), expected: true, }, { name: "Webapp1 server 2", - need: C1_Server_L2(), + need: C1ServerL2(), user: UserWebapp1(), expected: false, }, @@ -64,13 +64,13 @@ func TestUsersQualifiedForNeed(t *testing.T) { }{ { name: "happy server3", - need: C1_Server_L3(), + need: C1ServerL3(), users: sl.NewUsers(UserGuru(), UserServer1(), UserServer2(), UserServer3(), UserMobile1()), expectedQualified: sl.NewUsers(UserGuru(), UserServer1(), UserServer2(), UserServer3()), }, { name: "happy server4", - need: C1_Server_L4(), + need: C1ServerL4(), users: sl.NewUsers(UserGuru(), UserServer1(), UserServer2(), UserServer3(), UserMobile1()), expectedQualified: sl.NewUsers(UserGuru()), }, @@ -79,7 +79,6 @@ func TestUsersQualifiedForNeed(t *testing.T) { qualified, need := tc.need.QualifyUsers(tc.users) require.Equal(t, tc.expectedQualified, qualified) require.Equal(t, tc.need.Count()-int64(tc.expectedQualified.Len()), need.Count()) - }) } } diff --git a/server/utils/types/time_test.go b/server/utils/types/time_test.go index 8e48cf2..9b46c2d 100644 --- a/server/utils/types/time_test.go +++ b/server/utils/types/time_test.go @@ -14,7 +14,6 @@ import ( ) func TestTimeSet(t *testing.T) { - tests := []struct { in string expectedError string @@ -53,7 +52,6 @@ func TestTimeJSON(t *testing.T) { }, } for _, tc := range tests { - t.Run(tc.time.Format(time.RFC3339), func(t *testing.T) { tt := NewTime(tc.time).In(EST) From 1865810e1a13d7214e9b9b93db41d38648ac2e7b Mon Sep 17 00:00:00 2001 From: Augustas Verbickas Date: Mon, 3 Aug 2020 22:59:40 +0300 Subject: [PATCH 2/3] Comparing old Makefile --- Makefile | 178 ++++++++++++++++++++++++++++++++++++++++++++++-- build/custom.mk | 2 +- 2 files changed, 172 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 3782f03..45e9d16 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,27 @@ - -O ?= $(shell command -v go 2> /dev/null) +OS := $(shell uname 2> /dev/null) +GO ?= $(shell command -v go 2> /dev/null) NPM ?= $(shell command -v npm 2> /dev/null) CURL ?= $(shell command -v curl 2> /dev/null) MANIFEST_FILE ?= plugin.json GOPATH ?= $(shell go env GOPATH) -GO_TEST_FLAGS ?= -race -GO_BUILD_FLAGS ?= MM_UTILITIES_DIR ?= ../mattermost-utilities export GO111MODULE=on +MINIMUM_SUPPORTED_GO_MAJOR_VERSION = 1 +MINIMUM_SUPPORTED_GO_MINOR_VERSION = 12 +GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1) +GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2) +GO_VERSION_VALIDATION_ERR_MSG = Golang version is not supported, please update to at least $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION).$(MINIMUM_SUPPORTED_GO_MINOR_VERSION) +BUILD_DATE = $(shell date -u) +BUILD_HASH = $(shell git rev-parse HEAD) +BUILD_HASH_SHORT = $(shell git rev-parse --short HEAD) +LDFLAGS += -X "main.BuildDate=$(BUILD_DATE)" +LDFLAGS += -X "main.BuildHash=$(BUILD_HASH)" +LDFLAGS += -X "main.BuildHashShort=$(BUILD_HASH_SHORT)" +GO_TEST_FLAGS ?= -race +GO_BUILD_FLAGS ?= +GOBUILD = $(GO) build $(GOFLAGS) -ldflags '$(LDFLAGS)' +GOTEST = $(GO) test $(GOFLAGS) -ldflags '$(LDFLAGS)' # You can include assets this directory into the bundle. This can be e.g. used to include profile pictures. ASSETS_DIR ?= assets @@ -31,6 +44,55 @@ all: check-style test dist apply: ./build/bin/manifest apply +## Runs govet and gofmt against all packages. +.PHONY: check-style +check-style: webapp/.npminstall gofmt govet + @echo Checking for style guide compliance + +ifneq ($(HAS_WEBAPP),) + cd webapp && npm run lint +endif + +## Runs gofmt against all packages. +.PHONY: gofmt +gofmt: +ifneq ($(HAS_SERVER),) + @echo Running gofmt + @for package in $$(go list ./...); do \ + echo "Checking "$$package; \ + files=$$(go list -f '{{range .GoFiles}}{{$$.Dir}}/{{.}} {{end}}' $$package); \ + if [ "$$files" ]; then \ + gofmt_output=$$(gofmt -d -s $$files 2>&1); \ + if [ "$$gofmt_output" ]; then \ + echo "$$gofmt_output"; \ + echo "Gofmt failure"; \ + exit 1; \ + fi; \ + fi; \ + done + @echo Gofmt success +endif + +## Runs govet against all packages. +.PHONY: govet +govet: +ifneq ($(HAS_SERVER),) + @echo Running govet + @# Workaround because you can't install binaries without adding them to go.mod + env GO111MODULE=off $(GO) get golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow + $(GO) vet ./... + $(GO) vet -vettool=$(GOPATH)/bin/shadow ./... + @echo Govet success +endif + +## Runs golint against all packages. +.PHONY: golint +golint: + @echo Running lint + env GO111MODULE=off $(GO) get golang.org/x/lint/golint + $(GOPATH)/bin/golint -set_exit_status ./... + @echo lint success + ## Runs golangci-lint and eslint. .PHONY: check-style check-style: webapp/.npminstall golangci-lint @@ -61,6 +123,34 @@ ifneq ($(HAS_SERVER),) cd server && env GOOS=windows GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -o dist/plugin-windows-amd64.exe; endif +## Generates mock golang interfaces for testing +mock: +ifneq ($(HAS_SERVER),) + go install github.com/golang/mock/mockgen + mockgen -destination server/sl/mock_sl/mock_plugin_api.go github.com/mattermost/mattermost-plugin-solar-lottery/server/sl PluginAPI + # mockgen -destination server/utils/bot/mock_bot/mock_poster.go github.com/mattermost/mattermost-plugin-solar-lottery/server/utils/bot Poster + # mockgen -destination server/utils/bot/mock_bot/mock_admin.go github.com/mattermost/mattermost-plugin-solar-lottery/server/utils/bot Admin + # mockgen -destination server/store/mock_store/mock_store.go github.com/mattermost/mattermost-plugin-solar-lottery/server/store Store +endif + +## Generates mock golang interfaces for testing +clean_mock: +ifneq ($(HAS_SERVER),) + rm -rf ./server/solarlottery/mock_solarlottery + rm -rf ./server/utils/bot/mock_bot + rm -rf ./server/store/mock_store +endif + +## Builds the server, if it exists, including support for multiple architectures. +.PHONY: server +server: +ifneq ($(HAS_SERVER),) + mkdir -p server/dist; + cd server && env GOOS=linux GOARCH=amd64 $(GOBUILD) -o dist/plugin-linux-amd64; + cd server && env GOOS=darwin GOARCH=amd64 $(GOBUILD) -o dist/plugin-darwin-amd64; + cd server && env GOOS=windows GOARCH=amd64 $(GOBUILD) -o dist/plugin-windows-amd64.exe; +endif + ## Ensures NPM dependencies are installed without having to run this all the time. webapp/.npminstall: ifneq ($(HAS_WEBAPP),) @@ -112,11 +202,23 @@ endif dist: apply server webapp bundle ## Installs the plugin to a (development) server. -## It uses the API if appropriate environment variables are defined, -## and otherwise falls back to trying to copy the plugin to a sibling mattermost-server directory. .PHONY: deploy deploy: dist - ./build/bin/deploy $(PLUGIN_ID) dist/$(BUNDLE_NAME) +## It uses the API if appropriate environment variables are defined, +## or copying the files directly to a sibling mattermost-server directory. +ifneq ($(and $(MM_SERVICESETTINGS_SITEURL),$(MM_ADMIN_USERNAME),$(MM_ADMIN_PASSWORD),$(CURL)),) + @echo "Installing plugin via API" + $(eval TOKEN := $(shell curl -i --post301 --location $(MM_SERVICESETTINGS_SITEURL) -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/login -d '{"login_id": "$(MM_ADMIN_USERNAME)", "password": "$(MM_ADMIN_PASSWORD)"}' | grep Token | cut -f2 -d' ' 2> /dev/null)) + @curl -s --post301 --location $(MM_SERVICESETTINGS_SITEURL) -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins -F "plugin=@dist/$(BUNDLE_NAME)" -F "force=true" > /dev/null && \ + curl -s --post301 --location $(MM_SERVICESETTINGS_SITEURL) -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/enable > /dev/null && \ + echo "OK." || echo "Sorry, something went wrong." +else ifneq ($(wildcard ../mattermost-server/.*),) + @echo "Installing plugin via filesystem. Server restart and manual plugin enabling required" + mkdir -p ../mattermost-server/plugins + tar -C ../mattermost-server/plugins -zxvf dist/$(BUNDLE_NAME) +else + @echo "No supported deployment method available. Install plugin manually." +endif .PHONY: debug-deploy debug-deploy: debug-dist deploy @@ -172,3 +274,65 @@ endif # Help documentation à la https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html help: @cat Makefile | grep -v '\.PHONY' | grep -v '\help:' | grep -B1 -E '^[a-zA-Z0-9_.-]+:.*' | sed -e "s/:.*//" | sed -e "s/^## //" | grep -v '\-\-' | sed '1!G;h;$$!d' | awk 'NR%2{printf "\033[36m%-30s\033[0m",$$0;next;}1' | sort + +# sd is an easier-to-type alias for server-debug +.PHONY: sd +sd: server-debug + +# server-debug builds and deploys a debug version of the plugin for your architecture. +# Then resets the plugin to pick up the changes. +.PHONY: server-debug +server-debug: server-debug-deploy reset + +.PHONY: server-debug-deploy +server-debug-deploy: validate-go-version + ./build/bin/manifest apply + mkdir -p server/dist +ifeq ($(OS),Darwin) + cd server && env GOOS=darwin GOARCH=amd64 $(GOBUILD) -gcflags "all=-N -l" -o dist/plugin-darwin-amd64; +else ifeq ($(OS),Linux) + cd server && env GOOS=linux GOARCH=amd64 $(GOBUILD) -gcflags "all=-N -l" -o dist/plugin-linux-amd64; +else ifeq ($(OS),Windows_NT) + cd server && env GOOS=windows GOARCH=amd64 $(GOBUILD) -gcflags "all=-N -l" -o dist/plugin-windows-amd64.exe; +else + $(error make debug depends on uname to return your OS. If it does not return 'Darwin' (meaning OSX), 'Linux', or 'Windows_NT' (all recent versions of Windows), you will need to edit the Makefile for your own OS.) +endif + rm -rf dist/ + mkdir -p dist/$(PLUGIN_ID)/server/dist + cp $(MANIFEST_FILE) dist/$(PLUGIN_ID)/ + cp -r server/dist/* dist/$(PLUGIN_ID)/server/dist/ + mkdir -p ../mattermost-server/plugins + cp -r dist/* ../mattermost-server/plugins/ + +.PHONY: validate-go-version +validate-go-version: ## Validates the installed version of go against Mattermost's minimum requirement. + @if [ $(GO_MAJOR_VERSION) -gt $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION) ]; then \ + exit 0 ;\ + elif [ $(GO_MAJOR_VERSION) -lt $(MINIMUM_SUPPORTED_GO_MAJOR_VERSION) ]; then \ + echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\ + exit 1; \ + elif [ $(GO_MINOR_VERSION) -lt $(MINIMUM_SUPPORTED_GO_MINOR_VERSION) ] ; then \ + echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\ + exit 1; \ + fi + +# Reset the plugin +.PHONY: reset +reset: +ifeq ($(and $(MM_SERVICESETTINGS_SITEURL),$(MM_ADMIN_USERNAME),$(MM_ADMIN_PASSWORD),$(CURL)),) + $(error In order to use make reset, the following environment variables need to be defined: MM_SERVICESETTINGS_SITEURL, MM_ADMIN_USERNAME, MM_ADMIN_PASSWORD, and you need to have curl installed.) +endif + +# If we were debugging, we have to unattach the delve process or else we can't disable the plugin. +# NOTE: we are assuming the dlv was listening on port 2346, as in the debug-plugin.sh script. + @DELVE_PID=$(shell ps aux | grep "dlv attach.*2346" | grep -v "grep" | awk -F " " '{print $$2}') && \ + if [ "$$DELVE_PID" -gt 0 ] > /dev/null 2>&1 ; then \ + echo "Located existing delve process running with PID: $$DELVE_PID. Killing." ; \ + kill -9 $$DELVE_PID ; \ + fi + + @echo "\nRestarting plugin via API" + $(eval TOKEN := $(shell curl -i -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/login -d '{"login_id": "$(MM_ADMIN_USERNAME)", "password": "$(MM_ADMIN_PASSWORD)"}' | grep -o "Token: [0-9a-z]*" | cut -f2 -d' ' 2> /dev/null)) + @curl -s -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/disable > /dev/null && \ + curl -s -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/enable > /dev/null && \ + echo "OK." || echo "Sorry, something went wrong. Check that MM_ADMIN_USERNAME and MM_ADMIN_PASSWORD env variables are set correctly." \ No newline at end of file diff --git a/build/custom.mk b/build/custom.mk index efad4fb..743e6a4 100644 --- a/build/custom.mk +++ b/build/custom.mk @@ -1 +1 @@ -# Include custome targets and environment variables here +# Include custom targets and environment variables here From 91d701d1256e9068eed175c1b62cb5ff755c4a3a Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Wed, 5 Aug 2020 12:18:52 +0200 Subject: [PATCH 3/3] Cleanup Makefile --- Makefile | 61 +------------------------------------------------------- 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/Makefile b/Makefile index 45e9d16..591b27b 100644 --- a/Makefile +++ b/Makefile @@ -44,55 +44,6 @@ all: check-style test dist apply: ./build/bin/manifest apply -## Runs govet and gofmt against all packages. -.PHONY: check-style -check-style: webapp/.npminstall gofmt govet - @echo Checking for style guide compliance - -ifneq ($(HAS_WEBAPP),) - cd webapp && npm run lint -endif - -## Runs gofmt against all packages. -.PHONY: gofmt -gofmt: -ifneq ($(HAS_SERVER),) - @echo Running gofmt - @for package in $$(go list ./...); do \ - echo "Checking "$$package; \ - files=$$(go list -f '{{range .GoFiles}}{{$$.Dir}}/{{.}} {{end}}' $$package); \ - if [ "$$files" ]; then \ - gofmt_output=$$(gofmt -d -s $$files 2>&1); \ - if [ "$$gofmt_output" ]; then \ - echo "$$gofmt_output"; \ - echo "Gofmt failure"; \ - exit 1; \ - fi; \ - fi; \ - done - @echo Gofmt success -endif - -## Runs govet against all packages. -.PHONY: govet -govet: -ifneq ($(HAS_SERVER),) - @echo Running govet - @# Workaround because you can't install binaries without adding them to go.mod - env GO111MODULE=off $(GO) get golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow - $(GO) vet ./... - $(GO) vet -vettool=$(GOPATH)/bin/shadow ./... - @echo Govet success -endif - -## Runs golint against all packages. -.PHONY: golint -golint: - @echo Running lint - env GO111MODULE=off $(GO) get golang.org/x/lint/golint - $(GOPATH)/bin/golint -set_exit_status ./... - @echo lint success - ## Runs golangci-lint and eslint. .PHONY: check-style check-style: webapp/.npminstall golangci-lint @@ -113,16 +64,6 @@ golangci-lint: @echo Running golangci-lint golangci-lint run ./... -## Builds the server, if it exists, including support for multiple architectures. -.PHONY: server -server: -ifneq ($(HAS_SERVER),) - mkdir -p server/dist; - cd server && env GOOS=linux GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -o dist/plugin-linux-amd64; - cd server && env GOOS=darwin GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -o dist/plugin-darwin-amd64; - cd server && env GOOS=windows GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -o dist/plugin-windows-amd64.exe; -endif - ## Generates mock golang interfaces for testing mock: ifneq ($(HAS_SERVER),) @@ -335,4 +276,4 @@ endif $(eval TOKEN := $(shell curl -i -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/users/login -d '{"login_id": "$(MM_ADMIN_USERNAME)", "password": "$(MM_ADMIN_PASSWORD)"}' | grep -o "Token: [0-9a-z]*" | cut -f2 -d' ' 2> /dev/null)) @curl -s -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/disable > /dev/null && \ curl -s -H "Authorization: Bearer $(TOKEN)" -X POST $(MM_SERVICESETTINGS_SITEURL)/api/v4/plugins/$(PLUGIN_ID)/enable > /dev/null && \ - echo "OK." || echo "Sorry, something went wrong. Check that MM_ADMIN_USERNAME and MM_ADMIN_PASSWORD env variables are set correctly." \ No newline at end of file + echo "OK." || echo "Sorry, something went wrong. Check that MM_ADMIN_USERNAME and MM_ADMIN_PASSWORD env variables are set correctly."