# 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: uno-r4-wifi-fwuploader-plugin
  # 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-fwuploader/plugins/
  ARTIFACT_NAME: dist

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

jobs:
  create-release-artifacts:
    runs-on: ubuntu-latest
    permissions:
      contents: read

    strategy:
      matrix:
        os:
          - Windows_32bit
          - Windows_64bit
          - Linux_32bit
          - Linux_64bit
          - Linux_ARMv6
          - Linux_ARMv7
          - Linux_ARM64
          - macOS_64bit
          - macOS_ARM64

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

      - name: Create changelog
        # Avoid creating the same changelog for each os
        if: matrix.os == 'Windows_32bit'
        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@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
          version: 3.x

      - name: Build
        run: task dist:${{ matrix.os }}

      - 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 }}
    permissions:
      contents: read

    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@v4

      - 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"
          # Arbitrary password for a keychain that exists only for the duration of the job, so not secret
          KEYCHAIN_PASSWORD: keychainpassword
        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/Bearer/gon/releases/download/v0.0.27/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/Bearer/gon#configuration-file
          source = ["${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/${{ env.PROJECT_NAME }}"]
          bundle_id = "cc.arduino.${{ env.PROJECT_NAME }}"

          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 }}
          AC_PROVIDER: ${{ secrets.AC_PROVIDER }}
        run: |
          gon "${{ env.GON_CONFIG_PATH }}"

      - name: Re-package binary
        id: re-package
        working-directory: ${{ env.DIST_DIR }}
        # Repackage the signed binary replaced in place by Gon (ignoring the output zip file)
        run: |
          # GitHub's upload/download-artifact actions don't preserve file permissions,
          # so we need to add execution permission back until the action is made to do this.
          PLATFORM_DIR="${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}"
          chmod +x "${PLATFORM_DIR}/${{ env.PROJECT_NAME }}"
          TAG="${GITHUB_REF/refs\/tags\//}"
          PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${TAG}_${{ matrix.artifact.path }}"
          tar -czvf "$PACKAGE_FILENAME" "${PLATFORM_DIR}"
          echo "PACKAGE_FILENAME=$PACKAGE_FILENAME" >> $GITHUB_ENV

      - name: Upload artifact
        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
    permissions:
      contents: write

    steps:
      - name: Checkout # we need package_index.template
        uses: actions/checkout@v4

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

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

      - name: Build
        # This must be done after OS X notarization or the wrong checksum
        # would be calculated since the binary is modified during notarization
        run: task dist:generate-index-data

      - name: Create checksum file
        working-directory: ${{ env.DIST_DIR}}
        run: |
          TAG="${GITHUB_REF/refs\/tags\//}"
          sha256sum ${{ env.PROJECT_NAME }}_${TAG}* > ${TAG}-checksums.txt

      - 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.2.0.zip
          unzip -p /tmp/3.2.0.zip semver-tool-3.2.0/src/semver >/tmp/semver && chmod +x /tmp/semver
          if [[ \
            "$(
              /tmp/semver get prerel \
                "${GITHUB_REF/refs\/tags\//}"
            )" != \
            "" \
          ]]; then
            echo "IS_PRE=true" >> $GITHUB_OUTPUT
          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 }}
