# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-task.md
name: Release

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

on:
  push:
    tags:
      - "[0-9]+.[0-9]+.[0-9]+*"

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

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Create changelog
        uses: arduino/create-changelog@v1
        with:
          tag-regex: '^[0-9]+\.[0-9]+\.[0-9]+.*$'
          filter-regex: '^\[(skip|changelog)[ ,-](skip|changelog)\].*'
          case-insensitive-regex: true
          changelog-file-path: "${{ env.DIST_DIR }}/CHANGELOG.md"

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

      - name: Build
        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-release-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 }}"
          TAG="${GITHUB_REF/refs\/tags\//}"
          PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${TAG}_${{ 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 }}

  create-release:
    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: Identify Prerelease
        # This is a workaround while waiting for create-release action
        # to implement auto pre-release based on tag
        id: prerelease
        run: |
          wget -q -P /tmp https://github.com/fsaintjacques/semver-tool/archive/3.0.0.zip
          unzip -p /tmp/3.0.0.zip semver-tool-3.0.0/src/semver >/tmp/semver && chmod +x /tmp/semver
          if [[ "$(/tmp/semver get prerel "${GITHUB_REF/refs\/tags\//}")" ]]; then echo "::set-output name=IS_PRE::true"; fi

      - name: Create Github Release and upload artifacts
        uses: ncipollo/release-action@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          bodyFile: ${{ env.DIST_DIR }}/CHANGELOG.md
          draft: false
          prerelease: ${{ steps.prerelease.outputs.IS_PRE }}
          # NOTE: "Artifact is a directory" warnings are expected and don't indicate a problem
          # (all the files we need are in the DIST_DIR root)
          artifacts: ${{ env.DIST_DIR }}/*

      - name: Upload release files on Arduino downloads servers
        uses: docker://plugins/s3
        env:
          PLUGIN_SOURCE: "${{ env.DIST_DIR }}/*"
          PLUGIN_TARGET: ${{ env.AWS_PLUGIN_TARGET }}
          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 }}

      - name: Update Homebrew formula
        if: steps.prerelease.outputs.IS_PRE != 'true'
        uses: dawidd6/action-homebrew-bump-formula@v3
        with:
          token: ${{ secrets.ARDUINOBOT_GITHUB_TOKEN }}
          formula: arduino-cli
