name: "PR: Run all tests"
on:
  # git push origin main:tlim_testpr --force
  # will trigger a full PR test on the main branch:
  # https://github.com/StackExchange/dnscontrol/actions/workflows/pr_test.yml?query=branch%3Atlim_testpr
  push:
    branches:
      - 'tlim_testpr'
  pull_request:
  workflow_dispatch:

env:
  cache-key: 1639697695 #Change to force cache reset `pwsh > Get-Date -UFormat %s`
  go-mod-path: /go/pkg/mod
  BIND_DOMAIN: example.com

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      TEST_RESULTS: "/tmp/test-results"
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Set up Go
      uses: actions/setup-go@v5
      with:
        go-version: stable
    - name: restore_cache
      uses: actions/cache@v4.0.1
      with:
        key: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }}
        restore-keys: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }}
        path: ${{ env.go-mod-path }}
    - run: mkdir -p "$TEST_RESULTS"
    - name: Run unit tests
      run: |
        go install gotest.tools/gotestsum@latest
        gotestsum --junitfile ${TEST_RESULTS}/gotestsum-report.xml -- $PACKAGE_NAMES
    - name: Enforce Go Formatted Code
      run: "[ `go fmt ./... | wc -l` -eq 0 ]"
    - uses: actions/upload-artifact@v4.3.3
      with:
        name: unit-tests
        path: ${{ env.TEST_RESULTS }}

