diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..43b57a11 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,145 @@ +--- +name: ci +on: pull_request +jobs: + yamllint: + name: yamllint + runs-on: ubuntu-latest + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + - name: Setup Python + uses: actions/setup-python@v1 + - name: Install yamllint + run: pip install --user yamllint + - name: Run yamllint + run: ~/.local/bin/yamllint -c .yamllint.yml --strict . + shellcheck: + name: shellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: shellcheck + uses: fkautz/shell-linter@v1.0.1 + golangci-lint: + name: golangci-lint + runs-on: ubuntu-latest + env: + GOLANGCI_LINT_CONTAINER: golangci/golangci-lint:v1.23.2 + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v1 + - name: Pull golangci-lint docker container + run: docker pull ${GOLANGCI_LINT_CONTAINER} + - name: Run golangci-lint + run: docker run --rm -v $(pwd):/app -w /app ${GOLANGCI_LINT_CONTAINER} golangci-lint run + + excludeFmtErrorf: + name: exclude fmt.Errorf + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Exclude fmt.Errorf + run: | + if grep -r --include=*.go fmt.Errorf . ; then + echo "Please use errors.Errorf (or errors.New or errors.Wrap or errors.Wrapf) as appropriate rather than fmt.Errorf" + exit 1 + fi + + restrictNSMDeps: + name: Restrict dependencies on github.com/networkservicemesh/* + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Restrict dependencies on github.com/networkservicemesh/* + run: | + for i in $(grep github.com/networkservicemesh/ go.mod |grep -v '^module' | sed 's;.*\(github.com\/networkservicemesh\/[a-zA-z\/]*\).*;\1;g' | sort -u);do + if [ "${i}" != "github.com/networkservicemesh/sdk" ] && [ "${i}" != "github.com/networkservicemesh/api" ]; then + echo Dependency on "${i}" is forbidden + exit 1 + fi + done + + checkgomod: + name: check go.mod and go.sum + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-go@v1 + with: + go-version: 1.13.4 + - run: go mod tidy + - name: Check for changes in go.mod or go.sum + run: | + git diff --name-only --exit-code go.mod || ( echo "Run go tidy" && false ) + git diff --name-only --exit-code go.sum || ( echo "Run go tidy" && false ) + license: + name: license header check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-go@v1 + with: + go-version: 1.13.4 + - name: Install go-header + run: 'go get github.com/denis-tingajkin/go-header@v0.2.2' + - name: Run go-header + run: | + eval $(go env) + ${GOPATH}/bin/go-header + excludereplace: + name: Exclude replace in go.mod + runs-on: ubuntu-latest + steps: + - name: Check out the code + uses: actions/checkout@v1 + - name: Exclude replace in go.mod + run: | + grep -v 'replace github.com/satori/go.uuid' go.mod | grep ^replace || exit 0 + exit 1 + captureRunEnv: + name: Capture CI Run Env + runs-on: ubuntu-latest + steps: + - run: printenv + gogenerate: + name: gogenerate + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v1 + with: + go-version: 1.13.4 + - name: Generate files + run: go generate ./... + - name: Check for changes in generated code + run: | + git diff -- imports.go || ( echo "Rerun go generate ./... locally and resubmit" && false ) + docker: + name: Docker Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - run: docker build . + - run: docker run --rm $(docker build -q --target test .) + automerge: + name: automerge + runs-on: ubuntu-latest + needs: + - docker + if: github.actor == 'nsmbot' && github.base_ref == 'master' && github.event_name == 'pull_request' + steps: + - name: Check out the code + uses: actions/checkout@v2 + - name: Fetch master + run: | + git remote -v + git fetch --depth=1 origin master + - name: Only allow go.mod and go.sum changes + run: | + find . -type f ! -name 'go.mod' ! -name 'go.sum' -exec git diff --exit-code origin/master -- {} + + - name: Automerge nsmbot PR + uses: ridedott/merge-me-action@master + with: + GITHUB_LOGIN: nsmbot + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr-for-updates.yaml b/.github/workflows/pr-for-updates.yaml new file mode 100644 index 00000000..f7fddc30 --- /dev/null +++ b/.github/workflows/pr-for-updates.yaml @@ -0,0 +1,17 @@ +--- +name: Pull Request on update/* Branch Push +on: + push: + branches: + - update/* +jobs: + auto-pull-request: + name: Pull Request on update/* Branch Push + runs-on: ubuntu-latest + steps: + - name: pull-request-action + uses: vsoch/pull-request-action@master + env: + GITHUB_TOKEN: ${{ secrets.NSM_BOT_GITHUB_TOKEN }} + BRANCH_PREFIX: "update/" + PULL_REQUEST_BRANCH: "master" diff --git a/.go-header.yaml b/.go-header.yaml new file mode 100644 index 00000000..0a6d4b0d --- /dev/null +++ b/.go-header.yaml @@ -0,0 +1,17 @@ +--- +year: 2020 +goroutine-count: 6 +scope: + policy: "diff" + master-branch: "origin/master" +rules: + - template-path: ".license/template.txt" + paths: + - ".*[.]go$" + exclude-paths: + - ".*[.]pb" + - "./internal/imports/imports.go" +custom-patterns: + - name: NSM COPYRIGHT HOLDERS + pattern: "Copyright (c) {YEAR} {COPYRIGHT HOLDER}" + separator: "\n//\n// " diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..97fe49b9 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,163 @@ +--- +run: + # concurrency: 6 + timeout: 1m + issues-exit-code: 1 + tests: true +linters-settings: + errcheck: + check-type-assertions: false + check-blank: false + govet: + check-shadowing: true + settings: + printf: + funcs: + - (github.com/sirupsen/logrus.FieldLogger).Infof + - (github.com/sirupsen/logrus.FieldLogger).Warnf + - (github.com/sirupsen/logrus.FieldLogger).Errorf + - (github.com/sirupsen/logrus.FieldLogger).Fatalf + golint: + min-confidence: 0.8 + goimports: + local-prefixes: github.com/networkservicemesh/cmd-forwarder-sriov + gocyclo: + min-complexity: 15 + maligned: + suggest-new: true + dupl: + threshold: 150 + goconst: + min-len: 2 + min-occurrences: 2 + depguard: + list-type: blacklist + include-go-root: false + packages: + - errors + packages-with-error-message: + # specify an error message to output when a blacklisted package is used + - errors: "Please use \"github.com/pkg/errors\" instead of \"errors\" in go imports" + misspell: + locale: US + unparam: + check-exported: false + nakedret: + max-func-lines: 30 + prealloc: + simple: true + range-loops: true + for-loops: false + gocritic: + enabled-checks: + - appendAssign + - assignOp + - appendCombine + - argOrder + - badCall + - badCond + - boolExprSimplify + - builtinShadow + - captLocal + - caseOrder + - codegenComment + - commentFormatting + - commentedOutCode + - commentedOutImport + - defaultCaseOrder + - deprecatedComment + - docStub + - dupArg + - dupBranchBody + - dupCase + - dupImport + - dupSubExpr + - elseif + - emptyFallthrough + - emptyStringTest + - equalFold + - evalOrder + - exitAfterDefer + - flagDeref + - flagName + - hexLiteral + - hugeParam + - ifElseChain + - importShadow + - indexAlloc + - initClause + - methodExprCall + - nestingReduce + - newDeref + - nilValReturn + - octalLiteral + - offBy1 + - paramTypeCombine + - ptrToRefParam + - rangeExprCopy + - rangeValCopy + - regexpMust + - regexpPattern + - singleCaseSwitch + - sloppyLen + - sloppyReassign + - stringXbytes + - switchTrue + - typeAssertChain + - typeSwitchVar + - typeUnparen + - unlabelStmt + - unnamedResult + - unnecessaryBlock + - underef + - unlambda + - unslice + - valSwap + - weakCond + - wrapperFunc + - yodaStyleExpr +linters: + disable-all: true + enable: + # - rowserrcheck + - bodyclose + - deadcode + - depguard + - dogsled + - dupl + - errcheck + - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + - golint + - gosec + - gosimple + - govet + - ineffassign + - interfacer + # - lll + - misspell + - nakedret + - scopelint + - staticcheck + - structcheck + - stylecheck + - typecheck + - unconvert + - unparam + # - unused + - varcheck + - whitespace +issues: + exclude-use-default: false + max-issues-per-linter: 0 + max-same-issues: 0 + exclude-rules: + - path: main.go + linters: + - funlen + text: "Function 'main' is too long" diff --git a/.license/README.md b/.license/README.md new file mode 100644 index 00000000..de881eaa --- /dev/null +++ b/.license/README.md @@ -0,0 +1,48 @@ +## Copyright headers for source code +This folder contains the copyright templates for source files of NSM project. + +Below is an example of valid copyright header for `.go` files: +``` +// Copyright (c) 2020 Doc.ai and/or its affiliates. +// +// Copyright (c) 2020 Cisco and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +``` +Note you can use your company name instead of `Cisco and/or its affiliates`. +Also, source code files can have multi copyright holders, for example: +``` +// Copyright (c) 2020 Doc.ai and/or its affiliates. +// +// Copyright (c) 2020 Cisco and/or its affiliates. +// +// Copyright (c) 2020 Red Hat Inc. and/or its affiliates. +// +// Copyright (c) 2020 VMware, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +``` \ No newline at end of file diff --git a/.license/template.txt b/.license/template.txt new file mode 100644 index 00000000..7cbffa8a --- /dev/null +++ b/.license/template.txt @@ -0,0 +1,15 @@ +// {NSM COPYRIGHT HOLDERS} +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. \ No newline at end of file diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 00000000..d4a3b49d --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,15 @@ +--- +extends: default + +yaml-files: + - '*.yaml' + - '*.yml' + +rules: + truthy: disable + # 80 chars should be enough, but don't fail if a line is longer + line-length: disable + comments-indentation: + ignore: .circleci/config.yml + +ignore: scripts/aws/aws-k8s-cni.yaml diff --git a/staticcheck.conf b/staticcheck.conf new file mode 100644 index 00000000..6b78d471 --- /dev/null +++ b/staticcheck.conf @@ -0,0 +1,10 @@ +checks = ["all", "-ST1000", "-ST1016"] +initialisms = ["ACL", "API", "ASCII", "CPU", "CSS", "DNS", + "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", + "IP", "JSON", "NS", "NSM", "QPS", "RAM", "RPC", "SLA", + "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", + "UDP", "UI", "GID", "UID", "UUID", "URI", + "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", + "XSS"] +dot_import_whitelist = [] +http_status_code_whitelist = ["200", "400", "404", "500"]