Skip to content

Commit f269c6c

Browse files
Add release workflow
1 parent a8d4419 commit f269c6c

File tree

3 files changed

+336
-0
lines changed

3 files changed

+336
-0
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
### Motivation
2+
3+
<!-- Why this pull request? -->
4+
5+
### Change description
6+
7+
<!-- What does your code do? -->
8+
9+
### Additional Notes
10+
11+
<!-- Link any useful metadata: Jira task, GitHub issue, ... -->
12+
13+
### Reviewer checklist
14+
15+
- [ ] PR addresses a single concern.
16+
- [ ] PR title and description are properly filled.
17+
- [ ] Changes will be merged in `main`.
18+
- [ ] Changes are covered by tests.
19+
- [ ] Logging is meaningful in case of troubleshooting.
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
name: Release Arduino Flasher tool
2+
3+
on:
4+
push:
5+
tags:
6+
- "*" # Trigger on all tags
7+
8+
env:
9+
GO_VERSION: "1.25.1"
10+
PROJECT_NAME: "arduino-flasher-cli"
11+
GITHUB_TOKEN: ${{ secrets.ARDUINOBOT_TOKEN }}
12+
GITHUB_USERNAME: ArduinoBot
13+
DIST_DIR: build
14+
15+
jobs:
16+
build:
17+
strategy:
18+
matrix:
19+
runon: [ubuntu-24.04]
20+
os: [linux, darwin]
21+
arch: [amd64, arm64]
22+
include:
23+
- runon: windows-2025
24+
os: windows
25+
arch: amd64
26+
runs-on: ${{ matrix.runon }}
27+
outputs:
28+
release: ${{ steps.set-version.outputs.RELEASE_NAME }}
29+
defaults:
30+
run:
31+
shell: bash
32+
steps:
33+
- name: Extract version
34+
run: |
35+
TAG_NAME="${GITHUB_REF##*/}"
36+
VERSION="${TAG_NAME#flasher-}" # Remove 'flasher-' prefix
37+
echo "VERSION=${VERSION}" >> $GITHUB_ENV
38+
echo "RELEASE_NAME=${{ env.PROJECT_NAME }}-${VERSION}-${{ matrix.os }}-${{ matrix.arch }}" >> $GITHUB_ENV
39+
env:
40+
GITHUB_REF: ${{ github.ref }}
41+
42+
- name: Set Windows version
43+
id: set-version
44+
run: |
45+
echo "RELEASE_NAME=${{ env.RELEASE_NAME }}" >> $GITHUB_OUTPUT
46+
if: matrix.os == 'windows'
47+
48+
- name: Checkout
49+
uses: actions/checkout@v4
50+
with:
51+
fetch-depth: 0
52+
53+
- name: Set up Go
54+
uses: actions/setup-go@v5
55+
with:
56+
go-version: ${{ env.GO_VERSION }}
57+
58+
- name: Install Taskfile
59+
uses: arduino/setup-task@v2
60+
with:
61+
version: "3.x"
62+
repo-token: ${{ secrets.GITHUB_TOKEN }}
63+
64+
- name: Configure Git for private repo cloning
65+
run: |
66+
git config --global url."https://${{ env.GITHUB_USERNAME }}:${{ env.GITHUB_TOKEN }}@github.com".insteadOf "https://github.com"
67+
68+
- name: Build Binary
69+
run: |
70+
task arduino-flasher-cli:build
71+
env:
72+
GOARCH: ${{ matrix.arch }}
73+
GOOS: ${{ matrix.os }}
74+
75+
- name: Prepare Build Artifacts (!windows)
76+
working-directory: ./${{ env.DIST_DIR }}
77+
run: tar -czf ${{ env.RELEASE_NAME }}.tar.gz arduino-flasher-cli -C ../arduino-flasher-cli LICENSE
78+
if: matrix.os != 'windows'
79+
- name: Prepare Build Artifacts (windows)
80+
working-directory: ./${{ env.DIST_DIR }}
81+
run: 7z a -tzip ${{ env.RELEASE_NAME }}.zip arduino-flasher-cli.exe ../arduino-flasher-cli/LICENSE
82+
if: matrix.os == 'windows'
83+
84+
- name: Upload artifacts
85+
uses: actions/upload-artifact@v4
86+
with:
87+
name: ${{ env.PROJECT_NAME }}-${{ matrix.os }}-${{ matrix.arch }}
88+
path: |
89+
${{ env.DIST_DIR }}/${{ env.RELEASE_NAME }}.tar.gz
90+
${{ env.DIST_DIR }}/${{ env.RELEASE_NAME }}.zip
91+
if-no-files-found: error
92+
93+
sign-windows-executable:
94+
runs-on: windows-sign-pc
95+
needs: build
96+
97+
defaults:
98+
run:
99+
shell: bash
100+
101+
env:
102+
RELEASE_NAME: ${{ needs.build.outputs.release }}
103+
INSTALLER_CERT_WINDOWS_CER: "/tmp/cert.cer"
104+
# We are hardcoding the path for signtool because is not present on the windows PATH env var by default.
105+
# Keep in mind that this path could change when upgrading to a new runner version
106+
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0/x86/signtool.exe"
107+
SEVENZ_PATH: "C:/ProgramData/chocolatey/tools/7z.exe"
108+
109+
steps:
110+
- name: Download artifacts
111+
uses: actions/download-artifact@v5
112+
with:
113+
name: ${{ env.PROJECT_NAME }}-windows-amd64
114+
115+
- name: Save Win signing certificate to file
116+
run: echo "${{ secrets.INSTALLER_CERT_WINDOWS_CER }}" | base64 --decode > ${{ env.INSTALLER_CERT_WINDOWS_CER}}
117+
118+
- name: Extract build
119+
run: |
120+
${{ env.SEVENZ_PATH }} x ${{ env.RELEASE_NAME }}.zip -aoa
121+
rm ${{ env.RELEASE_NAME }}.zip
122+
123+
- name: Sign executable
124+
env:
125+
CERT_PASSWORD: ${{ secrets.INSTALLER_CERT_WINDOWS_PASSWORD }}
126+
CONTAINER_NAME: ${{ secrets.INSTALLER_CERT_WINDOWS_CONTAINER }}
127+
# https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing-with-safenet-etoken
128+
run: |
129+
"${{ 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"
130+
131+
- name: Prepare Build Artifacts
132+
run: |
133+
${{ env.SEVENZ_PATH }} a -tzip ${{ env.RELEASE_NAME }}.zip arduino-flasher-cli.exe LICENSE
134+
135+
- name: Upload artifacts
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: ${{ env.PROJECT_NAME }}-windows-amd64
139+
path: ${{ env.RELEASE_NAME }}.zip
140+
if-no-files-found: error
141+
overwrite: true
142+
143+
# This step is needed because the self hosted runner does not delete files automatically
144+
- name: Cleanup
145+
run: rm ${{ env.RELEASE_NAME }}.zip LICENSE arduino-flasher-cli.exe
146+
147+
notarize-macos:
148+
name: Notarize macOS
149+
runs-on: macos-15
150+
needs: build
151+
permissions:
152+
contents: read
153+
154+
env:
155+
GON_CONFIG_PATH: gon.config.hcl
156+
157+
strategy:
158+
matrix:
159+
build: [darwin-amd64, darwin-arm64]
160+
steps:
161+
- name: Set environment variables
162+
run: |
163+
TAG_NAME="${GITHUB_REF##*/}"
164+
VERSION="${TAG_NAME#flasher-}"
165+
echo "PACKAGE_FILENAME=${{ env.PROJECT_NAME }}-${VERSION}-${{ matrix.build }}.tar.gz" >>$GITHUB_ENV
166+
167+
- name: Checkout repository
168+
uses: actions/checkout@v5
169+
170+
- name: Download artifacts
171+
uses: actions/download-artifact@v5
172+
with:
173+
name: ${{ env.PROJECT_NAME }}-${{ matrix.build }}
174+
path: ${{ env.DIST_DIR }}
175+
176+
- name: Extract build
177+
working-directory: ${{ env.DIST_DIR }}
178+
run: |
179+
tar -xvf ${{ env.PACKAGE_FILENAME }}
180+
181+
- name: Import Code-Signing Certificates
182+
env:
183+
KEYCHAIN: "sign.keychain"
184+
INSTALLER_CERT_MAC_PATH: "/tmp/ArduinoCerts2020.p12"
185+
# Arbitrary password for a keychain that exists only for the duration of the job, so not secret
186+
KEYCHAIN_PASSWORD: keychainpassword
187+
run: |
188+
echo "${{ secrets.INSTALLER_CERT_MAC_P12 }}" | base64 --decode >"${{ env.INSTALLER_CERT_MAC_PATH }}"
189+
190+
security create-keychain \
191+
-p "${{ env.KEYCHAIN_PASSWORD }}" \
192+
"${{ env.KEYCHAIN }}"
193+
194+
security default-keychain \
195+
-s "${{ env.KEYCHAIN }}"
196+
197+
security unlock-keychain \
198+
-p "${{ env.KEYCHAIN_PASSWORD }}" \
199+
"${{ env.KEYCHAIN }}"
200+
201+
security import \
202+
"${{ env.INSTALLER_CERT_MAC_PATH }}" \
203+
-k "${{ env.KEYCHAIN }}" \
204+
-f pkcs12 \
205+
-A \
206+
-T "/usr/bin/codesign" \
207+
-P "${{ secrets.INSTALLER_CERT_MAC_PASSWORD }}"
208+
209+
security set-key-partition-list \
210+
-S apple-tool:,apple: \
211+
-s \
212+
-k "${{ env.KEYCHAIN_PASSWORD }}" \
213+
"${{ env.KEYCHAIN }}"
214+
215+
- name: Install gon for code signing and app notarization
216+
run: |
217+
wget \
218+
-q https://github.com/Bearer/gon/releases/download/v0.0.27/gon_macos.zip
219+
220+
unzip \
221+
gon_macos.zip \
222+
-d /usr/local/bin
223+
224+
- name: Write gon config to file
225+
# gon does not allow env variables in config file (https://github.com/mitchellh/gon/issues/20)
226+
run: |
227+
cat >"${{ env.GON_CONFIG_PATH }}" \
228+
<<EOF
229+
# See: https://github.com/Bearer/gon#configuration-file
230+
source = ["${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}"]
231+
bundle_id = "cc.arduino.${{ env.PROJECT_NAME }}"
232+
233+
sign {
234+
application_identity = "Developer ID Application: ARDUINO SA (7KT7ZWMCJT)"
235+
}
236+
237+
# Ask Gon for zip output to force notarization process to take place.
238+
# The CI will ignore the zip output, using the signed binary only.
239+
zip {
240+
output_path = "unused.zip"
241+
}
242+
EOF
243+
244+
- name: Sign and notarize binary
245+
env:
246+
AC_USERNAME: ${{ secrets.AC_USERNAME }}
247+
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
248+
AC_PROVIDER: ${{ secrets.AC_PROVIDER }}
249+
run: |
250+
gon "${{ env.GON_CONFIG_PATH }}"
251+
252+
- name: Re-package binary
253+
working-directory: ${{ env.DIST_DIR }}
254+
# Repackage the signed binary replaced in place by Gon (ignoring the output zip file)
255+
run: |
256+
# GitHub's upload/download-artifact actions don't preserve file permissions,
257+
# so we need to add execution permission back until the action is made to do this.
258+
chmod \
259+
+x \
260+
"${{ env.PROJECT_NAME }}"
261+
262+
tar -czf ${{ env.PACKAGE_FILENAME }} ${{ env.PROJECT_NAME }} LICENSE
263+
264+
- name: Replace artifact with notarized build
265+
uses: actions/upload-artifact@v4
266+
with:
267+
if-no-files-found: error
268+
name: ${{ env.PROJECT_NAME }}-${{ matrix.build }}
269+
overwrite: true
270+
path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }}
271+
272+
create-release:
273+
runs-on: ubuntu-24.04
274+
needs: [build, sign-windows-executable, notarize-macos]
275+
steps:
276+
- name: Checkout
277+
uses: actions/checkout@v4
278+
with:
279+
fetch-depth: 0 # fetch all history for the create changelog step to work properly
280+
281+
- name: Download artifact
282+
uses: actions/download-artifact@v5
283+
with:
284+
merge-multiple: true
285+
path: ${{ env.DIST_DIR }}
286+
287+
- name: Upload artifacts index
288+
uses: ncipollo/release-action@v1
289+
with:
290+
token: ${{ secrets.GITHUB_TOKEN }}
291+
draft: false
292+
prerelease: true
293+
artifacts: ${{ env.DIST_DIR }}/*

Taskfile.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
version: "3"
2+
3+
vars:
4+
VERSION: # if version is not passed we hack the semver by encoding the commit as pre-release
5+
sh: echo "${VERSION:-0.0.0-$(git rev-parse --short HEAD)}"
6+
7+
tasks:
8+
arduino-flasher-cli:build:
9+
deps:
10+
- arduino-flasher-cli:artifacts
11+
desc: "Build the arduino-flasher-cli locally"
12+
dir: arduino-flasher-cli
13+
vars:
14+
VERSION: "{{.VERSION }}"
15+
cmds:
16+
- cmd: go build -ldflags "-X main.Version={{.VERSION}}" -v -o ../build/arduino-flasher-cli .
17+
platforms: [linux, darwin]
18+
- cmd: go build -ldflags "-X main.Version={{.VERSION}}" -v -o ../build/arduino-flasher-cli.exe .
19+
platforms: [windows]
20+
21+
arduino-flasher-cli:artifacts:
22+
desc: Prepare the arduino-flasher-cli artifacts
23+
internal: true
24+
cmd: sh ./arduino-flasher-cli/updater/artifacts/download_resources.sh

0 commit comments

Comments
 (0)