diff --git a/.github/actions/acc_test/README.md b/.github/actions/acc_test/README.md new file mode 100644 index 00000000..c3484cf2 --- /dev/null +++ b/.github/actions/acc_test/README.md @@ -0,0 +1 @@ +# acceptance test action diff --git a/.github/actions/acc_test/action.yaml b/.github/actions/acc_test/action.yaml new file mode 100644 index 00000000..828e1011 --- /dev/null +++ b/.github/actions/acc_test/action.yaml @@ -0,0 +1,114 @@ +name: Acceptance Testing +description: "Acceptance Testing pipeline" + +inputs: + go-version: + description: "go version to install" + default: '1.25' + required: true + + project_id: + description: "STACKIT project ID for tests" + required: true + + region: + description: "STACKIT region for tests" + default: 'eu01' + required: true + + service_account_json: + description: "STACKIT service account JSON file contents" + required: true + + test_file: + description: "testfile to run" + default: '' + +outputs: + random-number: + description: "Random number" + value: ${{ steps.random-number-generator.outputs.random-number }} + +runs: + using: "composite" + steps: + - name: Random Number Generator + id: random-number-generator + run: echo "random-number=$(echo $RANDOM)" >> $GITHUB_OUTPUT + shell: bash + + - name: Install needed tools + shell: bash + run: | + set -e + apt-get -y -qq update + apt-get -y -qq install jq python3 python3-pip python-is-python3 s3cmd git make wget + + - name: Setup JAVA + uses: actions/setup-java@v5 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '21' + + - name: Install Go ${{ inputs.go-version }} + uses: actions/setup-go@v6 + with: + go-version: ${{ inputs.go-version }} + check-latest: true + go-version-file: 'go.mod' + + - name: Install go tools + shell: bash + run: | + set -e + go mod download + go install golang.org/x/tools/cmd/goimports@latest + go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.7.2 + go install github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs@v0.24.0 + + - name: Prepare pkg_gen directory + shell: bash + run: | + go run cmd/main.go build -p + + - name: Run acceptance test file + if: ${{ inputs.test_file != '' }} + shell: bash + run: | + echo "Running acceptance tests for the terraform provider" + echo "${STACKIT_SERVICE_ACCOUNT_JSON}" > ~/.service_account.json + cd stackit + TF_ACC=1 \ + TF_ACC_PROJECT_ID=${TF_ACC_PROJECT_ID} \ + TF_ACC_REGION=${TF_ACC_REGION} \ + go test ${{ inputs.test_file }} -count=1 -timeout=30m + env: + STACKIT_SERVICE_ACCOUNT_JSON: ${{ inputs.service_account_json }} + TF_PROJECT_ID: ${{ inputs.project_id }} + TF_ACC_REGION: ${{ inputs.region }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN }} + # TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID }} + # TF_ACC_TEST_PROJECT_PARENT_UUID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_UUID }} + # TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_USER_EMAIL }} + + - name: Run acceptance tests + if: ${{ inputs.test_file == '' }} + shell: bash + run: | + echo "Running acceptance tests for the terraform provider" + echo "${STACKIT_SERVICE_ACCOUNT_JSON}" > ~/.service_account.json + cd stackit + TF_ACC=1 \ + TF_ACC_PROJECT_ID=${TF_ACC_PROJECT_ID} \ + TF_ACC_REGION=${TF_ACC_REGION} \ + go test ./... -count=1 -timeout=30m + env: + STACKIT_SERVICE_ACCOUNT_JSON: ${{ inputs.service_account_json }} + TF_PROJECT_ID: ${{ inputs.project_id }} + TF_ACC_REGION: ${{ inputs.region }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN }} + # TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID }} + # TF_ACC_TEST_PROJECT_PARENT_UUID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_UUID }} + # TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_USER_EMAIL }} diff --git a/.github/actions/build/action.yaml b/.github/actions/build/action.yaml index fe544618..1fa83ee1 100644 --- a/.github/actions/build/action.yaml +++ b/.github/actions/build/action.yaml @@ -1,4 +1,3 @@ - name: Build description: "Build pipeline" inputs: diff --git a/.github/actions/setup-cache-go/action.yaml b/.github/actions/setup-cache-go/action.yaml new file mode 100644 index 00000000..81f0d17d --- /dev/null +++ b/.github/actions/setup-cache-go/action.yaml @@ -0,0 +1,71 @@ +name: 'Setup Go and cache dependencies' +author: 'Forgejo authors, Marcel S. Henselin' +description: | + Wrap the setup-go with improved dependency caching. + +inputs: + username: + description: 'User for which to manage the dependency cache' + default: root + + go-version: + description: "go version to install" + default: '1.25' + required: true + +runs: + using: "composite" + steps: + - name: "Install zstd for faster caching" + shell: bash + run: | + apt-get update -qq + apt-get -q install -qq -y zstd + + - name: "Set up Go using setup-go" + uses: https://code.forgejo.org/actions/setup-go@v6 + id: go-version + with: + go-version: ${{ inputs.go-version }} + check-latest: true # Always check for the latest patch release + # go-version-file: "go.mod" + # do not cache dependencies, we do this manually + cache: false + + - name: "Get go environment information" + shell: bash + id: go-environment + run: | + chmod 755 $HOME # ensure ${RUN_AS_USER} has permission when go is located in $HOME + export GOROOT="$(go env GOROOT)" + echo "modcache=$(su ${RUN_AS_USER} -c '${GOROOT}/bin/go env GOMODCACHE')" >> "$GITHUB_OUTPUT" + echo "cache=$(su ${RUN_AS_USER} -c '${GOROOT}/bin/go env GOCACHE')" >> "$GITHUB_OUTPUT" + env: + RUN_AS_USER: ${{ inputs.username }} + GO_VERSION: ${{ steps.go-version.outputs.go-version }} + + - name: "Create cache folders with correct permissions (for non-root users)" + shell: bash + if: inputs.username != 'root' + # when the cache is restored, only the permissions of the last part are restored + # so assuming that /home/user exists and we are restoring /home/user/go/pkg/mod, + # both folders will have the correct permissions, but + # /home/user/go and /home/user/go/pkg might be owned by root + run: | + su ${RUN_AS_USER} -c 'mkdir -p "${MODCACHE_DIR}" "${CACHE_DIR}"' + env: + RUN_AS_USER: ${{ inputs.username }} + MODCACHE_DIR: ${{ steps.go-environment.outputs.modcache }} + CACHE_DIR: ${{ steps.go-environment.outputs.cache }} + + - name: "Restore Go dependencies from cache or mark for later caching" + id: cache-deps + uses: https://code.forgejo.org/actions/cache@v5 + with: + key: setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}-${{ hashFiles('go.sum', 'go.mod') }} + restore-keys: | + setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}- + setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}- + path: | + ${{ steps.go-environment.outputs.modcache }} + ${{ steps.go-environment.outputs.cache }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fbc3f339..e747e730 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -6,6 +6,11 @@ on: - alpha - main workflow_dispatch: + schedule: + # every sunday at 00:00 + # - cron: '0 0 * * 0' + # every day at 00:00 + - cron: '0 0 * * *' push: branches: - '!main' @@ -17,6 +22,39 @@ env: CODE_COVERAGE_ARTIFACT_NAME: "code-coverage" jobs: + runner_test: + name: "Test STACKIT runner" + runs-on: stackit-docker + steps: + - name: Install needed tools + run: | + apt-get -y -qq update + apt-get -y -qq install jq python3 python3-pip python-is-python3 s3cmd git make wget + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install go tools + run: | + go install golang.org/x/tools/cmd/goimports@latest + go install github.com/hashicorp/terraform-plugin-codegen-framework/cmd/tfplugingen-framework@latest + go install github.com/hashicorp/terraform-plugin-codegen-openapi/cmd/tfplugingen-openapi@latest + + - name: Setup JAVA + uses: actions/setup-java@v5 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '21' + + - name: Checkout + uses: actions/checkout@v6 + + - name: Run build pkg directory + run: | + go run cmd/main.go build + publish_test: name: "Test readiness for publishing provider" needs: config @@ -99,14 +137,72 @@ jobs: --gpgPubKeyFile=public_key.pem \ --version=${VERSION} + testing: + name: CI run tests + runs-on: ubuntu-latest + needs: config + env: + TF_ACC_PROJECT_ID: ${{ vars.TF_ACC_PROJECT_ID }} + TF_ACC_REGION: ${{ vars.TF_ACC_REGION }} + TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL: ${{ vars.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL }} + TF_ACC_SERVICE_ACCOUNT_FILE: "~/service_account.json" + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Build + uses: ./.github/actions/build + with: + go-version: ${{ env.GO_VERSION }} + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_wrapper: false + + - name: Create service account json file + if: ${{ github.event_name == 'pull_request' }} + run: | + echo "${{ secrets.TF_ACC_SERVICE_ACCOUNT_JSON }}" >~/service_account.json + + - name: Run go mod tidy + if: ${{ github.event_name == 'pull_request' }} + run: go mod tidy + + - name: Testing + run: make test + + - name: Acceptance Testing + env: + TF_ACC: "1" + if: ${{ github.event_name == 'pull_request' }} + run: make test-acceptance-tf + + - name: Check coverage threshold + shell: bash + run: | + make coverage + COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//') + echo "Coverage: $COVERAGE%" + if (( $(echo "$COVERAGE < 80" | bc -l) )); then + echo "Coverage is below 80%" + # exit 1 + fi + + - name: Archive code coverage results + uses: actions/upload-artifact@v4 + with: + name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} + path: "stackit/${{ env.CODE_COVERAGE_FILE_NAME }}" main: - name: CI + if: ${{ github.event_name != 'schedule' }} + name: CI run build and linting runs-on: ubuntu-latest needs: config steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Build uses: ./.github/actions/build @@ -130,27 +226,45 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v9 with: - version: v2.7 + version: v2.9 args: --config=golang-ci.yaml --allow-parallel-runners --timeout=5m + continue-on-error: true - - name: Lint + - name: Linting run: make lint + continue-on-error: true - - name: Test - run: make test +# - name: Testing +# run: make test +# +# - name: Acceptance Testing +# if: ${{ github.event_name == 'pull_request' }} +# run: make test-acceptance-tf +# +# - name: Check coverage threshold +# shell: bash +# run: | +# make coverage +# COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//') +# echo "Coverage: $COVERAGE%" +# if (( $(echo "$COVERAGE < 80" | bc -l) )); then +# echo "Coverage is below 80%" +# # exit 1 +# fi - - name: Archive code coverage results - uses: actions/upload-artifact@v4 - with: - name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} - path: "stackit/${{ env.CODE_COVERAGE_FILE_NAME }}" +# - name: Archive code coverage results +# uses: actions/upload-artifact@v4 +# with: +# name: ${{ env.CODE_COVERAGE_ARTIFACT_NAME }} +# path: "stackit/${{ env.CODE_COVERAGE_FILE_NAME }}" config: + if: ${{ github.event_name != 'schedule' }} name: Check GoReleaser config runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Check GoReleaser uses: goreleaser/goreleaser-action@v6 diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 2e01d519..b86dba35 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -130,3 +130,16 @@ jobs: cd release/ s3cmd put --recursive v1 s3://terraform-provider-privatepreview/ s3cmd put --recursive .well-known s3://terraform-provider-privatepreview/ + + - name: Import SSH key + run: | + mkdir -p ~/.ssh + echo "${{ secrets.DOCS_UPLOAD_SSH_KEY }}" > ~/.ssh/id_ed25519 + chmod 0600 ~/.ssh/id_ed25519 + + - name: Upload docs via scp + run: | + set -e + ssh -o StrictHostKeyChecking=no ubuntu@${{ vars.DOCS_SERVER_IP }} 'rm -rf /srv/www/docs' + echo "${{ github.ref_name }}" >docs/_version.txt + scp -o StrictHostKeyChecking=no -r docs ubuntu@${{ vars.DOCS_SERVER_IP }}:/srv/www/ diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 254c40f2..7d7106ed 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -18,7 +18,7 @@ jobs: goreleaser: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: # Allow goreleaser to access older tag information. fetch-depth: 0 diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 12454b9f..90adebe6 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Self-hosted Renovate uses: renovatebot/github-action@v41.0.0 with: diff --git a/.github/workflows/runnerstats.yaml b/.github/workflows/runnerstats.yaml new file mode 100644 index 00000000..08190d4c --- /dev/null +++ b/.github/workflows/runnerstats.yaml @@ -0,0 +1,29 @@ +name: Runner stats + +on: + workflow_dispatch: + +jobs: + stats-own: + name: "Get own runner stats" + runs-on: ubuntu-latest + steps: + - name: Install needed tools + run: | + apt-get -y -qq update + apt-get -y -qq install inxi + + - name: Show stats + run: inxi -c 0 + + stats-stackit: + name: "Get STACKIT runner stats" + runs-on: stackit-docker + steps: + - name: Install needed tools + run: | + apt-get -y -qq update + apt-get -y -qq install inxi + + - name: Show stats + run: inxi -c 0 diff --git a/.github/workflows/tf-acc-test.yaml b/.github/workflows/tf-acc-test.yaml index a8e6a53f..3b4fb061 100644 --- a/.github/workflows/tf-acc-test.yaml +++ b/.github/workflows/tf-acc-test.yaml @@ -7,21 +7,17 @@ on: workflow_dispatch: jobs: - main: + acc_test: name: Acceptance Tests runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 - - name: Install project tools and dependencies - run: make project-tools - - name: Run tests - run: | - make test-acceptance-tf TF_ACC_PROJECT_ID=$${{ secrets.TF_ACC_PROJECT_ID }} TF_ACC_ORGANIZATION_ID=$${{ secrets.TF_ACC_ORGANIZATION_ID }} TF_ACC_REGION="eu01" - env: - STACKIT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_SERVICE_ACCOUNT_TOKEN }} - TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL }} - TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN }} - TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID }} - TF_ACC_TEST_PROJECT_PARENT_UUID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_UUID }} - TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_USER_EMAIL }} + uses: actions/checkout@v6 + + - name: Run Test + uses: ./.github/actions/acc_test + with: + go-version: ${{ env.GO_VERSION }} + project_id: ${{ vars.TEST_PROJECT_ID }} + region: 'eu01' + service_account_json: ${{ secrets.TF_ACC_SERVICE_ACCOUNT_JSON }} diff --git a/.gitignore b/.gitignore index c588a0f1..1dac2ea3 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ dist pkg_gen /release/ +.env +**/.env diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 3e9105ca..e0aafe37 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -19,20 +19,20 @@ builds: ldflags: - '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}' goos: -# - freebsd -# - windows + - freebsd + - windows - linux - darwin goarch: - amd64 -# - '386' -# - arm + - '386' + - arm - arm64 -# ignore: -# - goos: darwin -# goarch: '386' -# - goos: windows -# goarch: arm + ignore: + - goos: darwin + goarch: '386' + - goos: windows + goarch: arm binary: '{{ .ProjectName }}_v{{ .Version }}' archives: - formats: [ 'zip' ] diff --git a/Makefile b/Makefile index c6b3f9ac..680cf020 100644 --- a/Makefile +++ b/Makefile @@ -12,9 +12,10 @@ project-tools: # LINT lint-golangci-lint: @echo "Linting with golangci-lint" - @$(SCRIPTS_BASE)/lint-golangci-lint.sh + @go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint run --fix --config golang-ci.yaml -lint-tf: + +lint-tf: @echo "Linting terraform files" @terraform fmt -check -diff -recursive @@ -23,6 +24,7 @@ lint: lint-golangci-lint lint-tf # DOCUMENTATION GENERATION generate-docs: @echo "Generating documentation with tfplugindocs" + @$(SCRIPTS_BASE)/tfplugindocs.sh build: @@ -34,15 +36,16 @@ fmt: @terraform fmt -diff -recursive # TEST +.PHONY: test coverage test: @echo "Running tests for the terraform provider" - @cd $(ROOT_DIR)/stackit && go test ./... -count=1 -coverprofile=coverage.out && cd $(ROOT_DIR) + @cd $(ROOT_DIR)/stackit && go test -timeout 0 ./... -count=1 -coverprofile=../coverage.out && cd $(ROOT_DIR) # Test coverage coverage: @echo ">> Creating test coverage report for the terraform provider" - @cd $(ROOT_DIR)/stackit && (go test ./... -count=1 -coverprofile=coverage.out || true) && cd $(ROOT_DIR) - @cd $(ROOT_DIR)/stackit && go tool cover -html=coverage.out -o coverage.html && cd $(ROOT_DIR) + @cd $(ROOT_DIR)/stackit && (go test -timeout 0 ./... -count=1 -coverprofile=../coverage.out || true) && cd $(ROOT_DIR) + @cd $(ROOT_DIR)/stackit && go tool cover -html=../coverage.out -o ../coverage.html && cd $(ROOT_DIR) test-acceptance-tf: @if [ -z $(TF_ACC_PROJECT_ID) ]; then echo "Input TF_ACC_PROJECT_ID missing"; exit 1; fi diff --git a/README.md b/README.md index 1da34359..ab79f28e 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,14 @@