Trigger workflow on a semver tag #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Arduino Flasher CLI | |
| on: | |
| push: | |
| tags: | |
| - "[0-9]+.[0-9]+.[0-9]+*" | |
| env: | |
| GO_VERSION: "1.25.1" | |
| PROJECT_NAME: "arduino-flasher-cli" | |
| GITHUB_TOKEN: ${{ secrets.ARDUINOBOT_TOKEN }} | |
| GITHUB_USERNAME: ArduinoBot | |
| DIST_DIR: build | |
| jobs: | |
| build: | |
| strategy: | |
| matrix: | |
| runon: [ubuntu-24.04] | |
| os: [linux, darwin] | |
| arch: [amd64, arm64] | |
| include: | |
| - runon: windows-2025 | |
| os: windows | |
| arch: amd64 | |
| runs-on: ${{ matrix.runon }} | |
| outputs: | |
| release: ${{ steps.set-version.outputs.RELEASE_NAME }} | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Tag version | |
| run: | | |
| echo "VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV | |
| echo "RELEASE_NAME=${{ env.PROJECT_NAME }}-${{ env.VERSION }}-${{ matrix.os }}-${{ matrix.arch }}" >> $GITHUB_ENV | |
| env: | |
| GITHUB_REF: ${{ github.ref }} | |
| - name: Set Windows version | |
| id: set-version | |
| run: | | |
| echo "RELEASE_NAME=${{ env.RELEASE_NAME }}" >> $GITHUB_OUTPUT | |
| if: matrix.os == 'windows' | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install Taskfile | |
| uses: arduino/setup-task@v2 | |
| with: | |
| version: "3.x" | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure Git for private repo cloning | |
| run: | | |
| git config --global url."https://${{ env.GITHUB_USERNAME }}:${{ env.GITHUB_TOKEN }}@github.com".insteadOf "https://github.com" | |
| - name: Build Binary | |
| run: | | |
| task arduino-flasher-cli:build | |
| env: | |
| GOARCH: ${{ matrix.arch }} | |
| GOOS: ${{ matrix.os }} | |
| - name: Prepare Build Artifacts (!windows) | |
| working-directory: ./${{ env.DIST_DIR }} | |
| run: tar -czf ${{ env.RELEASE_NAME }}.tar.gz arduino-flasher-cli -C ../ LICENSE | |
| if: matrix.os != 'windows' | |
| - name: Prepare Build Artifacts (windows) | |
| working-directory: ./${{ env.DIST_DIR }} | |
| run: 7z a -tzip ${{ env.RELEASE_NAME }}.zip arduino-flasher-cli.exe ../LICENSE | |
| if: matrix.os == 'windows' | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.PROJECT_NAME }}-${{ matrix.os }}-${{ matrix.arch }} | |
| path: | | |
| ${{ env.DIST_DIR }}/${{ env.RELEASE_NAME }}.tar.gz | |
| ${{ env.DIST_DIR }}/${{ env.RELEASE_NAME }}.zip | |
| if-no-files-found: error | |
| sign-windows-executable: | |
| runs-on: windows-sign-pc | |
| needs: build | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| RELEASE_NAME: ${{ needs.build.outputs.release }} | |
| INSTALLER_CERT_WINDOWS_CER: "/tmp/cert.cer" | |
| # We are hardcoding the path for signtool because is not present on the windows PATH env var by default. | |
| # Keep in mind that this path could change when upgrading to a new runner version | |
| SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0/x86/signtool.exe" | |
| SEVENZ_PATH: "C:/ProgramData/chocolatey/tools/7z.exe" | |
| steps: | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v5 | |
| with: | |
| name: ${{ env.PROJECT_NAME }}-windows-amd64 | |
| - name: Save Win signing certificate to file | |
| run: echo "${{ secrets.INSTALLER_CERT_WINDOWS_CER }}" | base64 --decode > ${{ env.INSTALLER_CERT_WINDOWS_CER}} | |
| - name: Extract build | |
| run: | | |
| ${{ env.SEVENZ_PATH }} x ${{ env.RELEASE_NAME }}.zip -aoa | |
| rm ${{ env.RELEASE_NAME }}.zip | |
| - name: Sign executable | |
| env: | |
| CERT_PASSWORD: ${{ secrets.INSTALLER_CERT_WINDOWS_PASSWORD }} | |
| CONTAINER_NAME: ${{ secrets.INSTALLER_CERT_WINDOWS_CONTAINER }} | |
| # https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing-with-safenet-etoken | |
| run: | | |
| "${{ env.SIGNTOOL_PATH }}" sign -d "Arduino Flasher CLI" -f ${{ env.INSTALLER_CERT_WINDOWS_CER}} -csp "eToken Base Cryptographic Provider" -k "[{{${{ env.CERT_PASSWORD }}}}]=${{ env.CONTAINER_NAME }}" -fd sha256 -tr http://timestamp.digicert.com -td SHA256 -v "arduino-flasher-cli.exe" | |
| - name: Prepare Build Artifacts | |
| run: | | |
| ${{ env.SEVENZ_PATH }} a -tzip ${{ env.RELEASE_NAME }}.zip arduino-flasher-cli.exe LICENSE | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.PROJECT_NAME }}-windows-amd64 | |
| path: ${{ env.RELEASE_NAME }}.zip | |
| if-no-files-found: error | |
| overwrite: true | |
| # This step is needed because the self hosted runner does not delete files automatically | |
| - name: Cleanup | |
| run: rm ${{ env.RELEASE_NAME }}.zip LICENSE arduino-flasher-cli.exe | |
| notarize-macos: | |
| name: Notarize macOS | |
| runs-on: macos-15 | |
| needs: build | |
| permissions: | |
| contents: read | |
| env: | |
| GON_CONFIG_PATH: gon.config.hcl | |
| strategy: | |
| matrix: | |
| build: [darwin-amd64, darwin-arm64] | |
| steps: | |
| - name: Set environment variables | |
| run: | | |
| VERSION="${GITHUB_REF##*/}" | |
| echo "PACKAGE_FILENAME=${{ env.PROJECT_NAME }}-${VERSION}-${{ matrix.build }}.tar.gz" >>$GITHUB_ENV | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v5 | |
| with: | |
| name: ${{ env.PROJECT_NAME }}-${{ matrix.build }} | |
| path: ${{ env.DIST_DIR }} | |
| - name: Extract build | |
| working-directory: ${{ env.DIST_DIR }} | |
| run: | | |
| tar -xvf ${{ env.PACKAGE_FILENAME }} | |
| - 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 }}"] | |
| 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 | |
| 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. | |
| chmod \ | |
| +x \ | |
| "${{ env.PROJECT_NAME }}" | |
| tar -czf ${{ env.PACKAGE_FILENAME }} ${{ env.PROJECT_NAME }} LICENSE | |
| - name: Replace artifact with notarized build | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| if-no-files-found: error | |
| name: ${{ env.PROJECT_NAME }}-${{ matrix.build }} | |
| overwrite: true | |
| path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }} | |
| create-release: | |
| runs-on: ubuntu-24.04 | |
| needs: [build, sign-windows-executable, notarize-macos] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # fetch all history for the create changelog step to work properly | |
| - name: Download artifact | |
| uses: actions/download-artifact@v5 | |
| with: | |
| merge-multiple: true | |
| path: ${{ env.DIST_DIR }} | |
| - name: Upload artifacts index | |
| uses: ncipollo/release-action@v1 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| draft: false | |
| prerelease: true | |
| artifacts: ${{ env.DIST_DIR }}/* |