name: Build and Test
on:
  push:
    branches:
    - "main"
    - "release/v*"
    paths-ignore:
    - "**/*.png"
  pull_request:
    branches:
    - "main"
    - "release/v*"
    paths-ignore:
    - "**/*.png"

permissions:
  contents: read

jobs:
  lint:
    runs-on: ubuntu-22.04
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps
    # Generate the installation manifests first, so it can check
    # for errors while running `make -k lint`
    - run: IMAGE_PULL_POLICY=Always make generate-manifests
    - run: make lint-deps
    - run: make -k lint

  gen-check:
    runs-on: ubuntu-22.04
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps
    - run: make -k gen-check

  license-check:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps
    - run: make -k licensecheck

  coverage-test:
    runs-on: ubuntu-latest
    permissions:
      contents: read   #  for actions/checkout
      id-token: write  #  for fetching OIDC token
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps

    # test
    - name: Run Coverage Tests
      run: make go.test.coverage
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e  # v5.1.1
      with:
        fail_ci_if_error: true
        files: ./coverage.xml
        name: codecov-envoy-gateway
        verbose: true
        use_oidc: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork) }}

  build:
    runs-on: ubuntu-latest
    needs: [lint, gen-check, license-check, coverage-test]
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps

    - name: Build EG Multiarch Binaries
      run: make build-multiarch PLATFORMS="linux_amd64 linux_arm64"

    - name: Upload EG Binaries
      uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882  # v4.4.3
      with:
        name: envoy-gateway
        path: bin/

  conformance-test:
    runs-on: ubuntu-latest
    needs: [build]
    strategy:
      fail-fast: false
      matrix:
        version: [ v1.29.10, v1.30.6, v1.31.4, v1.32.0 ]
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps

    - name: Download EG Binaries
      uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16  # v4.1.8
      with:
        name: envoy-gateway
        path: bin/

    - name: Give Privileges To EG Binaries
      run: |
        chmod +x bin/linux/amd64/envoy-gateway
        chmod +x bin/linux/arm64/envoy-gateway

    # conformance
    - name: Run Standard Conformance Tests
      env:
        KIND_NODE_TAG: ${{ matrix.version }}
        IMAGE_PULL_POLICY: IfNotPresent
      run: make conformance

  e2e-test:
    runs-on: ubuntu-latest
    needs: [build]
    strategy:
      fail-fast: false
      matrix:
        target:
        - version: v1.29.10
          ipFamily: ipv4
        - version: v1.30.6
          ipFamily: ipv4
        - version: v1.31.4
          ipFamily: ipv6  # only run ipv6 test on this version to save time
        # TODO: this's IPv4 first, need a way to test IPv6 first.
        - version: v1.32.0
          ipFamily: dual  # only run dual test on latest version to save time
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps

    - name: Download EG Binaries
      uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16  # v4.1.8
      with:
        name: envoy-gateway
        path: bin/

    - name: Give Privileges To EG Binaries
      run: |
        chmod +x bin/linux/amd64/envoy-gateway
        chmod +x bin/linux/arm64/envoy-gateway

    # E2E
    - name: Run E2E Tests
      env:
        KIND_NODE_TAG: ${{ matrix.target.version }}
        IMAGE_PULL_POLICY: IfNotPresent
        IP_FAMILY: ${{ matrix.target.ipFamily }}
        E2E_TIMEOUT: 1h
      run: make e2e

  benchmark-test:
    runs-on: ubuntu-latest
    # There's a different workflow for benchmark-test on push.
    if: ${{ ! startsWith(github.event_name, 'push') }}
    needs: [build]
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps

    - name: Setup Graphviz
      uses: ts-graphviz/setup-graphviz@b1de5da23ed0a6d14e0aeee8ed52fdd87af2363c  # v2.0.2

    # Benchmark
    - name: Run Benchmark tests
      env:
        KIND_NODE_TAG: v1.29.10
        IMAGE_PULL_POLICY: IfNotPresent
        # Args for benchmark test
        BENCHMARK_RPS: 10000
        BENCHMARK_CONNECTIONS: 100
        BENCHMARK_DURATION: 30
        BENCHMARK_CPU_LIMITS: 1000m
        BENCHMARK_MEMORY_LIMITS: 2000Mi
        BENCHMARK_REPORT_DIR: benchmark_report
      run: make benchmark

    - name: Read Benchmark report
      run: cat test/benchmark/benchmark_report/benchmark_report.md
  resilience-test:
    runs-on: ubuntu-latest
    if: ${{ ! startsWith(github.event_name, 'push') }}
    needs: [build]
    steps:
    - uses: actions/checkout@v4.2.2
    - uses: ./tools/github-actions/setup-deps
    - name: Resilience Test
      env:
        KIND_NODE_TAG: v1.28.13
        IMAGE_PULL_POLICY: IfNotPresent
        CUSTOM_CNI: "true"
      run: make resilience

  publish:
    runs-on: ubuntu-latest
    needs: [conformance-test, e2e-test]
    steps:
    - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2
    - uses: ./tools/github-actions/setup-deps

    - name: Download EG Binaries
      uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16  # v4.1.8
      with:
        name: envoy-gateway
        path: bin/

    - name: Give Privileges To EG Binaries
      run: |
        chmod +x bin/linux/amd64/envoy-gateway
        chmod +x bin/linux/arm64/envoy-gateway

    # build and push image
    - name: Login to DockerHub
      if: github.event_name == 'push'
      uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567  # v3.3.0
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_PASSWORD }}

    - name: Setup Multiarch Environment
      if: github.event_name == 'push'
      run: make image.multiarch.setup

    - name: Build and Push EG Commit Image
      if: github.event_name == 'push'
      # tag is set to the short SHA of the commit
      run: make image.push.multiarch PLATFORMS="linux_amd64 linux_arm64" IMAGE=envoyproxy/gateway-dev

    - name: Build and Push EG Latest Image
      if: github.event_name == 'push' && github.ref == 'refs/heads/main'
      # tag is set to `latest` when pushing to main branch
      run: make image.push.multiarch TAG=latest PLATFORMS="linux_amd64 linux_arm64" IMAGE=envoyproxy/gateway-dev

    - name: Build and Push EG Latest Helm Chart
      if: github.event_name == 'push' && github.ref == 'refs/heads/main'
      # use `0.0.0` as the default latest version.
      # use `Always` image pull policy for latest version.
      run: |
        IMAGE_PULL_POLICY=Always OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-push
        IMAGE_PULL_POLICY=Always OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=0.0.0-latest TAG=latest make helm-push