From 8fa762b5ff9a93a1c1e4688c0d91ec26a2c4bcf4 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 5 May 2021 22:51:40 +0200 Subject: [PATCH 1/6] Make build dir configurable --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5a1b4592..7517e8de 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ # globals BINARY_NAME?=wakatime-cli +BUILD_DIR?="./build" COMMIT?=$(shell git rev-parse --short HEAD) DATE?=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ') REPO=github.com/wakatime/wakatime-cli @@ -103,12 +104,12 @@ build-windows-amd64: build-binary: CGO_ENABLED="0" GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -v \ -ldflags "${LD_FLAGS} -X ${REPO}/pkg/version.OS=$(GOOS) -X ${REPO}/pkg/version.Arch=$(GOARCH)" \ - -o ./build/$(BINARY_NAME)-$(GOOS)-$(GOARCH) + -o ${BUILD_DIR}/$(BINARY_NAME)-$(GOOS)-$(GOARCH) build-binary-windows: CGO_ENABLED="0" GOOS=$(GOOS) GOARCH=$(GOARCH) $(GOBUILD) -v \ -ldflags "${LD_FLAGS} -X ${REPO}/pkg/version.OS=$(GOOS) -X ${REPO}/pkg/version.Arch=$(GOARCH)" \ - -o ./build/$(BINARY_NAME)-$(GOOS)-$(GOARCH).exe + -o ${BUILD_DIR}/$(BINARY_NAME)-$(GOOS)-$(GOARCH).exe # install linter .PHONY: install-linter From 9c2aa0b8be554249d77f2b30d7fceac7f8093936 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 6 May 2021 00:22:20 +0200 Subject: [PATCH 2/6] Do not parse config for useragent and version commands --- cmd/legacy/run.go | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/cmd/legacy/run.go b/cmd/legacy/run.go index ff7bd0af..016484b9 100644 --- a/cmd/legacy/run.go +++ b/cmd/legacy/run.go @@ -21,6 +21,28 @@ import ( // Run executes legacy commands following the interface of the old python implementation of the WakaTime script. func Run(v *viper.Viper) { + if v.GetBool("useragent") { + log.Debugln("command: useragent") + + if plugin := v.GetString("plugin"); plugin != "" { + fmt.Println(heartbeat.UserAgent(plugin)) + + os.Exit(exitcode.Success) + } + + fmt.Println(heartbeat.UserAgentUnknownPlugin()) + + os.Exit(exitcode.Success) + } + + if v.GetBool("version") { + log.Debugln("command: version") + + runVersion(v.GetBool("verbose")) + + os.Exit(exitcode.Success) + } + if err := config.ReadInConfig(v, config.FilePath); err != nil { log.Errorf("failed to load configuration file: %s", err) @@ -50,28 +72,6 @@ func Run(v *viper.Viper) { log.SetVerbose(logfileParams.Verbose) - if v.GetBool("useragent") { - log.Debugln("command: useragent") - - if plugin := v.GetString("plugin"); plugin != "" { - fmt.Println(heartbeat.UserAgent(plugin)) - - os.Exit(exitcode.Success) - } - - fmt.Println(heartbeat.UserAgentUnknownPlugin()) - - os.Exit(exitcode.Success) - } - - if v.GetBool("version") { - log.Debugln("command: version") - - runVersion(v.GetBool("verbose")) - - os.Exit(exitcode.Success) - } - if v.IsSet("config-read") { log.Debugln("command: config-read") From 1eb5904ec84d5808bfb7e06c9cea65e358d171c8 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 8 May 2021 23:52:20 +0200 Subject: [PATCH 3/6] Add integration tests --- .github/workflows/on_push.yml | 69 ++++- .../workflows/on_push_protected_branches.yml | 8 +- Makefile | 4 + main_test.go | 282 ++++++++++++++++++ testdata/api_goals_id_response.json | 12 + testdata/api_heartbeats_request.json.tpl | 17 ++ testdata/api_heartbeats_response.json | 29 ++ testdata/api_summaries_response.json.tpl | 22 ++ testdata/main.go | 11 + testdata/wakatime.cfg | 0 10 files changed, 434 insertions(+), 20 deletions(-) create mode 100644 main_test.go create mode 100644 testdata/api_goals_id_response.json create mode 100644 testdata/api_heartbeats_request.json.tpl create mode 100644 testdata/api_heartbeats_response.json create mode 100644 testdata/api_summaries_response.json.tpl create mode 100644 testdata/main.go create mode 100644 testdata/wakatime.cfg diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index d7015da6..6ed75d53 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -1,4 +1,4 @@ -name: "Unit Tests" +name: "Tests" on: push: @@ -10,24 +10,24 @@ env: GO_VERSION: "1.16" jobs: - test: - name: Test + tests: + name: Unit tests runs-on: ubuntu-latest steps: - - + - name: "Checkout" uses: actions/checkout@v2 - - + - uses: actions/setup-go@v2 with: go-version: ${{ env.GO_VERSION }} - - + - name: "Pull dependencies" run: go mod vendor - - + - name: "Unit tests" run: make test - - + - name: "Linter" run: make lint - @@ -35,24 +35,61 @@ jobs: uses: shogo82148/actions-goveralls@v1 with: path-to-profile: coverage.out - - test-windows: - name: Test Windows + + integration-tests: + name: Integration tests + runs-on: ubuntu-latest + steps: + - + name: "Checkout" + uses: actions/checkout@v2 + - + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + - + name: "Pull dependencies" + run: go mod vendor + - + name: "Integration tests" + run: make test-integration + + + tests-windows: + name: Unit tests windows runs-on: windows-latest steps: - - + - name: "Checkout" uses: actions/checkout@v2 - - + - uses: actions/setup-go@v2 with: go-version: ${{ env.GO_VERSION }} - - + - name: "Pull dependencies" run: go mod vendor - - + - name: "Unit tests" run: make test - - + - name: "Linter" run: make lint + + integration-tests-windows: + name: Integration tests windows + runs-on: windows-latest + steps: + - + name: "Checkout" + uses: actions/checkout@v2 + - + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + - + name: "Pull dependencies" + run: go mod vendor + - + name: "Integration tests" + run: make test-integration diff --git a/.github/workflows/on_push_protected_branches.yml b/.github/workflows/on_push_protected_branches.yml index 9498027e..9f2459de 100644 --- a/.github/workflows/on_push_protected_branches.yml +++ b/.github/workflows/on_push_protected_branches.yml @@ -25,8 +25,8 @@ jobs: name: "Pull dependencies" run: go mod vendor - - name: "Unit tests" - run: make test + name: "Tests" + run: make test-integration - name: "Linter" run: make lint @@ -51,8 +51,8 @@ jobs: name: "Pull dependencies" run: go mod vendor - - name: "Unit tests" - run: make test + name: "Tests" + run: make test-integration - name: "Linter" run: make lint diff --git a/Makefile b/Makefile index 7517e8de..955a2ac4 100644 --- a/Makefile +++ b/Makefile @@ -127,3 +127,7 @@ lint: install-linter .PHONY: test test: go test -race -covermode=atomic -coverprofile=coverage.out ./... + +.PHONY: test-integration +test-integration: + go test -race -tags=integration ./main_test.go diff --git a/main_test.go b/main_test.go new file mode 100644 index 00000000..47c5c69f --- /dev/null +++ b/main_test.go @@ -0,0 +1,282 @@ +// +build integration + +package main_test + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "net/url" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + "github.com/wakatime/wakatime-cli/pkg/heartbeat" + "github.com/wakatime/wakatime-cli/pkg/version" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const testVersion = "v0.0.1-test" + +// nolint: gochecknoglobals +var binaryPath string + +func TestMain(m *testing.M) { + // build binary + cmd := exec.Command("make", fmt.Sprintf("build-%s-%s", runtime.GOOS, runtime.GOARCH)) + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, "COMMIT=ac109fe") + cmd.Env = append(cmd.Env, "DATE=2021-05-05T14:05:11Z") + cmd.Env = append(cmd.Env, fmt.Sprintf("VERSION=%s", testVersion)) + + run(cmd) + + binaryPath = filepath.Join("./build", fmt.Sprintf( + "wakatime-cli-%s-%s", + runtime.GOOS, + runtime.GOARCH, + )) + + if runtime.GOOS == "windows" { + binaryPath = binaryPath + ".exe" + } + + // run tests + defer os.Exit(m.Run()) +} + +func TestSendHeartbeats(t *testing.T) { + testSendHeartbeats(t, "testdata/main.go", "wakatime-cli") +} + +func TestSendHeartbeats_EntityFileInTempDir(t *testing.T) { + tmpDir := t.TempDir() + run(exec.Command("cp", "./testdata/main.go", tmpDir)) + + testSendHeartbeats(t, filepath.Join(tmpDir, "main.go"), "") +} + +func testSendHeartbeats(t *testing.T, entity, project string) { + apiUrl, router, close := setupTestServer() + defer close() + + var numCalls int + + router.HandleFunc("/v1/users/current/heartbeats.bulk", func(w http.ResponseWriter, req *http.Request) { + numCalls++ + + // check headers + assert.Equal(t, http.MethodPost, req.Method) + assert.Equal(t, []string{"application/json"}, req.Header["Accept"]) + assert.Equal(t, []string{"application/json"}, req.Header["Content-Type"]) + assert.Equal(t, []string{"Basic MDAwMDAwMDAtMDAwMC00MDAwLTgwMDAtMDAwMDAwMDAwMDAw"}, req.Header["Authorization"]) + assert.Equal(t, []string{heartbeat.UserAgentUnknownPlugin()}, req.Header["User-Agent"]) + + // check body + expectedBodyTpl, err := ioutil.ReadFile("testdata/api_heartbeats_request.json.tpl") + require.NoError(t, err) + + entityPath, err := filepath.Abs(entity) + require.NoError(t, err) + + entityPath = strings.ReplaceAll(entityPath, `\`, `/`) + expectedBody := fmt.Sprintf( + string(expectedBodyTpl), + entityPath, + project, + heartbeat.UserAgentUnknownPlugin(), + ) + + body, err := ioutil.ReadAll(req.Body) + require.NoError(t, err) + + assert.JSONEq(t, string(expectedBody), string(body)) + + // write response + f, err := os.Open("testdata/api_heartbeats_response.json") + require.NoError(t, err) + + w.WriteHeader(http.StatusCreated) + _, err = io.Copy(w, f) + require.NoError(t, err) + }) + + version.Version = testVersion + + cmd := exec.Command( + binaryPath, + "--api-url", apiUrl, + "--key", "00000000-0000-4000-8000-000000000000", + "--config", "testdata/wakatime.cfg", + "--entity", entity, + "--cursorpos", "12", + "--lineno", "42", + "--lines-in-file", "100", + "--time", "1585598059", + "--hide-branch-names", ".*", + "--log-to-stdout", + "--write", + "--verbose", + ) + + run(cmd) + + assert.Eventually(t, func() bool { return numCalls == 1 }, time.Second, 50*time.Millisecond) +} + +func TestTodayGoal(t *testing.T) { + apiUrl, router, close := setupTestServer() + defer close() + + var numCalls int + + router.HandleFunc("/v1/users/current/goals/11111111-1111-4111-8111-111111111111", func(w http.ResponseWriter, req *http.Request) { + numCalls++ + + // check request + assert.Equal(t, http.MethodGet, req.Method) + t.Logf("%#v\n", req.Header) + assert.Equal(t, []string{"application/json"}, req.Header["Accept"]) + assert.Equal(t, []string{"Basic MDAwMDAwMDAtMDAwMC00MDAwLTgwMDAtMDAwMDAwMDAwMDAw"}, req.Header["Authorization"]) + assert.Equal(t, []string{heartbeat.UserAgentUnknownPlugin()}, req.Header["User-Agent"]) + + // write response + f, err := os.Open("testdata/api_goals_id_response.json") + require.NoError(t, err) + + w.WriteHeader(http.StatusOK) + _, err = io.Copy(w, f) + require.NoError(t, err) + }) + + version.Version = testVersion + + out := run(exec.Command( + binaryPath, + "--api-url", apiUrl, + "--key", "00000000-0000-4000-8000-000000000000", + "--config", "testdata/wakatime.cfg", + "--today-goal", "11111111-1111-4111-8111-111111111111", + "--verbose", + )) + + assert.Equal(t, "3 hrs 23 mins\n", out) + + assert.Eventually(t, func() bool { return numCalls == 1 }, time.Second, 50*time.Millisecond) +} + +func TestTodaySummary(t *testing.T) { + apiUrl, router, close := setupTestServer() + defer close() + + var numCalls int + + router.HandleFunc("/v1/users/current/summaries", func(w http.ResponseWriter, req *http.Request) { + numCalls++ + + // check request + assert.Equal(t, http.MethodGet, req.Method) + t.Logf("%#v\n", req.Header) + assert.Equal(t, []string{"application/json"}, req.Header["Accept"]) + assert.Equal(t, []string{"Basic MDAwMDAwMDAtMDAwMC00MDAwLTgwMDAtMDAwMDAwMDAwMDAw"}, req.Header["Authorization"]) + assert.Equal(t, []string{heartbeat.UserAgentUnknownPlugin()}, req.Header["User-Agent"]) + + values, err := url.ParseQuery(req.URL.RawQuery) + require.NoError(t, err) + + today := time.Now().Format("2006-01-02") + + assert.Equal(t, url.Values(map[string][]string{ + "start": {today}, + "end": {today}, + }), values) + + // write response + responseBodyTpl, err := ioutil.ReadFile("testdata/api_summaries_response.json.tpl") + require.NoError(t, err) + + responseBody := fmt.Sprintf(string(responseBodyTpl), today) + + w.WriteHeader(http.StatusOK) + _, err = w.Write([]byte(responseBody)) + require.NoError(t, err) + }) + + version.Version = testVersion + + out := run(exec.Command( + binaryPath, + "--api-url", apiUrl, + "--key", "00000000-0000-4000-8000-000000000000", + "--config", "testdata/wakatime.cfg", + "--today", + "--verbose", + )) + + assert.Equal(t, "10 secs\n", out) + + assert.Eventually(t, func() bool { return numCalls == 1 }, time.Second, 50*time.Millisecond) +} + +func TestUseragent(t *testing.T) { + out := run(exec.Command(binaryPath, "--useragent")) + + assert.Equal(t, fmt.Sprintf("%s\n", heartbeat.UserAgentUnknownPlugin()), out) +} + +func TestUseragentWithPlugin(t *testing.T) { + out := run(exec.Command(binaryPath, "--useragent", "--plugin", "Wakatime/1.0.4")) + + assert.Equal(t, fmt.Sprintf("%s\n", heartbeat.UserAgent("Wakatime/1.0.4")), out) +} + +func TestVersion(t *testing.T) { + out := run(exec.Command(binaryPath, "--version")) + + assert.Equal(t, "v0.0.1-test\n", out) +} + +func TestVersionVerbose(t *testing.T) { + out := run(exec.Command(binaryPath(t), "--version", "--verbose")) + + assert.Regexp(t, regexp.MustCompile(fmt.Sprintf( + "wakatime-cli\n Version: v0.0.1-test\n Commit: [0-9a-f]{7}\n Built: [0-9-:TZ]{20}\n OS/Arch: %s/%s\n", + runtime.GOOS, + runtime.GOARCH, + )), out) +} + +func run(cmd *exec.Cmd) string { + fmt.Println(cmd.String()) + var stdout bytes.Buffer + cmd.Stdout = &stdout + + var stderr bytes.Buffer + cmd.Stderr = &stderr + + err := cmd.Run() + if err != nil { + fmt.Println(stdout.String()) + fmt.Println(stderr.String()) + fmt.Printf("failed to run command %s\n", cmd) + os.Exit(1) + } + + return stdout.String() +} + +func setupTestServer() (string, *http.ServeMux, func()) { + router := http.NewServeMux() + srv := httptest.NewServer(router) + + return srv.URL, router, func() { srv.Close() } +} diff --git a/testdata/api_goals_id_response.json b/testdata/api_goals_id_response.json new file mode 100644 index 00000000..bdf31ac5 --- /dev/null +++ b/testdata/api_goals_id_response.json @@ -0,0 +1,12 @@ +{ + "data": { + "chart_data": [ + { + "actual_seconds_text": "4 hrs 54 mins" + }, + { + "actual_seconds_text": "3 hrs 23 mins" + } + ] + } +} diff --git a/testdata/api_heartbeats_request.json.tpl b/testdata/api_heartbeats_request.json.tpl new file mode 100644 index 00000000..ec451fb1 --- /dev/null +++ b/testdata/api_heartbeats_request.json.tpl @@ -0,0 +1,17 @@ +[ + { + "branch": null, + "category": "coding", + "cursorpos": 12, + "dependencies": ["os"], + "entity": "%s", + "is_write": true, + "language": "Go", + "lineno": 42, + "lines": 100, + "project": "%s", + "type": "file", + "time": 1585598059, + "user_agent": "%s" + } +] diff --git a/testdata/api_heartbeats_response.json b/testdata/api_heartbeats_response.json new file mode 100644 index 00000000..b214dc5f --- /dev/null +++ b/testdata/api_heartbeats_response.json @@ -0,0 +1,29 @@ +{ + "responses": [ + [ + { + "data": { + "branch": "heartbeat", + "category": "coding", + "created_at": "2020-04-14T21:27:15Z", + "cursorpos": 12, + "dependencies": ["dep1", "dep2"], + "entity": "/tmp/main.go", + "id": "845a922e-9e65-4775-bd68-bb3196d2e06a", + "is_write": true, + "language": "Go", + "lineno": 42, + "lines": 100, + "machine_name_id": null, + "project": "wakatime-cli", + "type": "file", + "time": 1585598059.0, + "user_agent_id": null, + "user_agent": "wakatime/13.0.6", + "user_id": "9c4a41c0-eb11-4cf5-84b8-d5b7f5e91bea" + } + }, + 201 + ] + ] +} diff --git a/testdata/api_summaries_response.json.tpl b/testdata/api_summaries_response.json.tpl new file mode 100644 index 00000000..2682738e --- /dev/null +++ b/testdata/api_summaries_response.json.tpl @@ -0,0 +1,22 @@ +{ + "data": [ + { + "categories": [], + "grand_total": { + "text": "10 secs" + }, + "range": { + "date": "%s" + } + }, + { + "categories": [], + "grand_total": { + "text": "20 secs" + }, + "range": { + "date": "2020-04-02" + } + } + ] +} diff --git a/testdata/main.go b/testdata/main.go new file mode 100644 index 00000000..c6e84062 --- /dev/null +++ b/testdata/main.go @@ -0,0 +1,11 @@ +package main + +import ( + "fmt" + "os" +) + +func main() { + fmt.Println("hello world") + os.Exit(0) +} diff --git a/testdata/wakatime.cfg b/testdata/wakatime.cfg new file mode 100644 index 00000000..e69de29b From 86a836550ba57fc69bf90fd1fc0f0027e3d067b5 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 13 May 2021 00:13:44 +0200 Subject: [PATCH 4/6] Build binary in workflow --- .github/workflows/on_push.yml | 14 ++++++++-- main_test.go | 52 ++++++++++++++--------------------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 6ed75d53..b01f37ec 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -8,6 +8,7 @@ on: env: GO_VERSION: "1.16" + TEST_VERSION: "v0.0.1-test" jobs: tests: @@ -50,6 +51,11 @@ jobs: - name: "Pull dependencies" run: go mod vendor + - + name: "Build binary" + env: + VERSION: ${{ env.TEST_VERSION }} + run: make build-linux-amd64 - name: "Integration tests" run: make test-integration @@ -72,9 +78,6 @@ jobs: - name: "Unit tests" run: make test - - - name: "Linter" - run: make lint integration-tests-windows: name: Integration tests windows @@ -90,6 +93,11 @@ jobs: - name: "Pull dependencies" run: go mod vendor + - + name: "Build binary" + env: + VERSION: ${{ env.TEST_VERSION }} + run: make build-windows-amd64 - name: "Integration tests" run: make test-integration diff --git a/main_test.go b/main_test.go index 47c5c69f..9d3e5ab8 100644 --- a/main_test.go +++ b/main_test.go @@ -13,6 +13,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "runtime" "strings" "testing" @@ -25,33 +26,22 @@ import ( "github.com/stretchr/testify/require" ) -const testVersion = "v0.0.1-test" - -// nolint: gochecknoglobals -var binaryPath string - -func TestMain(m *testing.M) { - // build binary - cmd := exec.Command("make", fmt.Sprintf("build-%s-%s", runtime.GOOS, runtime.GOARCH)) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "COMMIT=ac109fe") - cmd.Env = append(cmd.Env, "DATE=2021-05-05T14:05:11Z") - cmd.Env = append(cmd.Env, fmt.Sprintf("VERSION=%s", testVersion)) - - run(cmd) - - binaryPath = filepath.Join("./build", fmt.Sprintf( - "wakatime-cli-%s-%s", - runtime.GOOS, - runtime.GOARCH, - )) +const ( + binaryPathLinux = "./build/wakatime-cli-linux-amd64" + binaryPathWindows = "./build/wakatime-cli-windows-amd64.exe" + testVersion = "v0.0.1-test" +) - if runtime.GOOS == "windows" { - binaryPath = binaryPath + ".exe" +func binaryPath(t *testing.T) string { + switch runtime.GOOS { + case "linux": + return binaryPathLinux + case "windows": + return binaryPathWindows + default: + t.Fatalf("OS %q not supported", runtime.GOOS) + return "" } - - // run tests - defer os.Exit(m.Run()) } func TestSendHeartbeats(t *testing.T) { @@ -113,7 +103,7 @@ func testSendHeartbeats(t *testing.T, entity, project string) { version.Version = testVersion cmd := exec.Command( - binaryPath, + binaryPath(t), "--api-url", apiUrl, "--key", "00000000-0000-4000-8000-000000000000", "--config", "testdata/wakatime.cfg", @@ -161,7 +151,7 @@ func TestTodayGoal(t *testing.T) { version.Version = testVersion out := run(exec.Command( - binaryPath, + binaryPath(t), "--api-url", apiUrl, "--key", "00000000-0000-4000-8000-000000000000", "--config", "testdata/wakatime.cfg", @@ -214,7 +204,7 @@ func TestTodaySummary(t *testing.T) { version.Version = testVersion out := run(exec.Command( - binaryPath, + binaryPath(t), "--api-url", apiUrl, "--key", "00000000-0000-4000-8000-000000000000", "--config", "testdata/wakatime.cfg", @@ -228,19 +218,19 @@ func TestTodaySummary(t *testing.T) { } func TestUseragent(t *testing.T) { - out := run(exec.Command(binaryPath, "--useragent")) + out := run(exec.Command(binaryPath(t), "--useragent")) assert.Equal(t, fmt.Sprintf("%s\n", heartbeat.UserAgentUnknownPlugin()), out) } func TestUseragentWithPlugin(t *testing.T) { - out := run(exec.Command(binaryPath, "--useragent", "--plugin", "Wakatime/1.0.4")) + out := run(exec.Command(binaryPath(t), "--useragent", "--plugin", "Wakatime/1.0.4")) assert.Equal(t, fmt.Sprintf("%s\n", heartbeat.UserAgent("Wakatime/1.0.4")), out) } func TestVersion(t *testing.T) { - out := run(exec.Command(binaryPath, "--version")) + out := run(exec.Command(binaryPath(t), "--version")) assert.Equal(t, "v0.0.1-test\n", out) } From 5658bbcd71b0a30909ec0a9b8e9e2517159ae06b Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 13 May 2021 00:42:52 +0200 Subject: [PATCH 5/6] Run integration tests on macos --- .github/workflows/on_push.yml | 41 +++++++++++++++++++++++++++++++++++ main_test.go | 6 ++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index b01f37ec..1235437d 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -101,3 +101,44 @@ jobs: - name: "Integration tests" run: make test-integration + + test-macos: + name: Unit tests macos + runs-on: macos-latest + steps: + - + name: "Checkout" + uses: actions/checkout@v2 + - + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + - + name: "Pull dependencies" + run: go mod vendor + - + name: "Unit tests" + run: make test + + integration-tests-macos: + name: Integration tests macos + runs-on: macos-latest + steps: + - + name: "Checkout" + uses: actions/checkout@v2 + - + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + - + name: "Pull dependencies" + run: go mod vendor + - + name: "Build binary" + env: + VERSION: ${{ env.TEST_VERSION }} + run: make build-darwin-amd64 + - + name: "Integration tests" + run: make test-integration diff --git a/main_test.go b/main_test.go index 9d3e5ab8..4460fb26 100644 --- a/main_test.go +++ b/main_test.go @@ -24,9 +24,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/yookoala/realpath" ) const ( + binaryPathDarwin = "./build/wakatime-cli-darwin-amd64" binaryPathLinux = "./build/wakatime-cli-linux-amd64" binaryPathWindows = "./build/wakatime-cli-windows-amd64.exe" testVersion = "v0.0.1-test" @@ -34,6 +36,8 @@ const ( func binaryPath(t *testing.T) string { switch runtime.GOOS { + case "darwin": + return binaryPathDarwin case "linux": return binaryPathLinux case "windows": @@ -75,7 +79,7 @@ func testSendHeartbeats(t *testing.T, entity, project string) { expectedBodyTpl, err := ioutil.ReadFile("testdata/api_heartbeats_request.json.tpl") require.NoError(t, err) - entityPath, err := filepath.Abs(entity) + entityPath, err := realpath.Realpath(entity) require.NoError(t, err) entityPath = strings.ReplaceAll(entityPath, `\`, `/`) From eda25f4883390b745438c083057da35e21f86dd0 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 15 May 2021 00:08:54 +0200 Subject: [PATCH 6/6] Merge on_push and on_push_protected_branches workflows --- .github/workflows/on_push.yml | 55 +++++++++-- .../workflows/on_push_protected_branches.yml | 96 ------------------- 2 files changed, 45 insertions(+), 106 deletions(-) delete mode 100644 .github/workflows/on_push_protected_branches.yml diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 1235437d..c532b555 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -1,17 +1,13 @@ name: "Tests" -on: - push: - branches-ignore: - - "develop" - - "master" +on: push env: GO_VERSION: "1.16" TEST_VERSION: "v0.0.1-test" jobs: - tests: + test: name: Unit tests runs-on: ubuntu-latest steps: @@ -37,7 +33,7 @@ jobs: with: path-to-profile: coverage.out - integration-tests: + test-integration: name: Integration tests runs-on: ubuntu-latest steps: @@ -61,7 +57,7 @@ jobs: run: make test-integration - tests-windows: + test-windows: name: Unit tests windows runs-on: windows-latest steps: @@ -79,7 +75,7 @@ jobs: name: "Unit tests" run: make test - integration-tests-windows: + test-integration-windows: name: Integration tests windows runs-on: windows-latest steps: @@ -120,7 +116,7 @@ jobs: name: "Unit tests" run: make test - integration-tests-macos: + test-integration-macos: name: Integration tests macos runs-on: macos-latest steps: @@ -142,3 +138,42 @@ jobs: - name: "Integration tests" run: make test-integration + + release: + name: Release + if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' }} + runs-on: ubuntu-latest + needs: [test, test-integration, test-windows, test-integration-windows, test-macos, test-integration-macos] + steps: + - + name: "Checkout" + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - + name: "Calculate semver tag" + id: semver-tag + uses: wakatime/semver-action@v1.2.2 + with: + prerelease_id: "alpha" + - + name: Changelog + uses: gandarez/changelog-action@v1.0.4 + id: changelog + with: + current_tag: ${{ github.sha }} + previous_tag: ${{ steps.semver-tag.outputs.ancestor_tag }} + exclude: | + ^Merge pull request .* + - + name: "Create release" + uses: softprops/action-gh-release@v1 + with: + name: ${{ steps.semver-tag.outputs.semver_tag }} + tag_name: ${{ steps.semver-tag.outputs.semver_tag }} + body: ${{ steps.changelog.outputs.changelog }} + prerelease: ${{ steps.semver-tag.outputs.is_prerelease }} + env: + # PAT is mandatory here to trigger new workflows + # https://docs.github.com/en/actions/reference/authentication-in-a-workflow#using-the-github_token-in-a-workflow + GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/on_push_protected_branches.yml b/.github/workflows/on_push_protected_branches.yml deleted file mode 100644 index 9f2459de..00000000 --- a/.github/workflows/on_push_protected_branches.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: "Create Release" - -on: - push: - branches: - - "develop" - - "master" - -env: - GO_VERSION: "1.16" - -jobs: - test: - name: Test - runs-on: ubuntu-latest - steps: - - - name: "Checkout" - uses: actions/checkout@v2 - - - uses: actions/setup-go@v2 - with: - go-version: ${{ env.GO_VERSION }} - - - name: "Pull dependencies" - run: go mod vendor - - - name: "Tests" - run: make test-integration - - - name: "Linter" - run: make lint - - - name: "Send coverage" - uses: shogo82148/actions-goveralls@v1 - with: - path-to-profile: coverage.out - - test-windows: - name: Test Windows - runs-on: windows-latest - steps: - - - name: "Checkout" - uses: actions/checkout@v2 - - - uses: actions/setup-go@v2 - with: - go-version: ${{ env.GO_VERSION }} - - - name: "Pull dependencies" - run: go mod vendor - - - name: "Tests" - run: make test-integration - - - name: "Linter" - run: make lint - - release: - name: Release - runs-on: ubuntu-latest - needs: [test, test-windows] - steps: - - - name: "Checkout" - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: "Calculate semver tag" - id: semver-tag - uses: wakatime/semver-action@v1.2.2 - with: - prerelease_id: "alpha" - - - name: Changelog - uses: gandarez/changelog-action@v1.0.4 - id: changelog - with: - current_tag: ${{ github.sha }} - previous_tag: ${{ steps.semver-tag.outputs.ancestor_tag }} - exclude: | - ^Merge pull request .* - - - name: "Create release" - uses: softprops/action-gh-release@v1 - with: - name: ${{ steps.semver-tag.outputs.semver_tag }} - tag_name: ${{ steps.semver-tag.outputs.semver_tag }} - body: ${{ steps.changelog.outputs.changelog }} - prerelease: ${{ steps.semver-tag.outputs.is_prerelease }} - env: - # PAT is mandatory here to trigger new workflows - # https://docs.github.com/en/actions/reference/authentication-in-a-workflow#using-the-github_token-in-a-workflow - GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}