# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/publish-go-nightly-task.md
name: Publish Nightly Build

env:
  # As defined by the Taskfile's PROJECT_NAME variable
  PROJECT_NAME: arduino-cli
  # As defined by the Taskfile's DIST_DIR variable
  DIST_DIR: dist
  # The project's folder on Arduino's download server for uploading builds
  AWS_PLUGIN_TARGET: /arduino-cli/
  ARTIFACT_NAME: dist

# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
on:
  schedule:
    # run every day at 1AM
    - cron: "0 1 * * *"
  workflow_dispatch:
  repository_dispatch:

jobs:
  create-nightly-artifacts:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Install Task
        uses: arduino/setup-task@v1
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          version: 3.x

      - name: Build
        env:
          NIGHTLY: true
        run: task dist:all

      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          if-no-files-found: error
          name: ${{ env.ARTIFACT_NAME }}
          path: ${{ env.DIST_DIR }}

  notarize-macos:
    name: Notarize ${{ matrix.artifact.name }}
    runs-on: macos-latest
    needs: create-nightly-artifacts
    outputs:
      checksum-darwin_amd64: ${{ steps.re-package.outputs.checksum-darwin_amd64 }}
      checksum-darwin_arm64: ${{ steps.re-package.outputs.checksum-darwin_arm64 }}

    env:
      GON_CONFIG_PATH: gon.config.hcl

    strategy:
      matrix:
        artifact:
          - name: darwin_amd64
            path: "macOS_64bit.tar.gz"
          - name: darwin_arm64
            path: "macOS_ARM64.tar.gz"

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          name: ${{ env.ARTIFACT_NAME }}
          path: ${{ env.DIST_DIR }}

      - name: Import Code-Signing Certificates
        env:
          KEYCHAIN: "sign.keychain"
          INSTALLER_CERT_MAC_PATH: "/tmp/ArduinoCerts2020.p12"
          KEYCHAIN_PASSWORD: keychainpassword # Arbitrary password for a keychain that exists only for the duration of the job, so not secret
        run: |
          echo "${{ secrets.INSTALLER_CERT_MAC_P12 }}" | base64 --decode > "${{ env.INSTALLER_CERT_MAC_PATH }}"
          security create-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}"
          security default-keychain -s "${{ env.KEYCHAIN }}"
          security unlock-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}"
          security import \
            "${{ env.INSTALLER_CERT_MAC_PATH }}" \
            -k "${{ env.KEYCHAIN }}" \
            -f pkcs12 \
            -A \
            -T /usr/bin/codesign \
            -P "${{ secrets.INSTALLER_CERT_MAC_PASSWORD }}"
          security set-key-partition-list \
            -S apple-tool:,apple: \
            -s \
            -k "${{ env.KEYCHAIN_PASSWORD }}" \
            "${{ env.KEYCHAIN }}"

      - name: Install gon for code signing and app notarization
        run: |
          wget -q https://github.com/mitchellh/gon/releases/download/v0.2.3/gon_macos.zip
          unzip gon_macos.zip -d /usr/local/bin

      - name: Write gon config to file
        # gon does not allow env variables in config file (https://github.com/mitchellh/gon/issues/20)
        run: |
          cat > "${{ env.GON_CONFIG_PATH }}" <<EOF
          # See: https://github.com/mitchellh/gon#configuration-file
          source = ["dist/arduino-cli_osx_${{ matrix.artifact.name }}/arduino-cli"]
          bundle_id = "cc.arduino.arduino-cli"

          sign {
            application_identity = "Developer ID Application: ARDUINO SA (7KT7ZWMCJT)"
          }

          # Ask Gon for zip output to force notarization process to take place.
          # The CI will ignore the zip output, using the signed binary only.
          zip {
            output_path = "unused.zip"
          }
          EOF

      - name: Sign and notarize binary
        env:
          AC_USERNAME: ${{ secrets.AC_USERNAME }}
          AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
        run: |
          gon "${{ env.GON_CONFIG_PATH }}"

      - name: Re-package binary and output checksum
        id: re-package
        working-directory: ${{ env.DIST_DIR }}
        # This step performs the following:
        # 1. Repackage the signed binary replaced in place by Gon (ignoring the output zip file)
        # 2. Recalculate package checksum
        # 3. Output the new checksum to include in the nnnnnn-checksums.txt file
        #    (it cannot be done there because of workflow job parallelization)
        run: |
          # GitHub's upload/download-artifact@v2 actions don't preserve file permissions,
          # so we need to add execution permission back until the action is made to do this.
          chmod +x "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/${{ env.PROJECT_NAME }}"
          # Use of an array here is required for globbing
          PACKAGE_FILENAME=(${{ env.PROJECT_NAME }}_nightly-*${{ matrix.artifact.path }})
          tar -czvf "$PACKAGE_FILENAME" \
          -C "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/" "${{ env.PROJECT_NAME }}" \
          -C ../../ LICENSE.txt
          CHECKSUM_LINE="$(shasum -a 256 $PACKAGE_FILENAME)"
          echo "PACKAGE_FILENAME=$PACKAGE_FILENAME" >> $GITHUB_ENV
          echo "::set-output name=checksum-${{ matrix.artifact.name }}::$CHECKSUM_LINE"

      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          if-no-files-found: error
          name: ${{ env.ARTIFACT_NAME }}
          path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }}

  publish-nightly:
    runs-on: ubuntu-latest
    needs: notarize-macos

    steps:
      - name: Download artifact
        uses: actions/download-artifact@v3
        with:
          name: ${{ env.ARTIFACT_NAME }}
          path: ${{ env.DIST_DIR }}

      - name: Update checksum
        run: |
          declare -a checksum_lines=("${{ needs.notarize-macos.outputs.checksum-darwin_amd64 }}" "${{ needs.notarize-macos.outputs.checksum-darwin_arm64 }}")
          for checksum_line in "${checksum_lines[@]}"
          do
            CHECKSUM=$(echo ${checksum_line} | cut -d " " -f 1)
            PACKAGE_FILENAME=$(echo ${checksum_line} | cut -d " " -f 2)
            perl -pi -w -e "s/.*${PACKAGE_FILENAME}/${CHECKSUM}  ${PACKAGE_FILENAME}/g;" ${{ env.DIST_DIR }}/*-checksums.txt
          done

      - name: Upload release files on Arduino downloads servers
        uses: docker://plugins/s3
        env:
          PLUGIN_SOURCE: "${{ env.DIST_DIR }}/*"
          PLUGIN_TARGET: "${{ env.AWS_PLUGIN_TARGET }}nightly"
          PLUGIN_STRIP_PREFIX: "${{ env.DIST_DIR }}/"
          PLUGIN_BUCKET: ${{ secrets.DOWNLOADS_BUCKET }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

  report:
    runs-on: ubuntu-latest
    needs: publish-nightly
    if: failure() # Run if publish-nightly or any of its job dependencies failed

    steps:
      - name: Report failure
        uses: masci/datadog@v1
        with:
          api-key: ${{ secrets.DD_API_KEY }}
          events: |
            - title: "${{ env.PROJECT_NAME }} nightly build failed"
              text: "Nightly build workflow has failed"
              alert_type: "error"
              host: ${{ github.repository }}
              tags:
                - "project:${{ env.PROJECT_NAME }}"
                - "workflow:${{ github.workflow }}"
