diff --git a/README.md b/README.md index 3765391..9ecacb9 100644 --- a/README.md +++ b/README.md @@ -62,11 +62,12 @@ and a [.golangci.yml](https://golangci-lint.run/usage/configuration/). | Option | Default | Required | Description | | :--------------------------------- | :----------------------------------- | -------- | :--------------------------------------------------------------------------------------------------------------- | -| code_coverage_expected | 80 | | | +| code-coverage-expected | 80 | | | | gci | true | | Check for 'incorrect import order'. If failed then instructions are shown to resolve the issue | | golang-unit-tests-exclusions | ' ' | | | | golangci-lint-version | v1.55.2 | | | | golang-number-of-tests-in-parallel | 4 | | | +| task-version | | | | | token | ' ' | x | GitHub token that is required to push an image to the registry of the project and to pull cached Trivy DB images | | trivy-action-db | ghcr.io/aquasecurity/trivy-db:2 | | Replace this with a cached image to prevent bump into pull rate limiting issues | | trivy-action-java-db | ghcr.io/aquasecurity/trivy-java-db:1 | | Replace this with a cached image to prevent bump into pull rate limiting issues | @@ -91,3 +92,5 @@ tests. If the `--tags` step is omitted, only unit tests will be executed. See the integration paragraph for the steps and replace `integration` with `component` to run them. + +TASK_X_REMOTE_TASKFILES=1 WATWATWAT=integration WAT123="\(cmd\/mcvs-scanner\|cmd\/mcvs-scanner-cli\|deprecated\|docs\/swagger\|mocks\)" CODE_COVERAGE_OUTPUT=18 task remote:coverage --offline diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..971faa8 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,163 @@ +# TASK_X_REMOTE_TASKFILES=1 task remote:lint +# cmd: steps that will be run sequentially +# deps: tasks that will be run in parallel +--- +version: "3" + +vars: + COVERPROFILE: profile.cov + GCI_VERSION: 0.13.5 + GOLANGCI_LINT_VERSION: 1.61.0 + MOCKERY_BIN: "{{.TASK_GO_PATH}}/bin/mockery" + MOCKERY_MAJOR_VERSION: v2 + MOCKERY_VERSION: "{{.MOCKERY_MAJOR_VERSION}}.46.0" + YQ_MAJOR_VERSION: v4 + YQ_VERSION: "{{.YQ_MAJOR_VERSION}}.44.3" + +tasks: + coverage: + silent: true + cmds: + - task: test + vars: + TEST_EXTRA_ARGS: >- + -coverpkg=$(go list --tags={{.TEST_TAGS}} ./... | grep -v '{{.CODE_COVERAGE_FILE_EXCLUSIONS}}' | tr '\n' ',') + -coverprofile={{.COVERPROFILE}} + TEST_TAGS: integration + - | + code_coverage_output=$(go tool cover -func {{.COVERPROFILE}}) + code_coverage_actual=$(echo "${code_coverage_output}" |\ + grep total: |\ + awk '{print $3}' |\ + sed 's/%//') + + echo "Code coverage overview:" + echo "{{.CODE_COVERAGE_EXPECTED}}" + if (( $(echo "{{.CODE_COVERAGE_EXPECTED}} > ${code_coverage_actual}" | bc -l) )); then + echo "The actual code coverage: '${code_coverage_actual}' is too low. Expected: '{{.CODE_COVERAGE_EXPECTED}}'." + exit 1 + elif (( $(echo "${code_coverage_actual} > {{.CODE_COVERAGE_EXPECTED}}" | bc -l) )); then + echo "The actual code coverage: '${code_coverage_actual}' exceeds the expected coverage. Please adjust the threshold to align with the expected: '{{.CODE_COVERAGE_OUTPUT}}'." + exit 1 + fi + gci-install: + silent: true + cmds: + - | + if ! ~/go/bin/gci --version | grep -q "gci version {{.GCI_VERSION}}"; then + go install github.com/daixiang0/gci@v{{.GCI_VERSION}} + fi + gci: + silent: true + cmds: + - task: gci-install + - | + if ~/go/bin/gci list --skip-generated . | grep "\.go$"; then + echo "One or more golang files detected with: 'incorrect import order':" + echo " * Observe: '~/go/bin/gci diff --skip-generated .'" + echo " * Resolve: '~/go/bin/gci write --skip-generated .'" + exit 1 + fi + gci-write: + silent: true + cmds: + - task: gci-install + - ~/go/bin/gci write --skip-generated -s standard -s default . + golangci-lint-install: + silent: true + cmds: + - | + if ! golangci-lint --version | grep -q "has version {{.GOLANGCI_LINT_VERSION}}"; then + curl \ + -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh |\ + sh -s -- -b $(go env GOPATH)/bin v{{.GOLANGCI_LINT_VERSION}} + fi + golangci-lint-run: + silent: true + cmds: + - | + golangci-lint run \ + # --build-tags component,e2e,integration \ + --timeout 2m30s \ + --verbose + golangci-lint: + silent: true + cmds: + - task: golangci-lint-install + - task: golangci-lint-run + golangci-lint-run-without-cache: + silent: true + cmds: + - task: golangci-lint-install + - golangci-lint cache clean + - task: golangci-lint-run + lint: + silent: true + deps: + - task: gci + - task: golangci-lint + mock-generate: + silent: true + cmds: + - | + if ! {{.MOCKERY_BIN}} --version | grep "{{.MOCKERY_VERSION}}"; then + go install github.com/vektra/mockery/{{.MOCKERY_MAJOR_VERSION}}@{{.MOCKERY_VERSION}} + fi + echo "{{.MOCK_GENERATE_DIR}} {{.MOCK_GENERATE_INTERFACE_NAME}}" + {{.MOCKERY_BIN}} \ + --dir {{.MOCK_GENERATE_DIR}} \ + --name {{.MOCK_GENERATE_INTERFACE_NAME}} \ + --output {{.MOCK_GENERATE_DIR}}/mocks + test: + silent: true + cmds: + - | + if [ "$(uname -s)" = "Darwin" ]; then + GOLANG_PARALLEL_TESTS=$(sysctl -n hw.ncpu) + else + GOLANG_PARALLEL_TESTS=$(nproc) + fi + echo "GOLANG_PARALLEL_TESTS: ${GOLANG_PARALLEL_TESTS}" + + if [ -z "{{.TEST_FILES}}" ]; then + TEST_FILES=./... + fi + echo "TEST_FILES: ${TEST_FILES}" + + TEST_TAGS="--tags={{.TEST_TAGS}}" + echo "TEST_TAGS: ${TEST_TAGS}" + + go test \ + -p "${GOLANG_PARALLEL_TESTS}" \ + -race \ + -short \ + "${TEST_TAGS}" \ + -v \ + ${TEST_FILES} \ + {{.TEST_EXTRA_ARGS}} + test-component: + silent: true + cmds: + - task: test + vars: + TEST_TAGS: component + test-e2e: + silent: true + cmds: + - task: test + vars: + TEST_TAGS: e2e + test-integration: + silent: true + cmds: + - task: test + vars: + TEST_TAGS: integration + yq: + silent: true + cmds: + - | + if ! yq --version | grep -q "version {{.YQ_VERSION}}"; then + go install \ + github.com/mikefarah/yq/{{.YQ_MAJOR_VERSION}}@{{.YQ_VERSION}} + fi diff --git a/action.yml b/action.yml index e4a6226..a8daf49 100644 --- a/action.yml +++ b/action.yml @@ -3,7 +3,7 @@ name: mcvs-golang-action description: | The Mission Critical Vulnerability Scanner (MCVS) Golang action. inputs: - code_coverage_expected: + code-coverage-expected: default: "80" description: | The minimum code coverage. @@ -22,6 +22,10 @@ inputs: golang-number-of-tests-in-parallel: description: | Number of test in parallel. + task-version: + default: v3.39.2 + description: | + The Task version that has to be installed and used. testing-type: description: | The testing type, e.g. integration, unit or some other. @@ -42,22 +46,23 @@ runs: using: "composite" steps: # - # YAML linting. - # - - run: | - pip install --user yamllint==1.35.1 - yamllint -d '{extends: default, rules: {comments: {min-spaces-from-content: 1}}}' . - if: inputs.testing-type == 'lint' - shell: bash - # - # Install the golang version that has been defined in the go.mod file. + # Install task and the golang version that has been defined in the go.mod + # file. # # yamllint disable rule:line-length - uses: actions/setup-go@v5.1.0 - if: inputs.testing-type == 'component' || inputs.testing-type == 'coverage' || inputs.testing-type == 'integration' || inputs.testing-type == 'unit' + if: inputs.testing-type == 'component' || inputs.testing-type == 'coverage' || inputs.testing-type == 'integration' || inputs.testing-type == 'lint' || inputs.testing-type == 'unit' with: go-version-file: "go.mod" cache: false + - name: install task + if: inputs.testing-type == 'component' || inputs.testing-type == 'coverage' || inputs.testing-type == 'integration' || inputs.testing-type == 'lint' || inputs.testing-type == 'unit' + shell: bash + run: | + if ! ~/go/bin/task --version | grep "Task version: ${{ inputs.task-version }}"; then + major_version=$(echo "${{ inputs.task-version }}" | sed -E 's/^v([0-9]+).*/\1/') + go install github.com/go-task/task/v${major_version}/cmd/task@${{ inputs.task-version }} + fi # yamllint enable rule:line-length # # Verify downloaded dependencies. @@ -80,14 +85,10 @@ runs: - name: gci if: inputs.gci == 'true' && inputs.testing-type == 'lint' shell: bash + env: + TASK_X_REMOTE_TASKFILES: 1 run: | - go install github.com/daixiang0/gci@v0.13.4 - if ~/go/bin/gci list --skip-generated . | grep "\.go$"; then - echo "One or more golang files detected with: 'incorrect import order':" - echo " * Observe: '~/go/bin/gci diff --skip-generated .'" - echo " * Resolve: '~/go/bin/gci write --skip-generated .'" - exit 1 - fi + task remote:golangci-lint --yes # # Code security scanning. # @@ -145,28 +146,22 @@ runs: # Run golangci-lint. # - name: golangci-lint - uses: golangci/golangci-lint-action@v6.1.1 if: inputs.testing-type == 'lint' - with: - args: |- - --enable-all \ - --out-format=colored-line-number \ - --timeout 2m30s \ - -v - version: ${{ inputs.golangci-lint-version }} + shell: bash + env: + TASK_X_REMOTE_TASKFILES: 1 + run: | + task remote:golangci-lint --yes # # Unit tests. # - name: unit tests if: inputs.testing-type == 'unit' shell: bash + env: + TASK_X_REMOTE_TASKFILES: 1 run: | - ${GITHUB_ACTION_PATH}/src/go-test.sh \ - "" \ - "" \ - "${{ inputs.golang-number-of-tests-in-parallel }}" \ - "${{ inputs.golang-unit-tests-exclusions }}" \ - "" + task remote:test --yes # # Integration tests. # @@ -176,12 +171,7 @@ runs: env: GITHUB_TOKEN: ${{ inputs.token }} run: | - ${GITHUB_ACTION_PATH}/src/go-test.sh \ - "" \ - "" \ - "${{ inputs.golang-number-of-tests-in-parallel }}" \ - "${{ inputs.golang-unit-tests-exclusions }}" \ - "integration" + task remote:test-integration --yes # # Coverage. # @@ -189,31 +179,11 @@ runs: if: inputs.testing-type == 'coverage' shell: bash env: + CODE_COVERAGE_EXPECTED: ${{ inputs.code-coverage-expected }} + CODE_COVERAGE_FILE_EXCLUSIONS: ${{ inputs.golang-unit-tests-exclusions }} GITHUB_TOKEN: ${{ inputs.token }} run: | - ${GITHUB_ACTION_PATH}/src/go-test.sh \ - "./..." \ - "profile.cov" \ - "${{ inputs.golang-number-of-tests-in-parallel }}" \ - "${{ inputs.golang-unit-tests-exclusions }}" \ - "integration" - - code_coverage_output=$(go tool cover -func profile.cov) - code_coverage_actual=$(echo "${code_coverage_output}" |\ - grep total: |\ - awk '{print $3}' |\ - sed 's/%//') - - echo "Code coverage overview:" - echo "${code_coverage_output}" - - if (( $(echo "${{ inputs.code_coverage_expected }} > ${code_coverage_actual}" | bc -l) )); then - echo "The actual code coverage: '${code_coverage_actual}' is too low. Expected: '${{ inputs.code_coverage_expected }}'." - exit 1 - elif (( $(echo "${code_coverage_actual} > ${{ inputs.code_coverage_expected }}" | bc -l) )); then - echo "The actual code coverage: '${code_coverage_actual}' exceeds the expected coverage. Please adjust the threshold to align with the expected: '${{ inputs.code_coverage_expected }}'." - exit 1 - fi + task remote:coverage --yes # # Component tests. # @@ -223,9 +193,4 @@ runs: env: GITHUB_TOKEN: ${{ inputs.token }} run: | - ${GITHUB_ACTION_PATH}/src/go-test.sh \ - "" \ - "" \ - "${{ inputs.golang-number-of-tests-in-parallel }}" \ - "${{ inputs.golang-unit-tests-exclusions }}" \ - "component" + task remote:test-component --yes