Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v.5.5.0
with:
go-version: '^1.17.5'
go-version: '^1.24.3'
- name: golangci-lint
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
with:
version: latest
args: --timeout=5m
- run: make test

1 change: 1 addition & 0 deletions .go-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.24.3
11 changes: 11 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# https://golangci-lint.run/usage/configuration/
version: '2'
linters:
default: standard
disable:
- errcheck
- unused
Comment on lines +6 to +7
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you intend to circle back and enable either of these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wanted to avoid adding any more changes to this PR.

formatters:
enable:
- gofmt
- goimports
2 changes: 1 addition & 1 deletion Brewfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
brew 'go'
brew 'hub'
brew 'gh'
50 changes: 19 additions & 31 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,56 +1,44 @@
SHELL = /bin/sh

VERSION=1.6.1
VERSION=1.7.0
BUILD=`git rev-parse HEAD`

LDFLAGS=-ldflags "-w -s \
-X github.com/Betterment/testtrack-cli/cmds.version=${VERSION} \
-X github.com/Betterment/testtrack-cli/cmds.build=${BUILD}"

PACKAGES=$$(find . -maxdepth 1 -type d ! -path '.' ! -path './.*' ! -path './vendor' ! -path './dist' ! -path './script' ! -path './doc')
LINTEXCLUDES="123nothingyet123"

all: test

install:
@go install ${LDFLAGS} github.com/Betterment/testtrack-cli/testtrack

dist:
@mkdir dist &&\
GOOS=linux GOARCH=amd64 go build -o "dist/testtrack.linux" ${LDFLAGS} github.com/Betterment/testtrack-cli/testtrack &&\
GOOS=darwin GOARCH=amd64 go build -o "dist/testtrack.darwin-amd64" ${LDFLAGS} github.com/Betterment/testtrack-cli/testtrack &&\
@mkdir dist && \
GOOS=linux GOARCH=amd64 go build -o "dist/testtrack.linux" ${LDFLAGS} github.com/Betterment/testtrack-cli/testtrack && \
GOOS=darwin GOARCH=amd64 go build -o "dist/testtrack.darwin-amd64" ${LDFLAGS} github.com/Betterment/testtrack-cli/testtrack && \
GOOS=darwin GOARCH=arm64 go build -o "dist/testtrack.darwin-arm64" ${LDFLAGS} github.com/Betterment/testtrack-cli/testtrack

release: distclean dist
@hub release create\
-a dist/testtrack.linux\
-a dist/testtrack.darwin-amd64\
-a dist/testtrack.darwin-arm64\
-m "TestTrack CLI ${VERSION}"\
-t "${BUILD}"\
v${VERSION}
@(gh release view v${VERSION} > /dev/null 2>&1 \
&& echo "v${VERSION} has already been released.") \
|| gh release create v${VERSION} \
dist/testtrack.linux \
dist/testtrack.darwin-amd64 \
dist/testtrack.darwin-arm64 \
--title "TestTrack CLI ${VERSION}" \
--target "${BUILD}" \
--generate-notes

test:
@go install golang.org/x/tools/cmd/goimports@latest
@go install golang.org/x/lint/golint@latest
@GOIMPORTS_RESULT=$$($$(go env GOPATH)/bin/goimports -l ${PACKAGES} | grep -v ${LINTEXCLUDES});\
if [ $$(echo "$$GOIMPORTS_RESULT\c" | head -c1 | wc -c) -ne 0 ];\
then\
echo "Style violations found. Run the following command to fix:";\
echo;\
echo "$$(go env GOPATH)/bin/goimports -w" $$GOIMPORTS_RESULT;\
echo;\
exit 1;\
fi
@go vet ${PACKAGES}
@GOLINT_RESULT=$$($$(go env GOPATH)/bin/golint ${PACKAGES} | grep -v ${LINTEXCLUDES});\
if [ $$(echo "$$GOLINT_RESULT\c" | head -c1 | wc -c) -ne 0 ];\
then\
echo $$GOLINT_RESULT;\
exit 1;\
fi
@go test ${PACKAGES}

lint:
golangci-lint version &>/dev/null || brew install golangci-lint
golangci-lint fmt --verbose
golangci-lint run --verbose --timeout 5m

cover:
@echo "What package do you want a coverage report for? \c"
@read PACKAGE &&\
Expand All @@ -68,4 +56,4 @@ clean:
distclean: clean
@rm -rf dist

.PHONY: all build install check clean distclean test
.PHONY: all build install clean distclean test
3 changes: 1 addition & 2 deletions cmds/generate_build_timestamp.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmds

