name: ci

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

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
  schedule:
    - cron: '0 10 * * *'
  push:
    branches:
      - 'master'
      - 'releases/v*'
    tags:
      - 'v*'
    paths-ignore:
      - '.github/workflows/ci-subaction.yml'
      - 'subaction/**'
  pull_request:
    paths-ignore:
      - '.github/workflows/ci-subaction.yml'
      - 'subaction/**'

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

jobs:
  bake:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        target:
          - default
          - release
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      -
        name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
            network=host
      -
        name: Build and push
        uses: ./
        with:
          builder: ${{ steps.buildx.outputs.name }}
          files: |
            ./test/config.hcl
          targets: |
            ${{ matrix.target }}
          push: false # set to true when https://github.com/docker/buildx/issues/179 is fixed

  error-msg:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Build
        continue-on-error: true
        uses: ./
        with:
          files: |
            ./test/config.hcl
          set: |
            *.platform=linux/amd64,linux/ppc64le,linux/s390x

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

  standalone:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Uninstall docker cli
        run: |
          if dpkg -s "docker-ce" >/dev/null 2>&1; then
            sudo dpkg -r --force-depends docker-ce-cli docker-buildx-plugin
          else
            sudo apt-get purge -y moby-cli moby-buildx
          fi
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl

  source:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Build
        uses: ./
        with:
          source: https://github.com/docker/buildx.git#v0.8.2
          targets: update-docs

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

  sbom:
    runs-on: ubuntu-latest
    env:
      DESTDIR: /tmp/bake-build
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: image
            output: type=image,name=localhost:5000/name/app:latest,push=true
          - target: binary
            output: /tmp/bake-build
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          workdir: ./test/go
          targets: ${{ matrix.target }}
          sbom: true
          set: |
            *.output=${{ matrix.output }}
            *.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'
        working-directory: ${{ env.DESTDIR }}
        run: |
          tree .
      -
        name: Print provenance
        if: matrix.target == 'binary'
        working-directory: ${{ env.DESTDIR }}
        run: |
          cat provenance.json | jq
      -
        name: Print SBOM
        if: matrix.target == 'binary'
        working-directory: ${{ env.DESTDIR }}
        run: |
          cat sbom.spdx.json | jq

  set:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Build
        uses: ./
        with:
          workdir: ./test/go
          set: |
            *.platform=linux/amd64
            *.output=type=image,"name=localhost:5000/name/app:v1.0.0,localhost:5000/name/app:latest",push=true
            *.tags=

  group:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
            network=host
      -
        name: Build and push
        uses: ./
        with:
          workdir: ./test/group
          push: true
          set: |
            t1.tags=localhost:5000/name/app:t1
            t2.tags=localhost:5000/name/app:t2

  docker-config-malformed:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set malformed docker config
        run: |
          mkdir -p ~/.docker
          echo 'foo_bar' >> ~/.docker/config.json
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl

  proxy-docker-config:
    runs-on: ubuntu-latest
    services:
      squid-proxy:
        image: ubuntu/squid:latest
        ports:
          - 3128:3128
    steps:
      -
        name: Check proxy
        run: |
          netstat -aptn
          curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy http://127.0.0.1:3128 -v --insecure --head https://www.google.com
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set proxy config
        run: |
          mkdir -p ~/.docker
          echo '{"proxies":{"default":{"httpProxy":"http://127.0.0.1:3128","httpsProxy":"http://127.0.0.1:3128"}}}' > ~/.docker/config.json
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
            network=host
          buildkitd-flags: --debug
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl
          targets: app-proxy

  proxy-buildkitd:
    runs-on: ubuntu-latest
    services:
      squid-proxy:
        image: ubuntu/squid:latest
        ports:
          - 3128:3128
    steps:
      -
        name: Check proxy
        run: |
          netstat -aptn
          curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy http://127.0.0.1:3128 -v --insecure --head https://www.google.com
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
            network=host
            env.http_proxy=http://127.0.0.1:3128
            env.https_proxy=http://127.0.0.1:3128
          buildkitd-flags: --debug
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl

  git-context:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          source: "{{defaultContext}}"

  git-context-and-local:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
      -
        name: Build
        uses: ./
        with:
          source: "{{defaultContext}}"
          files: |
            cwd://${{ steps.meta.outputs.bake-file }}

  multi-output:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
      -
        name: Build and push
        uses: ./
        with:
          workdir: ./test/go
          set: |
            *.output=type=image,name=localhost:5000/name/app:latest,push=true
            *.output=type=docker,name=app:local
            *.output=type=oci,dest=/tmp/oci.tar
      -
        name: Check registry
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:latest --format '{{json .}}'
      -
        name: Check docker
        run: |
          docker image inspect app:local
      -
        name: Check oci
        run: |
          set -ex
          mkdir -p /tmp/oci-out
          tar xf /tmp/oci.tar -C /tmp/oci-out
          tree -nh /tmp/oci-out

  load-and-push:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            network=host
      -
        name: Build and push
        uses: ./
        with:
          workdir: ./test/go
          targets: image
          load: true
          push: true
          set: |
            *.tags=localhost:5000/name/app:latest
      -
        name: Check registry
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:latest --format '{{json .}}'
      -
        name: Check docker
        run: |
          docker image inspect localhost:5000/name/app:latest

  summary-disable:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl
          targets: app
        env:
          DOCKER_BUILD_SUMMARY: false

  summary-disable-deprecated:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl
          targets: app
        env:
          DOCKER_BUILD_NO_SUMMARY: true

  summary-not-supported:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: v0.12.1
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl
          targets: app

  record-upload-disable:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl
          targets: app
        env:
          DOCKER_BUILD_RECORD_UPLOAD: false

  record-retention-days:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        days:
          - 2
          - 0
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl
          targets: app
        env:
          DOCKER_BUILD_RECORD_RETENTION_DAYS: ${{ matrix.days }}

  checks:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        buildx-version:
          - latest
          - v0.14.1
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ matrix.buildx-version }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          workdir: ./test
          files: |
            ./lint.hcl

  annotations-disabled:
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          workdir: ./test
          files: |
            ./lint.hcl
        env:
          DOCKER_BUILD_CHECKS_ANNOTATIONS: false

  allow:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        buildx-version:
          - v0.19.0-rc2
          - v0.18.0
          - v0.17.1
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          version: ${{ matrix.buildx-version }}
          driver-opts: |
            image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
      -
        name: Build
        uses: ./
        with:
          files: |
            ./test/config.hcl
          allow: network.host
          targets: app-entitlements
