name: CI

on:
  pull_request:
    branches:
      - "*"
    paths-ignore:
      - 'docs/**'
      - 'deploy/**'
      - '**.md'
      - 'images/**' # Images changes should be tested on their own workflow
      - '!images/nginx/**'

  push:
    branches:
      - main
      - release-*
    paths-ignore:
      - 'docs/**'
      - 'deploy/**'
      - '**.md'
      - 'images/**' # Images changes should be tested on their own workflow

  workflow_dispatch:
    inputs:
      run_e2e:
        description: 'Force e2e to run'
        required: false
        type: boolean


permissions:
  contents: read

jobs:

  changes:
    permissions:
      contents: read  # for dorny/paths-filter to fetch a list of changed files
      pull-requests: read  # for dorny/paths-filter to read pull requests
    runs-on: ubuntu-latest
    outputs:
      go: ${{ steps.filter.outputs.go }}
      charts: ${{ steps.filter.outputs.charts }}
      baseimage: ${{ steps.filter.outputs.baseimage }}

    steps:

      - name: Checkout
        uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

      - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
        id: filter
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          filters: |
            go:
              - '**/*.go'
              - 'go.mod'
              - 'go.sum'
              - 'rootfs/**/*'
              - 'TAG'
              - 'test/e2e/**/*'
              - 'NGINX_BASE'
            charts:
              - 'charts/ingress-nginx/Chart.yaml'
              - 'charts/ingress-nginx/**/*'
              - 'NGINX_BASE'
            baseimage:
              - 'NGINX_BASE'
              - 'images/nginx/**'
            docs:
              - '**/*.md'
            lua:
              - '**/*.lua'

  lua-lint:
    runs-on: ubuntu-latest
    needs: changes
    if: |
      (needs.changes.outputs.lua == 'true') || ${{ github.event.workflow_dispatch.run_e2e == 'true' }}
    steps:
      - name: Checkout
        uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
      
      - name: Lint Lua
        uses: lunarmodules/luacheck@v1
        with:
          args: --codes --globals lua_ingress --globals configuration --globals balancer --globals monitor --globals certificate --globals tcp_udp_configuration --globals tcp_udp_balancer --no-max-comment-line-length -q rootfs/etc/nginx/lua/

  test-go:
    runs-on: ubuntu-latest
    needs: changes
    if: |
      (needs.changes.outputs.go == 'true') || ${{ github.event.workflow_dispatch.run_e2e == 'true' }}
    steps:
      - name: Checkout
        uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

      - name: Get go version
        run: echo "GOLANG_VERSION=$(cat GOLANG_VERSION)" >> $GITHUB_ENV

      - name: Set up Go
        id: go
        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
          check-latest: true

      - name: Run test
        run: make test

        
  verify-docs:
    name: Verify Doc generation
    runs-on: ubuntu-latest
    needs: changes
    if: |
      (needs.changes.outputs.go == 'true') || (needs.changes.outputs.docs == 'true') || ${{ github.event.workflow_dispatch.run_e2e == 'true' }}
    steps:
      - name: Checkout
        uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
      - name: Get go version
        run: echo "GOLANG_VERSION=$(cat GOLANG_VERSION)" >> $GITHUB_ENV
      - name: Set up Go
        id: go
        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
          check-latest: true
      - name: Verify Docs
        run: make verify-docs

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: changes
    outputs:
      golangversion: ${{ steps.golangversion.outputs.version }}
    if: |
      (needs.changes.outputs.go == 'true') || (needs.changes.outputs.charts == 'true') || (needs.changes.outputs.baseimage == 'true') || ${{ github.event.workflow_dispatch.run_e2e == 'true' }}

    env:
        PLATFORMS: linux/amd64
    steps:
      - name: Checkout
        uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

      - name: Get go version
        id: golangversion
        run: |
          echo "version=$(cat GOLANG_VERSION)" >> "$GITHUB_OUTPUT"

      - name: Set up Go
        id: go
        uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
        with:
          go-version: ${{ steps.golangversion.outputs.version }}
          check-latest: true

      - name: Set up QEMU
        uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0

      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
        with:
          version: latest

      - name: Available platforms
        run: echo ${{ steps.buildx.outputs.platforms }}

      - name: Prepare Host
        run: |
          curl -LO https://dl.k8s.io/release/v1.34.2/bin/linux/amd64/kubectl
          chmod +x ./kubectl
          sudo mv ./kubectl /usr/local/bin/kubectl

      - name: Build NGINX Base image
        if: |
          needs.changes.outputs.baseimage == 'true'
        run: |
            export TAG=$(cat images/nginx/TAG)
            cd images/nginx/rootfs && docker buildx build --platform=${{ env.PLATFORMS }} --load -t registry.k8s.io/ingress-nginx/nginx:${TAG} .

      - name: Build images
        env:
          TAG: 1.0.0-dev
          ARCH: amd64
          REGISTRY: ingress-controller
        run: |
          echo "building images..."
          export TAGNGINX=$(cat images/nginx/TAG)
          make BASE_IMAGE=registry.k8s.io/ingress-nginx/nginx:${TAGNGINX} clean-image build image image-chroot
          make -C test/e2e-image image

          echo "creating images cache..."
          docker save \
            nginx-ingress-controller:e2e \
            ingress-controller/controller:1.0.0-dev \
            ingress-controller/controller-chroot:1.0.0-dev \
            | gzip > docker.tar.gz

      - name: cache
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
        with:
          name: docker.tar.gz
          path: docker.tar.gz
          retention-days: 5

  chart-lint:
    name: Chart / Lint
    runs-on: ubuntu-latest
    needs:
      - changes

    if: fromJSON(needs.changes.outputs.charts) || fromJSON(needs.changes.outputs.baseimage) || fromJSON(github.event.workflow_dispatch.run_e2e)

    steps:
      - name: Set up Python
        uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
        with:
          python-version: 3.x

      - name: Set up Helm
        uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
        with:
          version: v3.19.2

      - name: Set up Helm Chart Testing
        uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f

      - name: Set up Artifact Hub
        run: |
          curl --fail --location https://github.com/artifacthub/hub/releases/download/v1.20.0/ah_1.20.0_linux_amd64.tar.gz --output /tmp/ah.tar.gz
          echo "9027626f19ff9f3ac668f222917130ac885e289e922e1428bfd2e7f066324e31  /tmp/ah.tar.gz" | shasum --check
          sudo tar --extract --file /tmp/ah.tar.gz --directory /usr/local/bin ah

      - name: Set up Helm Docs
        uses: gabe565/setup-helm-docs-action@d5c35bdc9133cfbea3b671acadf50a29029e87c2 # v1.0.4

      - name: Set up Helm Unit Test
        run: helm plugin install https://github.com/helm-unittest/helm-unittest

      - name: Checkout code
        uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
        with:
          fetch-depth: 0

      - name: Lint chart
        run: |
          ct lint --config .ct.yaml
          ah lint --path charts/ingress-nginx

      - name: Check docs
        run: |
          helm-docs --chart-search-root charts
          git diff --exit-code charts/ingress-nginx/README.md

      - name: Run tests
        run: helm unittest charts/ingress-nginx --file "tests/**/*_test.yaml"

  chart-test:
    name: Chart / Test
    runs-on: ubuntu-latest
    needs:
      - changes
      - build
      - chart-lint

    if: fromJSON(needs.changes.outputs.charts) || fromJSON(needs.changes.outputs.baseimage) || fromJSON(github.event.workflow_dispatch.run_e2e)

    strategy:
      fail-fast: false
      matrix:
        k8s: [v1.30.13, v1.31.12, v1.32.8, v1.33.4, v1.34.0]

    steps:
      - name: Checkout code
        uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

      - name: Download cache
        uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
        with:
          name: docker.tar.gz

      - name: Load cache
        run: gzip --decompress --stdout docker.tar.gz | docker load

      - name: Run tests
        env:
          K8S_VERSION: ${{ matrix.k8s }}
          SKIP_IMAGE_CREATION: true
        run: |
          sudo mkdir -pm 777 "${HOME}/.kube"
          make kind-e2e-chart-tests

  kubernetes:
    name: Kubernetes
    needs:
      - changes
      - build
    if: |
      (needs.changes.outputs.go == 'true') || (needs.changes.outputs.baseimage == 'true') || ${{ github.event.workflow_dispatch.run_e2e == 'true' }}
    strategy:
      fail-fast: false
      matrix:
        k8s: [v1.30.13, v1.31.12, v1.32.8, v1.33.4, v1.34.0]
    uses: ./.github/workflows/zz-tmpl-k8s-e2e.yaml
    with:
      k8s-version: ${{ matrix.k8s }}

  kubernetes-chroot:
    name: Kubernetes chroot
    needs:
      - changes
      - build
    if: |
      (needs.changes.outputs.go == 'true') || (needs.changes.outputs.baseimage == 'true') || ${{ github.event.workflow_dispatch.run_e2e == 'true' }}
    strategy:
      fail-fast: false
      matrix:
        k8s: [v1.30.13, v1.31.12, v1.32.8, v1.33.4, v1.34.0]
    uses: ./.github/workflows/zz-tmpl-k8s-e2e.yaml
    with:
      k8s-version: ${{ matrix.k8s }}
      variation: "CHROOT"