import (
"io/ioutil"
"os"
"time"

Expand Down Expand Up @@ -36,5 +35,5 @@ func generateBuildTimestamp() error {
return err
}

return ioutil.WriteFile("testtrack/build_timestamp", timestamp, 0644)
return os.WriteFile("testtrack/build_timestamp", timestamp, 0644)
}
3 changes: 1 addition & 2 deletions cmds/init_project.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmds

import (
"io/ioutil"
"log"
"os"

Expand Down Expand Up @@ -40,7 +39,7 @@ func initProject() error {
}
keepfile.Close()

if err := ioutil.WriteFile("testtrack/.gitignore", []byte("build_timestamp\n"), 0644); err != nil {
if err := os.WriteFile("testtrack/.gitignore", []byte("build_timestamp\n"), 0644); err != nil {
log.Fatal(err)
}

Expand Down
8 changes: 3 additions & 5 deletions fakeassignments/fakeassignments.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package fakeassignments

import (
"io/ioutil"
"os"

"github.com/Betterment/testtrack-cli/paths"

"gopkg.in/yaml.v2"
)

Expand All @@ -20,12 +18,12 @@ func Read() (*map[string]string, error) {
if err != nil {
return nil, err
}
err = ioutil.WriteFile(*configDir+"/assignments.yml", []byte("{}"), 0644)
err = os.WriteFile(*configDir+"/assignments.yml", []byte("{}"), 0644)
if err != nil {
return nil, err
}
}
assignmentsBytes, err := ioutil.ReadFile(*configDir + "/assignments.yml")
assignmentsBytes, err := os.ReadFile(*configDir + "/assignments.yml")
if err != nil {
return nil, err
}
Expand All @@ -47,7 +45,7 @@ func Write(assignments *map[string]string) error {
if err != nil {
return err
}
err = ioutil.WriteFile(*configDir+"/assignments.yml", bytes, 0644)
err = os.WriteFile(*configDir+"/assignments.yml", bytes, 0644)
if err != nil {
return err
}
Expand Down
18 changes: 13 additions & 5 deletions fakeserver/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package fakeserver
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"strings"

Expand Down Expand Up @@ -341,7 +341,7 @@ func postV1AssignmentOverride(r *http.Request) error {
Variant: r.PostForm.Get("variant"),
}
case strings.HasPrefix(contentType, "application/json"):
requestBytes, err := ioutil.ReadAll(r.Body)
requestBytes, err := io.ReadAll(r.Body)
if err != nil {
return err
}
Expand All @@ -353,6 +353,10 @@ func postV1AssignmentOverride(r *http.Request) error {
return fmt.Errorf("got unexpected content type %s", contentType)
}
assignments, err := fakeassignments.Read()
if err != nil {
return err
}
Comment on lines +356 to +358
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catches, these.


(*assignments)[assignment.SplitName] = assignment.Variant
err = fakeassignments.Write(assignments)
if err != nil {
Expand All @@ -366,7 +370,7 @@ func postV2AssignmentOverride(r *http.Request) error {
contentType := r.Header.Get("content-type")
switch {
case strings.HasPrefix(contentType, "application/json"):
requestBytes, err := ioutil.ReadAll(r.Body)
requestBytes, err := io.ReadAll(r.Body)
if err != nil {
return err
}
Expand All @@ -380,6 +384,10 @@ func postV2AssignmentOverride(r *http.Request) error {
return fmt.Errorf("got unexpected content type %s", contentType)
}
storedAssignments, err := fakeassignments.Read()
if err != nil {
return err
}

for _, assignment := range assignments {
(*storedAssignments)[assignment.SplitName] = assignment.Variant
}
Expand Down Expand Up @@ -453,12 +461,12 @@ func getV1SplitDetail() (interface{}, error) {
Location: "location",
Platform: "platform",
VariantDetails: []v1VariantDetail{
v1VariantDetail{
{
Name: "variant_a",
Description: "this is a fake description",
ScreenshotURL: "https://example.org/a",
},
v1VariantDetail{
{
Name: "variant_b",
Description: "this is another fake description",
ScreenshotURL: "https://example.org/b",
Expand Down
19 changes: 9 additions & 10 deletions fakeserver/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package fakeserver

import (
"bytes"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
Expand Down Expand Up @@ -41,7 +40,7 @@ something_something_enabled: "true"
func TestMain(m *testing.M) {
current, exists := os.LookupEnv("TESTTRACK_FAKE_SERVER_CONFIG_DIR")

dir, err := ioutil.TempDir("", "testtrack-cli")
dir, err := os.MkdirTemp("", "testtrack-cli")
if err != nil {
log.Fatal(err)
}
Expand All @@ -53,12 +52,12 @@ func TestMain(m *testing.M) {
}

schemaContent := []byte(testSchema)
if err := ioutil.WriteFile(filepath.Join(schemasDir, "test.yml"), schemaContent, 0644); err != nil {
if err := os.WriteFile(filepath.Join(schemasDir, "test.yml"), schemaContent, 0644); err != nil {
log.Fatal(err)
}

assignmentsContent := []byte(testAssignments)
if err := ioutil.WriteFile(filepath.Join(dir, "assignments.yml"), assignmentsContent, 0644); err != nil {
if err := os.WriteFile(filepath.Join(dir, "assignments.yml"), assignmentsContent, 0644); err != nil {
log.Fatal(err)
}

Expand Down Expand Up @@ -230,7 +229,7 @@ func TestCors(t *testing.T) {
h.ServeHTTP(w, request)

require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, "", w.HeaderMap.Get("Access-Control-Allow-Origin"))
require.Equal(t, "", w.Result().Header.Get("Access-Control-Allow-Origin"))
})

t.Run("it passes cors with an allowed origin", func(t *testing.T) {
Expand All @@ -243,7 +242,7 @@ func TestCors(t *testing.T) {
h.ServeHTTP(w, request)

require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, "http://www.allowed.com", w.HeaderMap.Get("Access-Control-Allow-Origin"))
require.Equal(t, "http://www.allowed.com", w.Result().Header.Get("Access-Control-Allow-Origin"))
})

t.Run("it passes cors from localhost", func(t *testing.T) {
Expand All @@ -256,7 +255,7 @@ func TestCors(t *testing.T) {
h.ServeHTTP(w, request)

require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, "http://localhost:3000", w.HeaderMap.Get("Access-Control-Allow-Origin"))
require.Equal(t, "http://localhost:3000", w.Result().Header.Get("Access-Control-Allow-Origin"))
})

t.Run("it passes cors from loopback ip", func(t *testing.T) {
Expand All @@ -269,7 +268,7 @@ func TestCors(t *testing.T) {
h.ServeHTTP(w, request)

require.Equal(t, http.StatusOK, w.Code)
require.Equal(t, "http://127.0.0.1:3000", w.HeaderMap.Get("Access-Control-Allow-Origin"))
require.Equal(t, "http://127.0.0.1:3000", w.Result().Header.Get("Access-Control-Allow-Origin"))
})

os.Unsetenv("TESTTRACK_ALLOWED_ORIGINS")
Expand Down Expand Up @@ -305,11 +304,11 @@ func TestPersistAssignmentV2(t *testing.T) {

overrides := v2AssignmentOverrideRequestBody{
Assignments: []v1Assignment{
v1Assignment{
{
SplitName: "test.test_experiment",
Variant: "control",
},
v1Assignment{
{
SplitName: "test.test2_experiment",
Variant: "treatment",
},
Expand Down
2 changes: 1 addition & 1 deletion featurecompletions/featurecompletions.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (f *FeatureCompletion) ApplyToSchema(schema *serializers.Schema, _ migratio
if idempotently {
return nil
}
return fmt.Errorf("Couldn't locate feature_completion of %s in schema", *f.featureGate)
return fmt.Errorf("couldn't locate feature_completion of %s in schema", *f.featureGate)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? Should we be using something other than an inline string if we want to return a capital "C" to the end user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sort of a go idiom, https://google.github.io/styleguide/go/decisions.html#error-strings

If we do want to return a capital C we can ignore the linting rule

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine -- generally happy to stick with community conventions in 99.9% of cases.

}
for i, candidate := range schema.FeatureCompletions { // Replace
if candidate.FeatureGate == *f.featureGate {
Expand Down
20 changes: 10 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
module github.com/Betterment/testtrack-cli

go 1.17
go 1.24

require (
github.com/gorilla/mux v1.7.1
github.com/joho/godotenv v1.3.0
github.com/pkg/errors v0.8.1
github.com/rs/cors v1.6.0
github.com/spf13/cobra v0.0.3
github.com/stretchr/testify v1.3.0
gopkg.in/yaml.v2 v2.2.4
github.com/gorilla/mux v1.8.1
github.com/joho/godotenv v1.5.1
github.com/rs/cors v1.11.1
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0
gopkg.in/yaml.v2 v2.4.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.3 // indirect
github.com/spf13/pflag v1.0.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading