name: Docker Image Build & Push
description: Build Docker image and push to a container registry

inputs:
  registry-url:
    description: Docker container registry server URL
    required: true
  registry-username:
    description: Docker container registry username
    required: true
  registry-password:
    description: Docker container registry password
    required: true
  image-name:
    description: Docker image name
    required: true
  metadata-tags:
    description: List of tags as key-value pair attributes
    required: true
  metadata-labels:
    description: List of labels as key-value pair attributes
    required: false
  docker-context:
    description: Docker build's context
    required: false
  docker-file:
    description: Path to the Dockerfile
    required: false
  docker-args:
    description: List of build args as key-value pair attributes
    required: false
  trivy:
    description: Run Trivy vulnerability scanner
    required: false
    default: 'false'

runs:
  using: composite
  steps:
  - name: Log in to Docker Container Registry
    # See https://github.com/docker/login-action/commits/master/
    uses: docker/login-action@327cd5a69de6c009b9ce71bce8395f28e651bf99
    with:
      registry: ${{ inputs.registry-url }}
      username: ${{ inputs.registry-username }}
      password: ${{ inputs.registry-password }}

  - name: Extract metadata
    id: meta
    # See https://github.com/docker/metadata-action/commits/master/
    uses: docker/metadata-action@8e1d5461f02b7886d3c1a774bfbd873650445aa2
    with:
      images: ${{ inputs.registry-url }}/${{ inputs.image-name }}
      tags: ${{ inputs.metadata-tags }}
      labels: ${{ inputs.metadata-labels }}

  - name: Set up Docker Buildx
    # See https://github.com/docker/setup-buildx-action/commits/master/
    uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca

  - name: Set Environment variables
    run: |
      DOCKER_LAYERS_PATH="/tmp/.buildx-cache-${{ inputs.image-name }}"
      echo "DOCKER_LAYERS_PATH=${DOCKER_LAYERS_PATH}" >> $GITHUB_ENV
    shell: bash

    # See https://github.com/docker/build-push-action/issues/252#issuecomment-744400434
  - name: Cache Docker layers
    # See https://github.com/actions/cache/commits/main/
    uses: actions/cache@36f1e144e1c8edb0a652766b484448563d8baf46
    with:
      path: ${{ env.DOCKER_LAYERS_PATH }}
      key: ${{ runner.os }}-buildx-${{ inputs.image-name }}-${{ github.sha }}
      restore-keys: ${{ runner.os }}-buildx-${{ inputs.image-name }}

  - name: Build and push Docker image
    # See https://github.com/docker/build-push-action/commits/master/
    uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991
    with:
      context: ${{ inputs.docker-context }}
      file: ${{ inputs.docker-file }}
      push: true
      provenance: false
      tags: ${{ steps.meta.outputs.tags }}
      build-args: ${{ inputs.docker-args }}
      labels: ${{ steps.meta.outputs.labels }}
      cache-from: type=local,src=${{ env.DOCKER_LAYERS_PATH }}
      cache-to: type=local,dest=${{ env.DOCKER_LAYERS_PATH }}-new

  - name: Move Docker layers cache
    run: |
      rm -rf ${{ env.DOCKER_LAYERS_PATH }}
      mv ${{ env.DOCKER_LAYERS_PATH }}-new ${{ env.DOCKER_LAYERS_PATH }}
    shell: bash

  - name: Run Trivy vulnerability scanner
    if: ${{ inputs.trivy == 'true' }}
    # See https://github.com/aquasecurity/trivy-action/commits/master/
    uses: aquasecurity/trivy-action@a11da62073708815958ea6d84f5650c78a3ef85b
    with:
      image-ref: ${{ fromJSON(steps.meta.outputs.json).tags[0] }}
      format: json
      output: trivy-results.json

  - name: Convert Trivy JSON report into sarif
    if: ${{ inputs.trivy == 'true' }}
    run: |
      trivy convert --format sarif --output trivy-results.sarif trivy-results.json
      trivy convert --format table --output trivy-results.table trivy-results.json

      if [[ -s trivy-results.table ]]; then
        {
          echo "### Security Output"
          echo "<details><summary>Click to expand</summary>"
          echo ""
          echo '```markdown'
          cat trivy-results.table
          echo '```'
          echo "</details>"
        } >> $GITHUB_STEP_SUMMARY
      fi
    shell: bash

  - name: Upload Trivy scan results to GitHub Security tab
    if: ${{ inputs.trivy == 'true' }}
    # See https://github.com/github/codeql-action/commits/main/
    uses: github/codeql-action/upload-sarif@606392577144219644443c010bc0e17ad563e559
    with:
      sarif_file: trivy-results.sarif
      category: ${{ fromJSON(steps.meta.outputs.json).tags[0] }}