Skip to content

Trigger workflow on a semver tag #3

Trigger workflow on a semver tag

Trigger workflow on a semver tag #3

Workflow file for this run

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 }}/*