Skip to content

Commit 3207aa1

Browse files
MatteoPologrutolucarin91dido18
authored
Add workflow to publish releases (#1)
* Add release workflow * Update Taskfile and .gitignore * Fix some leftovers * Trigger workflow on a semver tag * Fix version in release name * Update Taskfile.yml Co-authored-by: Luca Rinaldi <lucarin@protonmail.com> * Update Taskfile.yml Co-authored-by: Davide <davideneri18@gmail.com> * Update Taskfile.yml Co-authored-by: Davide <davideneri18@gmail.com> * Update .github/workflows/release.yml Co-authored-by: Luca Rinaldi <lucarin@protonmail.com> * Remove authentication step * Update task name in workflow * Set GH_TOKEN to use gh cli in workflow * Try with another token --------- Co-authored-by: Luca Rinaldi <lucarin@protonmail.com> Co-authored-by: Davide <davideneri18@gmail.com>
1 parent 8f86284 commit 3207aa1

File tree

4 files changed

+334
-1
lines changed

4 files changed

+334
-1
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.

.github/workflows/release.yml

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

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
public/
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
5+
build/

Taskfile.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
build:
9+
deps:
10+
- artifacts
11+
desc: "Build the arduino-flasher-cli locally"
12+
vars:
13+
VERSION: "{{.VERSION }}"
14+
cmds:
15+
- cmd: go build -ldflags "-X main.Version={{.VERSION}}" -v -o ./build/arduino-flasher-cli .
16+
platforms: [linux, darwin]
17+
- cmd: go build -ldflags "-X main.Version={{.VERSION}}" -v -o ./build/arduino-flasher-cli.exe .
18+
platforms: [windows]
19+
20+
artifacts:
21+
desc: Prepare the arduino-flasher-cli artifacts
22+
internal: true
23+
cmd: sh ./updater/artifacts/download_resources.sh

0 commit comments

Comments
 (0)