diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b568f7e75..e49867cee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ on: release: types: [ published ] -concurrency: +concurrency: group: ${{ github.ref }} cancel-in-progress: true @@ -56,25 +56,19 @@ jobs: run: | mkdir -p .go-cache docker run -d --name build --mount type=bind,source="$(pwd)",target=/stash,consistency=delegated --mount type=bind,source="$(pwd)/.go-cache",target=/root/.cache/go-build,consistency=delegated -w /stash $COMPILER_IMAGE tail -f /dev/null - + - name: Pre-install run: docker exec -t build /bin/bash -c "make pre-ui" - name: Generate run: docker exec -t build /bin/bash -c "make generate" - + - name: Validate UI # skip UI validation for pull requests if UI is unchanged if: ${{ github.event_name != 'pull_request' || steps.cache-ui.outputs.cache-hit != 'true' }} - run: docker exec -t build /bin/bash -c "make ui-validate" + run: docker exec -t build /bin/bash -c "make validate-frontend" - # TODO: Replace with `make validate` once `revive` is bundled in COMPILER_IMAGE - # create UI file so that the embed doesn't fail - - name: Validate - run: | - mkdir -p ui/v2.5/build - touch ui/v2.5/build/index.html - docker exec -t build /bin/bash -c "make fmt-check vet it" + # Backend validation happens in parallel to the build in the golangci-lint action - name: Build UI # skip UI build for pull requests if UI is unchanged (UI was cached) @@ -102,7 +96,7 @@ jobs: sha1sum dist/stash-* | sed 's/dist\///g' | tee -a CHECKSUMS_SHA1 echo "STASH_VERSION=$(git describe --tags --exclude latest_develop)" >> $GITHUB_ENV echo "RELEASE_DATE=$(date +'%Y-%m-%d %H:%M:%S %Z')" >> $GITHUB_ENV - + - name: Upload Windows binary # only upload binaries for pull requests if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}} @@ -126,13 +120,13 @@ jobs: with: name: stash-linux path: dist/stash-linux - + - name: Update latest_develop tag if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} run : git tag -f latest_develop; git push -f --tags - name: Development Release - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} uses: marvinpinto/action-automatic-releases@v1.1.2 with: repo_token: "${{ secrets.GITHUB_TOKEN }}" @@ -148,7 +142,7 @@ jobs: dist/stash-linux-arm32v7 dist/stash-pi CHECKSUMS_SHA1 - + - name: Master release if: ${{ github.event_name == 'release' && github.ref != 'refs/tags/latest_develop' }} uses: meeDamian/github-release@2.0 @@ -165,7 +159,7 @@ jobs: dist/stash-pi CHECKSUMS_SHA1 gzip: false - + - name: Development Docker if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} env: @@ -173,7 +167,7 @@ jobs: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} run: | - docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64 + docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64 docker info docker buildx create --name builder --use docker buildx inspect --bootstrap @@ -187,7 +181,7 @@ jobs: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} run: | - docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64 + docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64 docker info docker buildx create --name builder --use docker buildx inspect --bootstrap diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 000000000..ab5c50010 --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,60 @@ +name: Lint (golangci-lint) +on: + push: + tags: + - v* + branches: + - master + - develop + pull_request: + +env: + COMPILER_IMAGE: stashapp/compiler:5 + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Checkout + run: git fetch --prune --unshallow --tags + + - name: Pull compiler image + run: docker pull $COMPILER_IMAGE + + - name: Start build container + run: | + mkdir -p .go-cache + docker run -d --name build --mount type=bind,source="$(pwd)",target=/stash,consistency=delegated --mount type=bind,source="$(pwd)/.go-cache",target=/root/.cache/go-build,consistency=delegated -w /stash $COMPILER_IMAGE tail -f /dev/null + + - name: Generate Backend + run: docker exec -t build /bin/bash -c "make generate-backend" + + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version + version: v1.42.1 + + # Optional: working directory, useful for monorepos + # working-directory: somedir + + # Optional: golangci-lint command line arguments. + args: --modules-download-mode=vendor --timeout=3m + + # Optional: show only new issues if it's a pull request. The default value is `false`. + # only-new-issues: true + + # Optional: if set to true then the action will use pre-installed Go. + # skip-go-installation: true + + # Optional: if set to true then the action don't cache or restore ~/go/pkg. + # skip-pkg-cache: true + + # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. + # skip-build-cache: true + + - name: Cleanup build container + run: docker rm -f -v build diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 000000000..986396748 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,72 @@ +# options for analysis running +run: + timeout: 3m + modules-download-mode: vendor + +issues: + # Rev at which the linter was introduced. Older bugs are still + # present, but should not be considered validation errors for now + new-from-rev: b14d5c56504dfcea2f5a7b86706b0ecdafd0b68c + +linters-settings: + gofmt: + simplify: false + + revive: + ignore-generated-header: true + severity: error + confidence: 0.8 + error-code: 1 + warning-code: 1 + rules: + - name: blank-imports + disabled: true + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + - name: error-return + - name: error-strings + - name: error-naming + - name: exported + disabled: true + - name: if-return + disabled: true + - name: increment-decrement + - name: var-naming + disabled: true + - name: var-declaration + - name: package-comments + - name: range + - name: receiver-naming + - name: time-naming + - name: unexported-return + disabled: true + - name: indent-error-flow + disabled: true + - name: errorf + - name: empty-block + disabled: true + - name: superfluous-else + - name: unused-parameter + disabled: true + - name: unreachable-code + - name: redefines-builtin-id + +linters: + disable-all: true + enable: + # Default set of linters from golangci-lint + - deadcode + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - structcheck + - typecheck + - unused + - varcheck + # Linters added by the stash project + - gofmt + - revive + diff --git a/Makefile b/Makefile index ae1c652df..0fe2eedbc 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ endif ifdef IS_WIN SEPARATOR := && SET := set -else +else SEPARATOR := ; SET := export endif @@ -24,7 +24,7 @@ endif export CGO_ENABLED = 1 -.PHONY: release pre-build +.PHONY: release pre-build release: generate ui build-release @@ -103,13 +103,13 @@ cross-compile-pi: export CC := arm-linux-gnueabi-gcc cross-compile-pi: OUTPUT := -o dist/stash-pi cross-compile-pi: build-release-static -cross-compile-all: - make cross-compile-windows - make cross-compile-osx-intel - make cross-compile-osx-applesilicon - make cross-compile-linux - make cross-compile-linux-arm64v8 - make cross-compile-linux-arm32v7 +cross-compile-all: + make cross-compile-windows + make cross-compile-osx-intel + make cross-compile-osx-applesilicon + make cross-compile-linux + make cross-compile-linux-arm64v8 + make cross-compile-linux-arm32v7 make cross-compile-pi # Regenerates GraphQL files @@ -133,23 +133,13 @@ generate-stash-box-client: fmt: go fmt ./... -# Ensures that changed files have had gofmt run on them -.PHONY: fmt-check -fmt-check: - sh ./scripts/check-gofmt.sh - -# Runs go vet on the project's source code. -.PHONY: vet -vet: - go vet -mod=vendor ./... - .PHONY: lint lint: - revive -config revive.toml -exclude ./vendor/... ./... + golangci-lint run # runs unit tests - excluding integration tests .PHONY: test -test: +test: go test -mod=vendor ./... # runs all tests - including integration tests @@ -162,7 +152,7 @@ it: generate-test-mocks: go run -mod=vendor github.com/vektra/mockery/v2 --dir ./pkg/models --name '.*ReaderWriter' --outpkg mocks --output ./pkg/models/mocks -# installs UI dependencies. Run when first cloning repository, or if UI +# installs UI dependencies. Run when first cloning repository, or if UI # dependencies have changed .PHONY: pre-ui pre-ui: @@ -193,9 +183,17 @@ ui-validate: # runs all of the tests and checks required for a PR to be accepted .PHONY: validate -validate: ui-validate fmt-check vet lint it +validate: validate-frontend validate-backend + +# runs all of the frontend PR-acceptance steps +.PHONY: validate-frontend +validate-frontend: ui-validate + +# runs all of the backend PR-acceptance steps +.PHONY: validate-backend +validate-backend: lint it # locally builds and tags a 'stash/build' docker image .PHONY: docker-build -docker-build: +docker-build: docker build -t stash/build -f docker/build/x86_64/Dockerfile . diff --git a/README.md b/README.md index 42aff6c08..9b1b283d7 100644 --- a/README.md +++ b/README.md @@ -94,10 +94,10 @@ For issues not addressed there, there are a few options. ## Pre-requisites * [Go](https://golang.org/dl/) -* [Revive](https://github.com/mgechev/revive) - Configurable linter - * Go Install: `go get github.com/mgechev/revive` +* [GolangCI](https://golangci-lint.run/) - A meta-linter which runs several linters in parallel + * To install, follow the [local installation instructions](https://golangci-lint.run/usage/install/#local-installation) * [Yarn](https://yarnpkg.com/en/docs/install) - Yarn package manager - * Run `yarn install --frozen-lockfile` in the `stash/ui/v2.5` folder (before running make generate for first time). + * Run `yarn install --frozen-lockfile` in the `stash/ui/v2.5` folder (before running make generate for first time). NOTE: You may need to run the `go get` commands outside the project directory to avoid modifying the projects module file. @@ -125,17 +125,15 @@ NOTE: The `make` command in Windows will be `mingw32-make` with MingW. * `make pre-ui` - Installs the UI dependencies. Only needs to be run once before building the UI for the first time, or if the dependencies are updated * `make fmt-ui` - Formats the UI source code * `make ui` - Builds the frontend -* `make vet` - Run `go vet` -* `make lint` - Run the linter +* `make lint` - Run the linter on the backend * `make fmt` - Run `go fmt` -* `make fmt-check` - Ensure changed files are formatted correctly * `make it` - Run the unit and integration tests * `make validate` - Run all of the tests and checks required to submit a PR * `make ui-start` - Runs the UI in development mode. Requires a running stash server to connect to. Stash port can be changed from the default of `9999` with environment variable `REACT_APP_PLATFORM_PORT`. ## Building a release -1. Run `make generate` to create generated files +1. Run `make generate` to create generated files 2. Run `make ui` to compile the frontend 3. Run `make build` to build the executable for your current platform @@ -151,7 +149,7 @@ command to open a bash shell to the container to poke around: Stash can be profiled using the `--cpuprofile ` command line flag. -The resulting file can then be used with pprof as follows: +The resulting file can then be used with pprof as follows: `go tool pprof ` diff --git a/revive.toml b/revive.toml deleted file mode 100644 index c535a9a5c..000000000 --- a/revive.toml +++ /dev/null @@ -1,30 +0,0 @@ -ignoreGeneratedHeader = false -severity = "error" -confidence = 0.8 -errorCode = 1 -warningCode = 1 - -#[rule.blank-imports] -[rule.context-as-argument] -[rule.context-keys-type] -[rule.dot-imports] -[rule.error-return] -[rule.error-strings] -[rule.error-naming] -#[rule.exported] -#[rule.if-return] -[rule.increment-decrement] -#[rule.var-naming] -[rule.var-declaration] -[rule.package-comments] -[rule.range] -[rule.receiver-naming] -[rule.time-naming] -#[rule.unexported-return] -#[rule.indent-error-flow] -[rule.errorf] -#[rule.empty-block] -[rule.superfluous-else] -#[rule.unused-parameter] -[rule.unreachable-code] -[rule.redefines-builtin-id] \ No newline at end of file diff --git a/scripts/check-gofmt.sh b/scripts/check-gofmt.sh deleted file mode 100644 index 24fa914a5..000000000 --- a/scripts/check-gofmt.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2012 The Go Authors. All rights reserved. - -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: - -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. - -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -gofiles=./pkg/ -[ "$OS" = "Windows_NT" ] && gofiles=.\\pkg\\ - -unformatted=$(gofmt -l $gofiles) -[ -z "$unformatted" ] && exit 0 - -# Some files are not gofmt'd. Print message and fail. - -echo >&2 "Go files must be formatted with gofmt. Please run:" -for fn in $unformatted; do - echo >&2 " gofmt -w $PWD/$fn" -done - -exit 1