name: ci

on:
  workflow_dispatch:
    inputs:
      buildx-version:
        description: 'Buildx version or Git context'
        default: 'latest'
        required: false
      buildkit-image:
        description: 'BuildKit image'
        default: 'moby/buildkit:buildx-stable-1'
        required: false
  push:
    branches:
      - 'master'
  pull_request:
    branches:
      - 'master'

env:
  BUILDX_VERSION: latest
  BUILDKIT_IMAGE: moby/buildkit:buildx-stable-1

jobs:
  minimal:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: action
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./action
        with:
          file: ./test/Dockerfile

  git-context:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: action
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build and push
        id: docker_build
        uses: ./action
        with:
          file: ./test/Dockerfile
          builder: ${{ steps.buildx.outputs.name }}
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            localhost:5000/name/app:latest
            localhost:5000/name/app:1.0.0
      -
        name: Inspect
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:1.0.0 --format '{{json .}}'
      -
        name: Check digest
        run: |
          if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
            echo "::error::Digest should not be empty"
            exit 1
          fi

  git-context-secret:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
        with:
          path: action
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build and push
        id: docker_build
        uses: ./action
        with:
          file: ./test/Dockerfile
          builder: ${{ steps.buildx.outputs.name }}
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            localhost:5000/name/app:latest
            localhost:5000/name/app:1.0.0
          secrets: |
            GIT_AUTH_TOKEN=${{ github.token }}
            "MYSECRET=aaaaaaaa
            bbbbbbb
            ccccccccc"
            FOO=bar
            "EMPTYLINE=aaaa

            bbbb
            ccc"
      -
        name: Inspect
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:1.0.0 --format '{{json .}}'
      -
        name: Check digest
        run: |
          if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
            echo "::error::Digest should not be empty"
            exit 1
          fi

  path-context:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build and push
        id: docker_build
        uses: ./
        with:
          context: ./test
          file: ./test/Dockerfile
          builder: ${{ steps.buildx.outputs.name }}
          push: true
          tags: |
            localhost:5000/name/app:latest
            localhost:5000/name/app:1.0.0
      -
        name: Inspect
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:1.0.0 --format '{{json .}}'
      -
        name: Check digest
        run: |
          if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
            echo "::error::Digest should not be empty"
            exit 1
          fi

  error:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Stop docker
        run: |
          sudo systemctl stop docker
      -
        name: Build
        id: docker_build
        continue-on-error: true
        uses: ./
        with:
          context: ./test
          file: ./test/Dockerfile
      -
        name: Check
        run: |
          echo "${{ toJson(steps.docker_build) }}"
          if [ "${{ steps.docker_build.outcome }}" != "failure" ] || [ "${{ steps.docker_build.conclusion }}" != "success" ]; then
            echo "::error::Should have failed"
            exit 1
          fi

  error-buildx:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        id: docker_build
        continue-on-error: true
        uses: ./
        with:
          context: ./test
          file: ./test/Dockerfile
          platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
          push: true
          tags: localhost:5000/name/app:latest
      -
        name: Check
        run: |
          echo "${{ toJson(steps.docker_build) }}"
          if [ "${{ steps.docker_build.outcome }}" != "failure" ] || [ "${{ steps.docker_build.conclusion }}" != "success" ]; then
            echo "::error::Should have failed"
            exit 1
          fi

  docker-driver:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Build
        id: docker_build
        uses: ./
        with:
          context: ./test
          file: ./test/Dockerfile
          push: true
          tags: localhost:5000/name/app:latest

  export-docker:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/Dockerfile
          load: true
          tags: myimage:latest
      -
        name: Inspect
        run: |
          docker image inspect myimage:latest

  secret:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: .
          file: ./test/secret.Dockerfile
          secrets: |
            MYSECRET=foo
            INVALID_SECRET=

  network:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: List networks
        run: docker network ls
      -
        name: Build
        uses: ./
        with:
          context: ./test
          tags: name/app:latest
          network: host

  shm-size:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/shmsize.Dockerfile
          tags: name/app:latest
          shm-size: 2g

  ulimit:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/ulimit.Dockerfile
          tags: name/app:latest
          ulimit: |
            nofile=1024:1024
            nproc=3

  cgroup-parent:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/cgroup.Dockerfile
          tags: name/app:latest
          cgroup-parent: foo

  add-hosts:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/addhost.Dockerfile
          tags: name/app:latest
          add-hosts: |
            docker:10.180.0.1
            foo:10.0.0.1

  build-contexts:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/buildcontext.Dockerfile
          build-contexts: |
            alpine=docker-image://debian:stable-slim
          tags: name/app:latest

  no-cache-filters:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/nocachefilter.Dockerfile
          no-cache-filters: build
          tags: name/app:latest
          cache-from: type=gha,scope=nocachefilter
          cache-to: type=gha,scope=nocachefilter,mode=max

  attests-compat:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - buildx: latest
            buildkit: moby/buildkit:buildx-stable-1
          - buildx: latest
            buildkit: moby/buildkit:v0.10.6
          - buildx: v0.9.1
            buildkit: moby/buildkit:buildx-stable-1
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ matrix.buildx }}
          driver-opts: |
            network=host
            image=${{ matrix.buildkit }}
      -
        name: Build
        uses: ./
        with:
          context: ./test/go
          file: ./test/go/Dockerfile
          outputs: type=cacheonly

  provenance:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        attrs:
          - ''
          - mode=max
          - builder-id=foo
          - false
          - true
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test/go
          file: ./test/go/Dockerfile
          target: binary
          outputs: type=oci,dest=/tmp/build.tar
          provenance: ${{ matrix.attrs }}
          cache-from: type=gha,scope=provenance
          cache-to: type=gha,scope=provenance,mode=max

  sbom:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: image
            output: type=image,name=localhost:5000/name/app:latest,push=true
          - target: binary
            output: /tmp/buildx-build
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test/go
          file: ./test/go/Dockerfile
          target: ${{ matrix.target }}
          outputs: ${{ matrix.output }}
          sbom: true
          cache-from: type=gha,scope=attests-${{ matrix.target }}
          cache-to: type=gha,scope=attests-${{ matrix.target }},mode=max
      -
        name: Inspect image
        if: matrix.target == 'image'
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:latest --format '{{json .}}'
      -
        name: Check output folder
        if: matrix.target == 'binary'
        run: |
          tree /tmp/buildx-build
      -
        name: Print provenance
        if: matrix.target == 'binary'
        run: |
          cat /tmp/buildx-build/provenance.json | jq
      -
        name: Print SBOM
        if: matrix.target == 'binary'
        run: |
          cat /tmp/buildx-build/sbom.spdx.json | jq

  multi:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        dockerfile:
          - multi
          - multi-sudo
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build and push
        id: docker_build
        uses: ./
        with:
          context: ./test
          file: ./test/${{ matrix.dockerfile }}.Dockerfile
          builder: ${{ steps.buildx.outputs.name }}
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            localhost:5000/name/app:latest
            localhost:5000/name/app:1.0.0
      -
        name: Inspect
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:1.0.0 --format '{{json .}}'
      -
        name: Check digest
        run: |
          if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
            echo "::error::Digest should not be empty"
            exit 1
          fi

  digest:
    runs-on: ubuntu-latest
    env:
      DOCKER_IMAGE: localhost:5000/name/app
    strategy:
      fail-fast: false
      matrix:
        driver:
          - docker
          - docker-container
        load:
          - true
          - false
        push:
          - true
          - false
        exclude:
          - driver: docker
            load: true
            push: true
          - driver: docker-container
            load: true
            push: true
          - driver: docker
            load: false
            push: false
          - driver: docker-container
            load: false
            push: false
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver: ${{ matrix.driver }}
          driver-opts: |
            network=host
      -
        name: Build
        id: docker_build
        uses: ./
        with:
          context: ./test
          load: ${{ matrix.load }}
          push: ${{ matrix.push }}
          tags: ${{ env.DOCKER_IMAGE }}:latest
          platforms: ${{ matrix.platforms }}
      -
        name: Docker images
        run: |
          docker image ls --no-trunc
      -
        name: Check digest
        if: ${{ matrix.push }}
        run: |
          if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
            echo "::error::Digest should not be empty"
            exit 1
          fi
      -
        name: Check manifest
        if: ${{ matrix.push }}
        run: |
          set -x
          docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}@${{ steps.docker_build.outputs.digest }} --format '{{json .}}'
      -
        name: Check image ID
        run: |
          if [ -z "${{ steps.docker_build.outputs.imageid }}" ]; then
            echo "::error::Image ID should not be empty"
            exit 1
          fi
      -
        name: Inspect image
        if: ${{ matrix.load }}
        run: |
          set -x
          docker image inspect ${{ steps.docker_build.outputs.imageid }}

  registry-cache:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build and push
        id: docker_build
        uses: ./
        with:
          context: ./test
          file: ./test/multi.Dockerfile
          builder: ${{ steps.buildx.outputs.name }}
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            localhost:5000/name/app:latest
            localhost:5000/name/app:1.0.0
          cache-from: type=registry,ref=localhost:5000/name/app
          cache-to: type=inline
      -
        name: Inspect
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:latest --format '{{json .}}'
      -
        name: Check digest
        run: |
          if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
            echo "::error::Digest should not be empty"
            exit 1
          fi

  github-cache:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
          buildkitd-flags: --debug
      -
        name: Build and push
        uses: ./
        with:
          context: ./test
          file: ./test/multi.Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            localhost:5000/name/app:latest
            localhost:5000/name/app:1.0.0
          cache-from: type=gha,scope=ci-${{ matrix.buildx_version }}
          cache-to: type=gha,scope=ci-${{ matrix.buildx_version }}
      -
        name: Inspect
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:1.0.0 --format '{{json .}}'

  standalone:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Uninstall moby cli
        run: |
          sudo apt-get purge -y moby-cli moby-buildx
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          context: ./test
          file: ./test/Dockerfile
