#
# This GitHub action builds Packer binaries, linux packages,
# and Docker images from source, and uploads them to GitHub artifacts.
# Note that artifacts available via GitHub Artifacts are not codesigned or notarized.
#

name: build

on: 
  workflow_dispatch: 
  workflow_call:
  push:
    branches:
      - main
      - release/**

env:
  REPO_NAME: "packer"

permissions:
  contents: read

jobs:
  get-go-version:
    runs-on: ubuntu-latest
    outputs:
      go-version: ${{ steps.get-go-version.outputs.go-version }}
    steps:
      - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: 'Determine Go version'
        id: get-go-version
        # We use .go-version as our source of truth for current Go
        # version, because "goenv" can react to it automatically.
        run: |
          echo "Building with Go $(cat .go-version)"
          echo "go-version=$(cat .go-version)" >> $GITHUB_OUTPUT

  set-product-version:
    runs-on: ubuntu-latest
    outputs:
      product-version: ${{ steps.set-product-version.outputs.product-version }}
      base-product-version: ${{ steps.set-product-version.outputs.base-product-version }}
      product-date: ${{ steps.get-product-version.outputs.product-date }}
      product-prerelease-version: ${{ steps.set-product-version.outputs.prerelease-product-version }}
      set-ld-flags: ${{ steps.set-ld-flags.outputs.set-ld-flags }}
    steps:
      - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: set product version
        id: set-product-version
        uses: hashicorp/actions-set-product-version@v1
      - name: set-ld-flags
        id: set-ld-flags
        run: |
          T="github.com/hashicorp/packer/version"
          echo "set-ld-flags=-s -w -X ${T}.GitCommit=${GITHUB_SHA::8} -X ${T}.GitDescribe=${{ steps.set-product-version.outputs.product-version }} -X ${T}.Version=${{ steps.set-product-version.outputs.base-product-version }} -X ${T}.VersionPrerelease=${{ steps.set-product-version.outputs.prerelease-product-version }} -X ${T}.VersionMetadata=" >> $GITHUB_OUTPUT
      - name: validate outputs
        run: |
          echo "Product Version: ${{ steps.set-product-version.outputs.product-version }}"
          echo "Base Product Version: ${{ steps.set-product-version.outputs.base-product-version }}"
          echo "Prerelease Version: ${{ steps.set-product-version.outputs.prerelease-product-version }}"
          echo "ldflags: ${{ steps.set-ld-flags.outputs.set-ld-flags }}"

  generate-metadata-file:
    needs: set-product-version
    runs-on: ubuntu-latest
    outputs:
      filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
    steps:
      - name: 'Checkout directory'
        uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: Generate metadata file
        id: generate-metadata-file
        uses: hashicorp/actions-generate-metadata@main
        with:
          version: ${{ needs.set-product-version.outputs.product-version }}
          product: ${{ env.REPO_NAME }}

      - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
        with:
          name: metadata.json
          path: ${{ steps.generate-metadata-file.outputs.filepath }}
  
  build-other:
    needs:
      - set-product-version
      - get-go-version
    runs-on: ubuntu-latest
    strategy:
      matrix:
        goos: [ freebsd, windows, netbsd, openbsd, solaris ]
        goarch: [ "386", "amd64", "arm"]
        go: [ "${{ needs.get-go-version.outputs.go-version }}" ]
        exclude:
          - goos: solaris
            goarch: 386
          - goos: solaris
            goarch: arm
          - goos: windows
            goarch: arm
      fail-fast: true

    name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build

    env:
      GOPRIVATE: "github.com/hashicorp"
      GO111MODULE: on
    steps:
      - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: Go Build
        env:
          PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
          PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version }}
          LD_FLAGS: "${{ needs.set-product-version.outputs.set-ld-flags}}"
          CGO_ENABLED: "0"
        uses: hashicorp/actions-go-build@v0.1.9
        with:
          product_name: ${{ env.REPO_NAME }}
          product_version: ${{ needs.set-product-version.outputs.product-version }}
          go_version: ${{ matrix.go }}
          os: ${{ matrix.goos }}
          arch: ${{ matrix.goarch }}
          reproducible: report
          instructions: |-
            go build -o "$BIN_PATH" -ldflags="$LD_FLAGS" -trimpath -buildvcs=false    

  build-linux:
    needs:
      - set-product-version
      - get-go-version
    runs-on: ubuntu-latest
    strategy:
      matrix:
        goos: [ linux ]
        goarch: [ "arm", "arm64", "386", "amd64", "ppc64le"]
        go: [ "${{ needs.get-go-version.outputs.go-version }}" ]
      fail-fast: true

    name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build

    env:
      GOPRIVATE: "github.com/hashicorp"
      GO111MODULE: on

    steps:
      - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: Go Build
        env:
          PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
          PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version }}
          LD_FLAGS: "${{ needs.set-product-version.outputs.set-ld-flags}}"
          CGO_ENABLED: "0"
        uses: hashicorp/actions-go-build@v0.1.9
        with:
          product_name: ${{ env.REPO_NAME }}
          product_version: ${{ needs.set-product-version.outputs.product-version }}
          go_version: ${{ matrix.go }}
          os: ${{ matrix.goos }}
          arch: ${{ matrix.goarch }}
          reproducible: report
          instructions: |-
            go build -o "$BIN_PATH" -ldflags="$LD_FLAGS" -trimpath -buildvcs=false

      - name: Linux Packaging
        uses: hashicorp/actions-packaging-linux@v1
        with:
          name: ${{ env.REPO_NAME }}
          description: "HashiCorp Packer - A tool for creating identical machine images for multiple platforms from a single source configuration"
          arch: ${{ matrix.goarch }}
          version: ${{ needs.set-product-version.outputs.product-version }}
          maintainer: "HashiCorp"
          homepage: "https://www.packer.io/docs"
          license: "BUSL-1.1"
          binary: "dist/${{ env.REPO_NAME }}"
          deb_depends: "openssl"
          rpm_depends: "openssl"
      - name: Add Linux Package names to env
        run: |
          echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV
          echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV
      - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
        with:
          name: ${{ env.RPM_PACKAGE }}
          path: out/${{ env.RPM_PACKAGE }}
      - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
        with:
          name: ${{ env.DEB_PACKAGE }}
          path: out/${{ env.DEB_PACKAGE }}

  build-darwin:
    needs:
      - set-product-version
      - get-go-version
    runs-on: macos-latest
    strategy:
      matrix:
        goos: [ darwin ]
        goarch: [ "amd64", "arm64" ]
        go: [ "${{ needs.get-go-version.outputs.go-version }}" ]
      fail-fast: true
    name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build

    env:
      GOPRIVATE: "github.com/hashicorp"
      GO111MODULE: on

    steps:
      - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: Go Build
        env:
          PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
          PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version }}
          LD_FLAGS: "${{ needs.set-product-version.outputs.set-ld-flags}}"
          CGO_ENABLED: "0"
        uses: hashicorp/actions-go-build@v0.1.9
        with:
          product_name: ${{ env.REPO_NAME }}
          product_version: ${{ needs.set-product-version.outputs.product-version }}
          go_version: ${{ matrix.go }}
          os: ${{ matrix.goos }}
          arch: ${{ matrix.goarch }}
          reproducible: report
          instructions: |-
            go build -o "$BIN_PATH" -ldflags="$LD_FLAGS" -tags netcgo -trimpath -buildvcs=false

  build-docker-light:
    name: Docker light ${{ matrix.arch }} build
    needs:
      - set-product-version
      - build-linux
    runs-on: ubuntu-latest
    strategy:
      matrix:
        arch: [ "arm", "arm64", "386", "amd64" ]
    env:
      version: ${{ needs.set-product-version.outputs.product-version }}
    steps:
      - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: Docker Build (Action)
        uses: hashicorp/actions-docker-build@v1
        with:
          version: ${{ env.version }}
          target: release-light
          arch: ${{ matrix.arch }}
          tags: |
            docker.io/hashicorp/${{ env.REPO_NAME }}:light
            docker.io/hashicorp/${{ env.REPO_NAME }}:light-${{ env.version }}
            docker.io/hashicorp/${{ env.REPO_NAME }}:${{ env.version }}
            public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:light
            public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:light-${{ env.version }}
            public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:${{ env.version }}
          dev_tags: |
            docker.io/hashicorppreview/${{ env.REPO_NAME }}:${{ env.version }}
            docker.io/hashicorppreview/${{ env.REPO_NAME }}:${{ env.version }}-${{ github.sha }}

  build-docker-full:
    name: Docker full ${{ matrix.arch }} build
    needs:
      - set-product-version
      - build-linux
    runs-on: ubuntu-latest
    strategy:
      matrix:
        arch: [ "arm", "arm64", "386", "amd64" ]
    env:
      version: ${{ needs.set-product-version.outputs.product-version }}
    steps:
      - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
      - name: Docker Build (Action)
        uses: hashicorp/actions-docker-build@v1
        with:
          version: ${{ env.version }}
          target: release-full
          arch: ${{ matrix.arch }}
          tags: |
            docker.io/hashicorp/${{ env.REPO_NAME }}:full
            docker.io/hashicorp/${{ env.REPO_NAME }}:full-${{ env.version }}
            public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:full
            public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:full-${{ env.version }}
          dev_tags: |
            docker.io/hashicorppreview/${{ env.REPO_NAME }}:full-${{ env.version }}
            docker.io/hashicorppreview/${{ env.REPO_NAME }}:full-${{ env.version }}-${{ github.sha }}
