diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..faff8b9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..6c5972d --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +# Description + +< Replace with adequate description for this PR as per [Pull Request document](https://www.notion.so/rudderstacks/Pull-Requests-40a4c6bd7a5e4387ba9029bab297c9e3) > + +## Linear Ticket + +< Replace with Linear Link > + +## Security + +- [ ] The code changed/added as part of this pull request won't create any security issues with how the software is being used. diff --git a/.github/workflows/pr-description-enforcer.yaml b/.github/workflows/pr-description-enforcer.yaml new file mode 100644 index 0000000..e2290f3 --- /dev/null +++ b/.github/workflows/pr-description-enforcer.yaml @@ -0,0 +1,17 @@ +name: 'Pull Request Description' +on: + pull_request: + types: + - opened + - edited + - reopened + +jobs: + enforce: + runs-on: ubuntu-latest + + steps: + - uses: rudderlabs/pr-description-enforcer@v1.0.0 + with: + repo-token: '${{ secrets.GITHUB_TOKEN }}' + placeholder-regex: '< Replace .* >' diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml new file mode 100644 index 0000000..a7004b3 --- /dev/null +++ b/.github/workflows/release-please.yaml @@ -0,0 +1,23 @@ +on: + push: + branches: + - "release/*" + - "main" +name: release-please +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - name: Extract branch name + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + id: extract_branch + - uses: google-github-actions/release-please-action@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + pull-request-title-pattern: "chore: release ${version}" + release-type: go + package-name: sql-tunnels + default-branch: ${{ steps.extract_branch.outputs.branch }} + changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false},{"type":"refactor","section":"Miscellaneous","hidden":false},{"type":"test","section":"Miscellaneous","hidden":false},{"type":"doc","section":"Documentation","hidden":false}]' + bump-minor-pre-major: true \ No newline at end of file diff --git a/.github/workflows/semantic-pr.yaml b/.github/workflows/semantic-pr.yaml new file mode 100644 index 0000000..f0c6546 --- /dev/null +++ b/.github/workflows/semantic-pr.yaml @@ -0,0 +1,73 @@ +name: "Semantic pull requests" + +on: + pull_request: + types: + - opened + - edited + - labeled + - unlabeled + - converted_to_draft + - ready_for_review + - synchronize + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - + uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + fix + feat + chore + refactor + exp + doc + test + scopes: | + core + multi-tenant + tooling + gateway + jobsdb + warehouse + processor + router + batchrouter + destination + startup + shutdown + ci + requireScope: false + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + doesn't start with an uppercase character. + # For work-in-progress PRs you can typically use draft pull requests + # from GitHub. However, private repositories on the free plan don't have + # this option and therefore this action allows you to opt-in to using the + # special "[WIP]" prefix to indicate this state. This will avoid the + # validation of the PR title and the pull request checks remain pending. + # Note that a second check will be reported if this is enabled. + wip: true + # When using "Squash and merge" on a PR with only one commit, GitHub + # will suggest using that commit message instead of the PR title for the + # merge commit, and it's easy to commit this by mistake. Enable this option + # to also validate the commit message for one commit PRs. + validateSingleCommit: false + # Related to `validateSingleCommit` you can opt-in to validate that the PR + # title matches a single commit to avoid confusion. + validateSingleCommitMatchesPrTitle: false + # If the PR contains one of these labels, the validation is skipped. + # Multiple labels can be separated by newlines. + # If you want to rerun the validation when labels change, you might want + # to use the `labeled` and `unlabeled` event triggers in your workflow. + ignoreLabels: | + bot + dependencies diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..0344f8c --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,23 @@ +name: Tests +on: + push: + branches: + - master + - main + - "release/*" + pull_request: +jobs: + test: + name: Unit + runs-on: 'ubuntu-20.04' + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version: '~1.21' + check-latest: true + - run: go version + - run: go mod download + - run: make test + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 \ No newline at end of file diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 0000000..b19fc9c --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,47 @@ +name: verify +on: + push: + tags: + - v* + branches: + - master + - main + pull_request: +jobs: + generate: + name: Correct generated files + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + check-latest: true + go-version: '~1.21' + - run: go version + + - run: go mod tidy + - run: git diff --exit-code go.mod + - name: Error message + if: ${{ failure() }} + run: echo '::error file=go.mod,line=1,col=1::Inconsistent go mod file. Ensure you have run `go mod tidy` and committed the files locally.'; echo '::error file=enterprise_mod.go,line=1,col=1::Possible missing enterprise exclusive dependencies.' + + - run: make fmt + - run: git diff --exit-code + - name: Error message + if: ${{ failure() }} + run: echo 'Not formatted files. Ensure you have run `make fmt` and committed the files locally.' + + linting: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version: '~1.21' + check-latest: true + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.55.0 + args: -v diff --git a/.gitignore b/.gitignore index f0a73e9..c43f331 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,10 @@ junit*.xml *.out.* *.out coverage.html +coverage.txt *.orig **/gomock_reflect_*/* ginkgo.report .env +profile.out +_testok \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..098929f --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,45 @@ +run: + timeout: 7m + go: '1.21' + +linters: + enable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - typecheck + - unused + - unparam + - unconvert + - bodyclose + - decorder + - makezero + - nilnil + - nilerr + - rowserrcheck + - tenv + - wastedassign + - unparam + - misspell + - unconvert + - depguard + - unused + +issues: + exclude-use-default: true + exclude-case-sensitive: false + max-issues-per-linter: 50 + max-same-issues: 10 + new: false + + +linters-settings: + depguard: + rules: + main: + files: + - .* + allow: + - .* \ No newline at end of file diff --git a/Makefile b/Makefile index dd9be6c..1e68195 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ GO=go LDFLAGS?=-s -w +TESTFILE=_testok .PHONY: default default: lint @@ -13,21 +14,33 @@ generate: install-tools $(GO) generate ./... .PHONY: test -test: install-tools test-run ## Run all tests +test: install-tools test-run test-teardown ## Run all tests + +test-teardown: + @if [ -f "$(TESTFILE)" ]; then \ + echo "Tests passed, tearing down..." ;\ + rm -f $(TESTFILE) ;\ + echo "mode: atomic" > coverage.txt ;\ + find . -name "profile.out" | while read file; do grep -v 'mode: atomic' $${file} >> coverage.txt; rm -f $${file}; done ;\ + else \ + rm -f coverage.txt coverage.html ; find . -name "profile.out" | xargs rm -f ;\ + echo "Tests failed :-(" ;\ + exit 1 ;\ + fi .PHONY: test-run test-run: $(eval TEST_CMD = go test) - $(eval TEST_OPTIONS = -v -count 1 -race -coverprofile cover.out --timeout=15m) + $(eval TEST_OPTIONS = -v -count 1 -race -failfast -shuffle=on -coverprofile=profile.out -covermode=atomic -coverpkg=./... -vet=all --timeout=15m) ifdef package - $(TEST_CMD) $(TEST_OPTIONS) $(package) + $(TEST_CMD) $(TEST_OPTIONS) ./$(package)/... && touch $(TESTFILE) || true else - $(TEST_CMD) $(TEST_OPTIONS) ./... + $(TEST_CMD) $(TEST_OPTIONS) ./... && touch $(TESTFILE) || true endif .PHONY: coverage coverage: test-run - go tool cover -html=cover.out -o coverage.html + go tool cover -html=coverage.txt -o coverage.html .PHONY: test-with-coverage test-with-coverage: test coverage @@ -36,11 +49,12 @@ test-with-coverage: test coverage install-tools: go install github.com/golang/mock/mockgen@v1.6.0 go install mvdan.cc/gofumpt@latest + go install golang.org/x/tools/cmd/goimports@latest + bash ./scripts/install-golangci-lint.sh v1.55.0 .PHONY: lint lint: fmt ## Run linters on all go files - docker run --rm -v $(shell pwd):/app:ro -w /app golangci/golangci-lint:v1.51.1 bash -e -c \ - 'golangci-lint run -v --timeout 5m' + golangci-lint run -v --timeout 5m .PHONY: fmt fmt: install-tools ## Formats all go files diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..522b708 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,10 @@ +coverage: + status: + project: + default: + informational: true + patch: + default: + informational: true +ignore: + - "mocks" diff --git a/internal/poller/poller_test.go b/internal/poller/poller_test.go index 1bf5464..84bf64b 100644 --- a/internal/poller/poller_test.go +++ b/internal/poller/poller_test.go @@ -42,7 +42,7 @@ func TestPoller(t *testing.T) { var wg sync.WaitGroup wg.Add(len(mockedResponses)) - var expectedResponseIndex = 0 + expectedResponseIndex := 0 startTestPoller(t, ctx, client, func(wcs *modelv2.WorkspaceConfigs) error { require.Equal(t, mockedResponses[expectedResponseIndex], wcs) @@ -70,7 +70,7 @@ func TestPoller(t *testing.T) { var wg sync.WaitGroup wg.Add(len(mockedResponses)) - var expectedResponseIndex = 0 + expectedResponseIndex := 0 startTestPoller(t, ctx, client, func(wcs *modelv2.WorkspaceConfigs) error { require.Equal(t, mockedResponses[expectedResponseIndex], wcs) @@ -98,7 +98,7 @@ func TestPoller(t *testing.T) { var wg sync.WaitGroup wg.Add(len(mockedResponses)) - var expectedResponseIndex = 0 + expectedResponseIndex := 0 var hasReturnedError bool // start a poller with handler that fails on first attempt and succeeds on second startTestPoller(t, ctx, client, func(wcs *modelv2.WorkspaceConfigs) error { diff --git a/modelv2/workspaceconfigs_test.go b/modelv2/workspaceconfigs_test.go index 9e3df3f..2db9411 100644 --- a/modelv2/workspaceconfigs_test.go +++ b/modelv2/workspaceconfigs_test.go @@ -9,7 +9,7 @@ import ( ) func TestWorkspaceConfigsUpdatedAt(t *testing.T) { - var wcs = &modelv2.WorkspaceConfigs{ + wcs := &modelv2.WorkspaceConfigs{ Workspaces: map[string]*modelv2.WorkspaceConfig{ "ws-1": { UpdatedAt: time.Date(2021, 1, 2, 0, 0, 0, 0, time.UTC), diff --git a/scripts/install-golangci-lint.sh b/scripts/install-golangci-lint.sh new file mode 100755 index 0000000..ce2b06d --- /dev/null +++ b/scripts/install-golangci-lint.sh @@ -0,0 +1,7 @@ +#!/bin/bash +VERSION=$1 +[ -z "${VERSION}" ] && VERSION="v1.55.0" +GOPATH=$(go env GOPATH) +[ -f "${GOPATH}/bin/golangci-lint-${VERSION}" ] && echo "golangci-lint ${VERSION} is already installed" || \ +curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/${VERSION}/install.sh | sh -s -- -b ${GOPATH}/bin ${VERSION} && \ +cp ${GOPATH}/bin/golangci-lint ${GOPATH}/bin/golangci-lint-${VERSION} diff --git a/sdk.go b/sdk.go index 56dd022..18311cd 100644 --- a/sdk.go +++ b/sdk.go @@ -115,7 +115,7 @@ func (cp *ControlPlane) setupPoller() error { return nil } - var handle = func(wc *modelv2.WorkspaceConfigs) error { + handle := func(wc *modelv2.WorkspaceConfigs) error { cp.configsCache.Set(wc) return nil }