name: Build and test
on:
  push:
    branches:
      - master
  pull_request:
    paths:
      - '.github/workflows/test.yml'
      - '**Makefile'
      - '**.go'
      - '**.proto'
      - 'go.mod'
      - 'go.sum'
jobs:

  static:
    name: Static checks
    runs-on: ubuntu-latest
    steps:

    - uses: actions/checkout@v6

    - uses: actions/setup-go@v6
      with:
        go-version: '1.26'
        check-latest: true

    - name: Install goimports
      run: go install golang.org/x/tools/cmd/goimports@latest

    - name: gofmt
      run: |
        if [ "$(find . -iname '*.go' | grep -v '\.pb\.go$' | xargs goimports -l)" ]
        then
          find . -iname '*.go' | grep -v '\.pb\.go$' | xargs goimports -d
          exit 1
        fi

    - name: Vet
      run: make vet

    - name: golangci-lint
      uses: golangci/golangci-lint-action@v9
      with:
        version: v2.12

  test:
    name: Test ${{ matrix.name }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
        - name: linux
          os: ubuntu-latest
          build-cmd: go build ./cmd/nebula ./cmd/nebula-cert
          test-cmd: make test
          e2e-cmd: make e2evv
        - name: linux-boringcrypto
          os: ubuntu-latest
          build-cmd: make boringcrypto
          test-cmd: make boringcrypto test
          e2e-cmd: make boringcrypto e2evv
        - name: linux-fips140
          os: ubuntu-latest
          build-cmd: make fips140
          test-cmd: make fips140 test
          e2e-cmd: make fips140 e2evv
        - name: linux-pkcs11
          os: ubuntu-latest
          build-cmd: make bin-pkcs11
          test-cmd: make test-pkcs11
          e2e-cmd: ''
        - name: macos
          os: macos-latest
          build-cmd: go build ./cmd/nebula ./cmd/nebula-cert
          test-cmd: make test
          e2e-cmd: make e2evv
        - name: windows
          os: windows-latest
          build-cmd: go build ./cmd/nebula ./cmd/nebula-cert
          test-cmd: make test
          e2e-cmd: make e2evv
    steps:

    - uses: actions/checkout@v6

    - uses: actions/setup-go@v6
      with:
        go-version: '1.26'
        check-latest: true

    - name: Build
      run: ${{ matrix.build-cmd }}

    - name: Cross-build darwin-amd64
      if: matrix.name == 'macos'
      run: GOARCH=amd64 go build -o /tmp/nebula-amd64 ./cmd/nebula && GOARCH=amd64 go build -o /tmp/nebula-cert-amd64 ./cmd/nebula-cert

    - name: Test
      run: ${{ matrix.test-cmd }}

    - name: End 2 end
      if: matrix.e2e-cmd != ''
      run: ${{ matrix.e2e-cmd }}

    - uses: actions/upload-artifact@v7
      if: matrix.e2e-cmd != '' && always()
      with:
        name: e2e packet flow ${{ matrix.name }}
        path: e2e/mermaid/
        if-no-files-found: warn

  cross-build:
    name: Cross-build ${{ matrix.name }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
        - {name: linux-arm,   make-target: all-cross-linux-arm}
        - {name: linux-mips,  make-target: all-cross-linux-mips}
        - {name: linux-other, make-target: all-cross-linux-other}
        - {name: freebsd,     make-target: all-freebsd}
        - {name: openbsd,     make-target: all-openbsd}
        - {name: netbsd,      make-target: all-netbsd}
        - {name: windows,     make-target: all-cross-windows}
        - {name: mobile,      make-target: build-test-mobile}
    steps:

    - uses: actions/checkout@v6

    - uses: actions/setup-go@v6
      with:
        go-version: '1.26'
        check-latest: true

    - name: Build ${{ matrix.name }}
      run: make -j"$(nproc)" ${{ matrix.make-target }}

  finish:
    name: CI status
    if: always()
    needs: [static, test, cross-build]
    runs-on: ubuntu-latest
    steps:

    - name: Fail if any upstream job failed
      if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
      run: |
        echo "upstream results: ${{ toJSON(needs) }}"
        exit 1

    - name: All upstream jobs passed
      run: echo "ok"
