name: Check and publish Docker images

on:
  pull_request:
  push:
    branches: [master]
    tags:
      - 'v*'
      - '!v*-dev'
      - 'release'

defaults:
  run:
    shell: bash

env:
  IMAGE_NAME: zeek-image.tar
  IMAGE_FILE: /tmp/zeek-image.tar
  IMAGE_PATH: /tmp

jobs:
  docker-build:
    runs-on: ubuntu-latest
    env:
      TEST_TAG: zeek:latest
      CONFFLAGS: --generator=Ninja --build-type=Release --enable-zeek-client
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: "recursive"

      # Create and boot a loader. This will e.g., provide caching
      # so we avoid rebuilds of the same image after this step.
      - uses: docker/setup-buildx-action@v1

      - name: Build image
        uses: docker/build-push-action@v2
        with:
          context: ./
          file: docker/Dockerfile
          build-args: |
            CONFFLAGS=${{ env.CONFFLAGS }}
          load: true
          tags: ${{ env.TEST_TAG }}

      - name: Run btests
        run: make -C docker/btest

      - name: Save image tarball
        run: docker save -o ${{ env.IMAGE_FILE }} ${{ env.TEST_TAG }}

      - name: Get version
        id: version
        run: echo "::set-output name=RELEASE_VERSION::$(cat VERSION)"

      - name: Compute target tag
        id: target
        env:
          RELEASE_VERSION: ${{ steps.version.outputs.RELEASE_VERSION }}
        run: |
          # Translate the Github reference into a tag name.
          #
          # - `release` tag maps to `zeek:latest`
          # - `v*` tag (excluding `v*-dev` tags) maps to `zeek:RELEASE_VERSION`
          # - `master` branch maps to `zeek-dev:latest`
          #
          # Any other refs are not published below.
          if [ "${GITHUB_REF}" = "refs/tags/release" ]; then
            echo "::set-output name=tag::zeek:latest"
          elif [ "${GITHUB_REF}" = "refs/heads/master" ]; then
            echo "::set-output name=tag::zeek-dev:latest"
          elif [[ "${GITHUB_REF}" = refs/tags/v* ]] && [[ "${GITHUB_REF}" != refs/tags/v*-dev ]]; then
            echo "::set-output name=tag::zeek:${RELEASE_VERSION}"
          fi

      - name: Login to DockerHub
        uses: docker/login-action@v1
        # Don't publish on forks. Also note that secrets for the login are not
        # available for pull requests, so trigger on pushes only.
        if: github.repository == 'zeek/zeek' && github.event_name == 'push'
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Push image
        # Only publish if we did compute a tag.
        if: github.repository == 'zeek/zeek' && github.event_name == 'push' && steps.target.outputs.tag != ''
        uses: docker/build-push-action@v2
        with:
          context: ./
          file: docker/Dockerfile
          build-args: |
            CONFFLAGS=${{ env.CONFFLAGS }}
          push: true
          tags: |
            zeekurity/${{ steps.target.outputs.tag }}

      - name: Preserve image artifact
        uses: actions/upload-artifact@v2
        with:
          name: ${{ env.IMAGE_NAME }}
          path: ${{ env.IMAGE_FILE }}
          retention-days: 1

      - name: Preserve btest artifacts
        uses: actions/upload-artifact@v2
        if: failure()
        with:
          name: docker-btest
          path: docker/btest/.tmp
          if-no-files-found: ignore

  cluster-testing:
    # We need the Zeek Docker image build job to complete first, since we need
    # the resulting image for our docker-compose setup.
    needs: docker-build
    runs-on: ubuntu-latest
    steps:
      # Grab the sources so we have access to btest. Could also use pip, but it
      # seems appealing to be using the in-tree version of btest. btest is in a
      # submodule; we check it out selectively to save time.
      - uses: actions/checkout@v2
      - name: Check out btest
        run: git submodule update --init ./auxil/btest

      - name: Download Docker image artifact
        uses: actions/download-artifact@v2
        with:
          name: ${{ env.IMAGE_NAME }}
          path: ${{ env.IMAGE_PATH }}

      - name: Load Docker image
        run: |
          docker load --input ${{ env.IMAGE_FILE }}
          docker tag zeek:latest zeektest:latest

      # The testsuite ref to use for this version of Zeek is stored in a file in
      # the Zeek source tree.
      - name: Get testsuite version
        run: |
          echo "TESTSUITE_COMMIT=$(cat ./testing/external/commit-hash.zeek-testing-cluster)" >> $GITHUB_ENV

      - name: Retrieve cluster testsuite
        uses: actions/checkout@v2
        with:
          repository: zeek/zeek-testing-cluster
          path: testing/external/zeek-testing-cluster
          ref: ${{ ENV.TESTSUITE_COMMIT }}

      - name: Run testsuite
        run: make -C testing/external/zeek-testing-cluster

      - name: Preserve btest artifacts
        uses: actions/upload-artifact@v2
        if: failure()
        with:
          name: cluster-btest
          path: testing/external/zeek-testing-cluster/.tmp
          if-no-files-found: ignore
