name: Common Library Tests

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
on:
  workflow_call:
  push:
    branches:
      - master
    paths:
      - "charts/library/common/**"
      - "charts/library/common-test/**"
      - ".github/workflows/common-tests.yaml"
  #pull_request:
  #  branches:
  #    - main
  #  paths:
  #    - "charts/charts/library/common/**"
  #    - ".github/workflows/common-tests.yaml"
  workflow_dispatch:

jobs:
  check_changes:
    runs-on:
      group: default
    outputs:
      changes_detected: ${{ steps.filter.outputs.changed }}

    steps:
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Filter paths
        id: filter
        uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4
        with:
          list-files: json
          filters: |
            changed:
            - 'charts/library/common/**'

  lint:
    name: Lint Common
    runs-on: ubuntu-latest
    needs: check_changes
    if: needs.check_changes.outputs.changes_detected == 'true'
    strategy:
      fail-fast: false
      matrix:
        helm-version:
          - v3.14.0
          - v3.20.0
          - v4.1.0
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          fetch-depth: 1

      - name: Install Helm
        uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
        with:
          version: ${{ matrix.helm-version }}

      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
        with:
          python-version: "3.10"

      - name: Set up chart-testing
        uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0

      - name: Run chart-testing (lint)
        id: lint
        run: |
          ct lint --config .github/ct-lint.yaml \
                  --lint-conf .github/lint-conf.yaml \
                  --charts charts/library/common-test \
                  --debug

  unittest:
    needs:
      - lint
    name: Unit Tests
    runs-on: ubuntu-latest
    env:
      helmUnitVersion: 1.0.3
    strategy:
      fail-fast: false
      matrix:
        helm-version:
          - v3.14.0
          - v3.20.0
          - v4.1.0
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          fetch-depth: 1

      - name: Install Helm
        uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
        with:
          version: ${{ matrix.helm-version }}

      - name: Cache helm plugins
        uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
        with:
          path: |
            /home/runner/.local/share/helm/plugins/helm-unittest
            /tmp/_dist/
          key: helm-${{ matrix.helm-version }}-unittest-v${{ env.helmUnitVersion }}
          restore-keys: |
            helm-${{ matrix.helm-version }}-unittest-v${{ env.helmUnitVersion }}

      - name: Run Unittests
        shell: bash
        run: |
          set -x
          helm_ver=${{ matrix.helm-version}}
          helm_ver="${helm_ver#v}"

          VERIFY_FLAG=""
          if [ "$(printf '%s\n' "4.0.0" "$helm_ver" | sort -V | head -n1)" = "4.0.0" ]; then
            VERIFY_FLAG="--verify=false"
          fi

          (helm unittest -h > /dev/null) || \
            helm plugin install https://github.com/helm-unittest/helm-unittest --version=v${helmUnitVersion} $VERIFY_FLAG || \
            (sleep 10 && helm plugin install https://github.com/helm-unittest/helm-unittest --version=v${helmUnitVersion} $VERIFY_FLAG) || \
            echo "finished unittest reinstall tries"

          # Run tests
          cd charts/library/common-test/
          helm dependency update
          helm unittest -f "tests/**/*.yaml" . -v ./unit-values.yaml

  install:
    needs:
      - lint
    name: Install Charts
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        # We test the latest k3s version and the lowest supported
        k3s-version:
          - v1.28
          - v1.35
          - latest
        # We test the latest helm version and the lowest supported
        helm-version:
          - v3.14.0
          - v3.20.0
          - v4.1.0
        values:
          - basic-values.yaml
          - configmap-values.yaml
          - secrets-values.yaml
          - imagePullSecret-values.yaml
          - daemonset-values.yaml
          - job-values.yaml
          - cron-values.yaml
          - statefulset-values.yaml
          - persistence-values.yaml
          - extra-containers-values.yaml
          - rbac-values.yaml
          # Only run ingress tests without as no valid certissuer -> helm v4 waits for cert to be ready
          - ingress-wo-tls-values.yaml
          - networkPolicy-values.yaml
          # TODO: broken
          # - codeserver-values.yaml
          - netshoot-values.yaml
          - metrics-values.yaml
          - cnpg-values.yaml
          - cnpg-multi-values.yaml
          - register-operator-values.yaml
          ## TODO: reenable when we've some credentials ready to rock for testing
          # - volsync-dest-values.yaml
          # - volsync-src-values.yaml
          # - volsync-dest-direct-values.yaml
          # - volsync-src-direct-values.yaml

    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          fetch-depth: 1

      - name: Install Helm
        uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
        with:
          version: ${{ matrix.helm-version }}

      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
        with:
          python-version: "3.10"

      - name: Set up chart-testing
        uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0

      - name: Create k3d cluster - Attempt 1/3
        continue-on-error: true
        id: createc1
        uses: nolar/setup-k3d-k3s@8bf8d22160e8b1d184dcb780e390d6952a7eec65 # v1.0.10
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          version: ${{ matrix.k3s-version }}
          # Flags found here https://github.com/k3d-io/k3d
          k3d-args: --k3s-arg --disable=metrics-server@server:*

      - name: Wait 10 second to retry
        if: steps.createc1.outcome=='failure'
        run: |
          sleep 10
      - name: Create k3d cluster - Attempt 2/3
        continue-on-error: true
        if: steps.createc1.outcome=='failure'
        id: createc2
        uses: nolar/setup-k3d-k3s@8bf8d22160e8b1d184dcb780e390d6952a7eec65 # v1.0.10
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          version: ${{ matrix.k3s-version }}
          # Flags found here https://github.com/k3d-io/k3d
          k3d-args: --k3s-arg --disable=metrics-server@server:*

      - name: Wait 10 second to retry
        if: steps.createc2.outcome=='failure'
        run: |
          sleep 10
      - name: Create k3d cluster - Attempt 3/3
        id: createc3
        if: steps.createc2.outcome=='failure'
        uses: nolar/setup-k3d-k3s@8bf8d22160e8b1d184dcb780e390d6952a7eec65 # v1.0.10
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          version: ${{ matrix.k3s-version }}
          # Flags found here https://github.com/k3d-io/k3d
          k3d-args: --k3s-arg --disable=metrics-server@server:*

        # Install Kail to grab logs from tests, as there are cases ct-install fail to output logs
      - name: Install Kail
        run: |
          export KAIL_VERSION=v0.16.1
          wget https://github.com/boz/kail/releases/download/${KAIL_VERSION}/kail_${KAIL_VERSION}_linux_amd64.tar.gz
          tar -xvzf kail_${KAIL_VERSION}_linux_amd64.tar.gz
          chmod +x kail

      - name: Add Dependencies
        run: |
          if [[ "${{ matrix.values }}" =~ (ingress|metrics|cnpg|volsync).*-values.yaml ]]; then
            helm install kube-prometheus-stack oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack --namespace kube-prometheus-stack --create-namespace --set alertmanager.enabled=false --set grafana.enabled=false --set kubeProxy.enabled=false --wait
          fi
          if [[ "${{ matrix.values }}" =~ cnpg.*-values.yaml ]]; then
            helm install cloudnative-pg oci://ghcr.io/cloudnative-pg/charts/cloudnative-pg --namespace cloudnative-pg --create-namespace --wait
          fi
          if [[ "${{ matrix.values }}" =~ ingress.*-values.yaml ]]; then
            helm install cert-manager oci://quay.io/jetstack/charts/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true --wait
            helm install ingress-nginx oci://ghcr.io/home-operations/charts-mirror/ingress-nginx --namespace ingress-nginx --create-namespace \
            --set controller.ingressClassResource.default=true --set controller.publishService.enabled=false --set controller.service.type="ClusterIP" --set controller.config.allow-snippet-annotations=true --set controller.config.annotations-risk-level="Critical" --wait
          fi
          if [[ "${{ matrix.values }}" =~ volsync.*-values.yaml ]]; then
            helm install snapshot-controller oci://oci.trueforge.org/truecharts/snapshot-controller --namespace snapshot-controller --create-namespace --wait
            helm install volsync oci://oci.trueforge.org/truecharts/volsync --namespace volsync --create-namespace --wait
          fi

      - name: Run chart-testing (install)
        run: |
          # Move all ci values on a temp location (or skip if already moved from another matrix job)
          mv charts/library/common-test/ci charts/library/common-test/runtests || echo "Nothing to move"

          # Move one values.yaml to the correct location to run the test
          mv -f charts/library/common-test/runtests/${{ matrix.values }} charts/library/common-test/values.yaml

          # Stat kail on the background to grab logs from tests
          ./kail --ignore-ns kube-system --ignore-ns cert-manager --ignore-ns metallb-system --ignore-ns prometheus-operator >> /tmp/output.log &

          # Actually run the test
          ct install  --config .github/ct-install.yaml \
                      --charts charts/library/common-test \
                      --debug || (echo -e "\n\n--===PODLOGS===--\n\n" && \
                                  cat /tmp/output.log && \
                                  rm -f /tmp/output.log && exit 1)

          kill $!
          echo -e "\n\n--===PODLOGS===--\n\n"
          cat  /tmp/output.log
          rm -f /tmp/output.log

  # Summarize matrix https://github.community/t/status-check-for-a-matrix-jobs/127354/7
  common-tests-complete:
    needs: [lint, unittest, install]
    if: ${{ always() }}
    name: Common Tets Completed
    runs-on:
      group: default
    steps:
      - name: Check Results
        run: |
          if [[ "${{ needs.check_changes.outputs.changes_detected }}" == 'true' && ( "${{ needs.lint.result }}" != "success" || \
                "${{ needs.unittest.result }}" != "success" || \
                "${{ needs.install.result }}" != "success") ]]; then
            echo "One or more jobs failed!"
            exit 1
          else
            echo "Common Lint, Tests and unittests Completed Successfully"
          fi
