name: CI

on:
  push:
    branches:
      - "main"
jobs:
  check:
    runs-on: "ubuntu-latest"
    steps:
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      - name: Lint
        run: make check && make check-templates
      - name: Check that 'func.yaml schema' is up-to-date
        run: make schema-check
      - name: Check embedded templates content
        run: go test -run "^\QTestFileSystems\E$/^\Qembedded\E$" ./pkg/filesystem

  test-unit:
    strategy:
      matrix:
        java: [ 21 ]
        os: [ "ubuntu-latest", "windows-latest", "macos-latest" ]
    runs-on: ${{ matrix.os }}
    steps:
      - run: git config --global core.autocrlf false
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      - uses: actions/setup-java@v4
        with:
          java-version: ${{ matrix.java }}
          distribution: 'temurin'
      - uses: actions/setup-python@v5
        with:
          python-version: '3.10'
      - name: Unit Test
        run:  make test
      - name: Template Unit Tests
        run:  make test-templates
      - uses: codecov/codecov-action@v5
        with:
          files: ./coverage.txt
          flags: unit-tests-${{ matrix.os }}
          fail_ci_if_error: true
          verbose: true
          token: ${{ secrets.CODECOV_TOKEN }}

  test-integration:
    runs-on: "ubuntu-latest"
    steps:
      - name: Set Environment Variables
        run: |
          echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
          echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      - name: Install Binaries
        run: ./hack/install-binaries.sh
      - name: Allocate Cluster
        run: |
          attempt=0
          max_attempts=5
          until [ $attempt -ge $max_attempts ]
          do
            attempt=$((attempt+1))
            echo "------------------ Attempt $attempt ------------------"
            ./hack/allocate.sh && break
            echo "------------------ failed, retrying... ------------------"
            if [ $attempt -ge $max_attempts ]; then
              echo "------------------ max # of retries reached, exiting ------------------"
              exit 1
            fi
            ./hack/delete.sh
            echo "------------------ sleep for 5 minutes ------------------"
            sleep 300
          done
          echo "------------------ finished! attempt $attempt ------------------"
      - name: Local Registry
        run: ./hack/registry.sh
      - name: Setup testing images
        run: ./hack/setup-testing-images.sh
      - name: Integration Tests
        run: make test-integration
      - uses: codecov/codecov-action@v5
        with:
          files: ./coverage.txt
          flags: integration-tests
          fail_ci_if_error: true
          verbose: true
          token: ${{ secrets.CODECOV_TOKEN }}

  e2e-test:
    strategy:
      matrix:
        os: ["ubuntu-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Set Environment Variables
        run: |
          echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
          echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      - name: Install Binaries
        run: ./hack/install-binaries.sh
      - name: Allocate Cluster
        run: |
          attempt=0
          max_attempts=5
          until [ $attempt -ge $max_attempts ]
          do
            attempt=$((attempt+1))
            echo "------------------ Attempt $attempt ------------------"
            ./hack/allocate.sh && break
            echo "------------------ failed, retrying... ------------------"
            if [ $attempt -ge $max_attempts ]; then
              echo "------------------ max # of retries reached, exiting ------------------"
              exit 1
            fi
            ./hack/delete.sh
            echo "------------------ sleep for 5 minutes ------------------"
            sleep 300
          done
          echo "------------------ finished! attempt $attempt ------------------"
      - name: Local Registry
        run: ./hack/registry.sh
      - name: E2E Test
        run: make test-e2e
      - uses: codecov/codecov-action@v5
        with:
          files: ./coverage.txt
          flags: e2e-test
          fail_ci_if_error: true
          verbose: true
          token: ${{ secrets.CODECOV_TOKEN }}

  e2e-on-cluster-test:
    strategy:
      matrix:
        os: ["ubuntu-latest"]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Set Environment Variables
        run: |
          echo "KUBECONFIG=${{ github.workspace }}/hack/bin/kubeconfig.yaml" >> "$GITHUB_ENV"
          echo "PATH=${{ github.workspace }}/hack/bin:$PATH" >> "$GITHUB_ENV"
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      - uses: imjasonh/setup-ko@v0.6
      - name: Install Binaries
        run: ./hack/install-binaries.sh
      - name: Allocate Cluster
        run: |
          attempt=0
          max_attempts=5
          until [ $attempt -ge $max_attempts ]
          do
            attempt=$((attempt+1))
            echo "------------------ Attempt $attempt ------------------"
            ./hack/allocate.sh && break
            echo "------------------ failed, retrying... ------------------"
            if [ $attempt -ge $max_attempts ]; then
              echo "------------------ max # of retries reached, exiting ------------------"
              exit 1
            fi
            ./hack/delete.sh
            echo "------------------ sleep for 5 minutes ------------------"
            sleep 300
          done
          echo "------------------ finished! attempt $attempt ------------------"
      - name: Setup testing images
        run: ./hack/setup-testing-images.sh
      - name: Deploy Tekton
        run: ./hack/install-tekton.sh
      - name: Deploy Test Git Server
        run: ./hack/install-git-server.sh
      - name: E2E On Cluster Test
        env:
          E2E_RUNTIMES: ""
        run: make test-e2e-on-cluster
      - uses: codecov/codecov-action@v5
        with:
          files: ./coverage.txt
          flags: e2e-test-oncluster
          fail_ci_if_error: true
          verbose: true
          token: ${{ secrets.CODECOV_TOKEN }}

  build:
    needs: [check, test-unit, test-integration, e2e-test, e2e-on-cluster-test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      # Standard build tasks
      - name: Build
        run: make cross-platform
      # Upload all build artifacts
      - uses: actions/upload-artifact@v4
        with:
          name: OSX Binary (AMD)
          path: func_darwin_amd64
      - uses: actions/upload-artifact@v4
        with:
          name: OSX Binary (ARM)
          path: func_darwin_arm64
      - uses: actions/upload-artifact@v4
        with:
          name: Linux Binary (AMD)
          path: func_linux_amd64
      - uses: actions/upload-artifact@v4
        with:
          name: Linux Binary (ARM)
          path: func_linux_arm64
      - uses: actions/upload-artifact@v4
        with:
          name: Linux Binary (PPC64LE)
          path: func_linux_ppc64le
      - uses: actions/upload-artifact@v4
        with:
          name: Linux Binary (S390X)
          path: func_linux_s390x
      - uses: actions/upload-artifact@v4
        with:
          name: Windows Binary
          path: func_windows_amd64.exe

  publish-utils-image:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      - uses: docker/setup-qemu-action@v3
      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        run: |
          for a in amd64 arm64 ppc64le s390x; do
            CGO_ENABLED=0 go build -o "func-util-$a" -trimpath -ldflags '-w -s' ./cmd/func-util
          done
          docker buildx create --name multiarch --driver docker-container --use
          docker buildx build . -f Dockerfile.utils \
            --platform=linux/ppc64le,linux/s390x,linux/amd64,linux/arm64 \
            --push \
            -t "ghcr.io/knative/func-utils:v2" \
            --annotation index:org.opencontainers.image.description="Knative Func Utils Image" \
            --annotation index:org.opencontainers.image.source="https://github.com/knative/func" \
            --annotation index:org.opencontainers.image.vendor="https://github.com/knative/func" \
            --annotation index:org.opencontainers.image.url="https://github.com/knative/func/pkgs/container/func-utils"

  publish-image:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: knative/actions/setup-go@main
      - uses: imjasonh/setup-ko@v0.6
      - run: ko build --platform=linux/ppc64le,linux/s390x,linux/amd64,linux/arm64 -B ./cmd/func
