name: atlantis-image

on:
  push:
    branches:
      - 'main'
      - 'release-**'
    tags:
      - v*.*.* # stable release like, v0.19.2
      - v*.*.*-pre.* # pre release like, v0.19.0-pre.calendardate
  pull_request:
    branches:
      - 'main'
      - 'release-**'
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

jobs:
  changes:
    outputs:
      should-run-build: ${{ steps.changes.outputs.src == 'true' || startsWith(github.ref, 'refs/tags/') }}
    if: github.event.pull_request.draft == false
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v2
        id: changes
        with:
          filters: |
            src:
              - 'Dockerfile'
              - 'docker-entrypoint.sh'
              - '.github/workflows/atlantis-image.yml'
              - '**.go'
              - 'go.*'

  build:
    needs: [changes]
    if: needs.changes.outputs.should-run-build == 'true'
    name: Build Image
    strategy:
      matrix:
        image_type: [alpine, debian]
    runs-on: ubuntu-22.04
    env:
      # Set docker repo to either the fork or the main repo where the branch exists
      DOCKER_REPO: ghcr.io/${{ github.repository }}
      # Push if not a pull request and references the main branch
      PUSH: ${{ github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) }}

    steps:
    - uses: actions/checkout@v4

    # Lint the Dockerfile first before setting anything up
    - name: Lint Dockerfile
      uses: hadolint/hadolint-action@v3.1.0
      with:
        dockerfile: "Dockerfile"

    - name: Set up QEMU
      uses: docker/setup-qemu-action@v3
      with:
        image: tonistiigi/binfmt:latest
        platforms: arm64,arm

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
      # https://github.com/docker/build-push-action/issues/761#issuecomment-1575006515
      with:
        driver-opts: |
          image=moby/buildkit:v0.12.5

    # release version is the name of the tag i.e. v0.10.0
    # release version also has the image type appended i.e. v0.10.0-alpine
    # release tag is either pre-release or latest i.e. latest
    # release tag also has the image type appended i.e. latest-alpine
    # if it's v0.10.0 and alpine, it will do v0.10.0, v0.10.0-alpine, latest, latest-alpine
    # if it's v0.10.0 and debian, it will do v0.10.0-debian, latest-debian
    - name: Docker meta
      id: meta
      uses: docker/metadata-action@v5
      env:
        SUFFIX: ${{ format('-{0}', matrix.image_type) }}
      with:
        images: |
          ${{ env.DOCKER_REPO }}
        labels: |
          org.opencontainers.image.authors="@runatlantis Github Org"
          org.opencontainers.image.licenses=Apache-2.0
        tags: |
          # semver
          type=semver,pattern={{version}},prefix=v,suffix=${{ env.SUFFIX }}
          type=semver,pattern={{version}},prefix=v,enable=${{ matrix.image_type == 'alpine' }}
          type=semver,pattern={{major}}.{{minor}},prefix=v,suffix=${{ env.SUFFIX }}
          # dev
          type=raw,event=push,value=dev,enable={{is_default_branch}},suffix=${{ env.SUFFIX }}
          type=raw,event=push,value=dev,enable={{is_default_branch}},suffix=${{ env.SUFFIX }}-{{ sha }}
          type=raw,event=push,value=dev,enable=${{ github.ref == format('refs/heads/{0}', 'main') && matrix.image_type == 'alpine' }},suffix=
          # prerelease
          type=raw,event=tag,value=prerelease-latest,enable=${{ startsWith(github.ref, 'refs/tags/') && contains(github.ref, 'pre') && matrix.image_type == 'alpine' }},suffix=
          type=raw,event=tag,value=prerelease-latest,enable=${{ startsWith(github.ref, 'refs/tags/') && contains(github.ref, 'pre') }},suffix=${{ env.SUFFIX }}
          # latest
          type=raw,event=tag,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') && !contains(github.ref, 'pre') && matrix.image_type == 'alpine' }},suffix=
          type=raw,event=tag,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') && !contains(github.ref, 'pre') }},suffix=${{ env.SUFFIX }}
          # pr
          type=ref,event=pr,suffix=${{ env.SUFFIX }}
        flavor: |
          # This is disabled here so we can use the raw form above
          latest=false
          # Suffix is not used here since there's no way to disable it above

    - name: Login to Packages Container registry
      uses: docker/login-action@v3
      with:
        registry: ghcr.io
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    # Publish release to container registry
    - name: Populate release version
      if: contains(fromJson('["push", "pull_request"]'), github.event_name)
      run: echo "RELEASE_VERSION=${{ startsWith(github.ref, 'refs/tags/') && '${GITHUB_REF#refs/*/}' || 'dev' }}" >> $GITHUB_ENV

    - name: "Build ${{ env.PUSH == 'true' && 'and push' || '' }} ${{ env.DOCKER_REPO }} image"
      if: contains(fromJson('["push", "pull_request"]'), github.event_name)
      uses: docker/build-push-action@v5
      with:
        cache-from: type=gha
        cache-to: type=gha,mode=max
        context: .
        build-args: |
          ATLANTIS_BASE_TAG_TYPE=${{ matrix.image_type }}
          ATLANTIS_VERSION=${{ env.RELEASE_VERSION }}
          ATLANTIS_COMMIT=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
          ATLANTIS_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
        platforms: linux/arm64/v8,linux/amd64,linux/arm/v7
        push: ${{ env.PUSH }}
        tags: ${{ steps.meta.outputs.tags }}
        target: ${{ matrix.image_type }}
        labels: ${{ steps.meta.outputs.labels }}
        outputs: type=image,name=target,annotation-index.org.opencontainers.image.description=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.description'] }}

  skip-build:
    needs: [changes]
    if: needs.changes.outputs.should-run-build == 'false'
    name: Build Image
    strategy:
      matrix:
        image_type: [alpine, debian]
    runs-on: ubuntu-22.04
    steps:
      - run: 'echo "No build required"'