# Stringer is needed because .goreleaser includes "go generate ./..."
    - name: Install stringer
      run: |
        go install golang.org/x/tools/cmd/stringer@latest

    -
      id: build_binaries_tagged
      name: Build binaries (if tagged)
      if: github.ref_type == 'tag'
      uses: goreleaser/goreleaser-action@v6
      with:
        distribution: goreleaser
        version: latest
        args: build
    -
      id: build_binaries_not_tagged
      name: Build binaries (not tagged)
      if: github.ref_type != 'tag'
      uses: goreleaser/goreleaser-action@v6
      with:
        args: build --snapshot
  integration-test-providers:
    needs: build
    runs-on: ubuntu-latest
    outputs:
      integration_test_providers: ${{ steps.get_integration_test_providers.outputs.integration_test_providers }}
    steps:
    - name: Set Integration Test Providers
      id: get_integration_test_providers
      shell: pwsh
      run: |
        $Providers = @()
        $EnvContext = ConvertFrom-Json -InputObject $env:ENV_CONTEXT
        $VarsContext = ConvertFrom-Json -InputObject $env:VARS_CONTEXT
        $SecretsContext = ConvertFrom-Json -InputObject $env:SECRETS_CONTEXT
        ConvertFrom-Json -InputObject $env:PROVIDERS | ForEach-Object {
          if(($null -ne $EnvContext."$($_)_DOMAIN") -or ($null -ne $VarsContext."$($_)_DOMAIN") -or ($null -ne $SecretsContext."$($_)_DOMAIN")) {
            $Providers += $_
          }
        }
        Write-Host "Integration test providers: $Providers"
        echo "integration_test_providers=$(ConvertTo-Json -InputObject $Providers -Compress)" >> $env:GITHUB_OUTPUT
      env:
        PROVIDERS: "['AZURE_DNS','BIND','BUNNY_DNS','CLOUDFLAREAPI','CLOUDNS','DIGITALOCEAN','GANDI_V5','GCLOUD','HEDNS','HEXONET','HUAWEICLOUD','INWX','NAMEDOTCOM','NS1','POWERDNS','ROUTE53','TRANSIP']"
        ENV_CONTEXT: ${{ toJson(env) }}
        VARS_CONTEXT: ${{ toJson(vars) }}
        SECRETS_CONTEXT: ${{ toJson(secrets) }}
  integration-tests:
    if: github.ref != 'refs/heads/master' && github.ref != 'refs/heads/main'
    runs-on: ubuntu-latest
    container:
      image: golang:1.22
    needs:
    - integration-test-providers
    env:
      TEST_RESULTS: "/tmp/test-results"
      GOTESTSUM_FORMAT: testname

      # PROVIDER DOMAIN LIST
      # These providers will be tested if the env variable is set.
      # Set it to the domain name to use during the test.
      AZURE_DNS_DOMAIN: ${{ vars.AZURE_DNS_DOMAIN }}
      BIND_DOMAIN: ${{ vars.BIND_DOMAIN }}
      BUNNY_DNS_DOMAIN: ${{ vars.BUNNY_DNS_DOMAIN }}
      CLOUDFLAREAPI_DOMAIN: ${{ vars.CLOUDFLAREAPI_DOMAIN }}
      CLOUDNS_DOMAIN: ${{ vars.CLOUDNS_DOMAIN }}
      CSCGLOBAL_DOMAIN: ${{ vars.CSCGLOBAL_DOMAIN }}
      DIGITALOCEAN_DOMAIN: ${{ vars.DIGITALOCEAN_DOMAIN }}
      GANDI_V5_DOMAIN: ${{ vars.GANDI_V5_DOMAIN }}
      GCLOUD_DOMAIN: ${{ vars.GCLOUD_DOMAIN }}
      HEDNS_DOMAIN: ${{ vars.HEDNS_DOMAIN }}
      HEXONET_DOMAIN: ${{ vars.HEXONET_DOMAIN }}
      HUAWEICLOUD_DOMAIN: ${{ vars.HUAWEICLOUD_DOMAIN }}
      NAMEDOTCOM_DOMAIN: ${{ vars.NAMEDOTCOM_DOMAIN }}
      NS1_DOMAIN: ${{ vars.NS1_DOMAIN }}
      POWERDNS_DOMAIN: ${{ vars.POWERDNS_DOMAIN }}
      ROUTE53_DOMAIN: ${{ vars.ROUTE53_DOMAIN }}
      TRANSIP_DOMAIN: ${{ vars.TRANSIP_DOMAIN }}

      # PROVIDER SECRET LIST
      # The above providers have additional env variables they
      # need for credentials and such.

      AZURE_DNS_CLIENT_ID: ${{ secrets.AZURE_DNS_CLIENT_ID }}
      AZURE_DNS_CLIENT_SECRET: ${{ secrets.AZURE_DNS_CLIENT_SECRET }}
      AZURE_DNS_RESOURCE_GROUP: ${{ secrets.AZURE_DNS_RESOURCE_GROUP }}
      AZURE_DNS_SUBSCRIPTION_ID: ${{ secrets.AZURE_DNS_SUBSCRIPTION_ID }}
      AZURE_DNS_TENANT_ID: ${{ secrets.AZURE_DNS_TENANT_ID }}

      BUNNY_DNS_API_KEY: ${{ secrets.BUNNY_DNS_API_KEY }}

      CLOUDFLAREAPI_ACCOUNTID: ${{ secrets.CLOUDFLAREAPI_ACCOUNTID }}
      CLOUDFLAREAPI_TOKEN: ${{ secrets.CLOUDFLAREAPI_TOKEN }}

      CLOUDNS_AUTH_ID: ${{ secrets.CLOUDNS_AUTH_ID }}
      CLOUDNS_AUTH_PASSWORD: ${{ secrets.CLOUDNS_AUTH_PASSWORD }}

      CSCGLOBAL_APIKEY: ${{ secrets.CSCGLOBAL_APIKEY }}
      CSCGLOBAL_USERTOKEN: ${{ secrets.CSCGLOBAL_USERTOKEN }}

      DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }}

      GANDI_V5_APIKEY: ${{ secrets.GANDI_V5_APIKEY }}

      GCLOUD_EMAIL: ${{ secrets.GCLOUD_EMAIL }}
      GCLOUD_PRIVATEKEY: ${{ secrets.GCLOUD_PRIVATEKEY }}
      GCLOUD_PROJECT: ${{ secrets.GCLOUD_PROJECT }}
      GCLOUD_TYPE: ${{ secrets.GCLOUD_TYPE }}

      HEDNS_PASSWORD: ${{ secrets.HEDNS_PASSWORD }}
      HEDNS_TOTP_SECRET: ${{ secrets.HEDNS_TOTP_SECRET }}
      HEDNS_USERNAME: ${{ secrets.HEDNS_USERNAME }}

      HEXONET_ENTITY: ${{ secrets.HEXONET_ENTITY }}
      HEXONET_PW: ${{ secrets.HEXONET_PW }}
      HEXONET_UID: ${{ secrets.HEXONET_UID }}

      HUAWEICLOUD_REGION: ${{ secrets.HUAWEICLOUD_REGION }}
      HUAWEICLOUD_KEY_ID: ${{ secrets.HUAWEICLOUD_KEY_ID }}
      HUAWEICLOUD_KEY: ${{ secrets.HUAWEICLOUD_KEY }}

      NAMEDOTCOM_KEY: ${{ secrets.NAMEDOTCOM_KEY }}
      NAMEDOTCOM_URL: ${{ secrets.NAMEDOTCOM_URL }}
      NAMEDOTCOM_USER: ${{ secrets.NAMEDOTCOM_USER }}

      NS1_TOKEN: ${{ secrets.NS1_TOKEN }}

      POWERDNS_APIKEY: ${{ secrets.POWERDNS_APIKEY }}
      POWERDNS_APIURL: ${{ secrets.POWERDNS_APIURL }}
      POWERDNS_SERVERNAME: ${{ secrets.POWERDNS_SERVERNAME }}

      ROUTE53_KEY: ${{ secrets.ROUTE53_KEY }}
      ROUTE53_KEY_ID: ${{ secrets.ROUTE53_KEY_ID }}

      TRANSIP_ACCOUNT_NAME: ${{ secrets.TRANSIP_ACCOUNT_NAME }}
      TRANSIP_PRIVATE_KEY: ${{ secrets.TRANSIP_PRIVATE_KEY }}

    concurrency:
      group: ${{ github.workflow }}-${{ matrix.provider }}
    strategy:
      fail-fast: false
      matrix:
        provider: ${{ fromJson(needs.integration-test-providers.outputs.integration_test_providers )}}
    steps:
    - uses: actions/checkout@v4
    - run: mkdir -p "$TEST_RESULTS"
    - name: restore_cache
      uses: actions/cache@v4.0.1
      with:
        key: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }}
        restore-keys: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }}
        path: ${{ env.go-mod-path }}
    - name: Run integration tests for ${{ matrix.provider }} provider
      run: |-
        go install gotest.tools/gotestsum@latest
        if [ -n "$${{ matrix.provider }}_DOMAIN" ] ; then
          gotestsum --junitfile ${TEST_RESULTS}/gotestsum-report.xml -- -timeout 30m -v -verbose -provider ${{ matrix.provider }} -cfworkers=false
        else
          echo "Skip test for ${{ matrix.provider }} provider"
        fi
      working-directory: integrationTest
    - uses: actions/upload-artifact@v4.3.3
      with:
        name: integration-tests-${{ matrix.provider }}
        path: ${{ env.TEST_RESULTS }}
