Skip to content

Commit 7490907

Browse files
Add CI workflow to publish releases
On every push of a tag named with a version format: - Build the project for all supported platforms. - Sign and notarize the macOS builds. - Create a GitHub release. - Builds and checksums are attached as release assets - A changelog generated from the commit history is added to the release description - If the tag has a pre-release version suffix, the GitHub release will be marked as a pre-release. - Upload the builds to Arduino's downloads server.
1 parent 6d584ad commit 7490907

File tree

4 files changed

+427
-0
lines changed

4 files changed

+427
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/release-go-crosscompile-task.md
2+
name: Release
3+
4+
env:
5+
# As defined by the Taskfile's PROJECT_NAME variable
6+
PROJECT_NAME: arduinoOTA
7+
# As defined by the Taskfile's DIST_DIR variable
8+
DIST_DIR: dist
9+
# The project's folder on Arduino's download server for uploading builds
10+
AWS_PLUGIN_TARGET: /arduinoOTA/
11+
ARTIFACT_NAME: dist
12+
# See: https://github.com/actions/setup-go/tree/main#supported-version-syntax
13+
GO_VERSION: "1.17"
14+
15+
on:
16+
push:
17+
tags:
18+
- "[0-9]+.[0-9]+.[0-9]+*"
19+
20+
jobs:
21+
create-release-artifacts:
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- name: Checkout repository
26+
uses: actions/checkout@v3
27+
with:
28+
fetch-depth: 0
29+
30+
- name: Create changelog
31+
uses: arduino/create-changelog@v1
32+
with:
33+
tag-regex: '^[0-9]+\.[0-9]+\.[0-9]+.*$'
34+
filter-regex: '^\[(skip|changelog)[ ,-](skip|changelog)\].*'
35+
case-insensitive-regex: true
36+
changelog-file-path: "${{ env.DIST_DIR }}/CHANGELOG.md"
37+
38+
- name: Install Go
39+
uses: actions/setup-go@v3
40+
with:
41+
go-version: ${{ env.GO_VERSION }}
42+
43+
- name: Install Task
44+
uses: arduino/setup-task@v1
45+
with:
46+
repo-token: ${{ secrets.GITHUB_TOKEN }}
47+
version: 3.x
48+
49+
- name: Build
50+
run: task dist:all
51+
52+
- name: Upload artifacts
53+
uses: actions/upload-artifact@v3
54+
with:
55+
if-no-files-found: error
56+
name: ${{ env.ARTIFACT_NAME }}
57+
path: ${{ env.DIST_DIR }}
58+
59+
notarize-macos:
60+
name: Notarize ${{ matrix.artifact.name }}
61+
runs-on: macos-latest
62+
needs: create-release-artifacts
63+
outputs:
64+
checksum-darwin_amd64: ${{ steps.re-package.outputs.checksum-darwin_amd64 }}
65+
checksum-darwin_arm64: ${{ steps.re-package.outputs.checksum-darwin_arm64 }}
66+
67+
env:
68+
GON_CONFIG_PATH: gon.config.hcl
69+
70+
strategy:
71+
matrix:
72+
artifact:
73+
- name: darwin_amd64
74+
path: "macOS_64bit.tar.gz"
75+
- name: darwin_arm64
76+
path: "macOS_ARM64.tar.gz"
77+
78+
steps:
79+
- name: Checkout repository
80+
uses: actions/checkout@v3
81+
82+
- name: Download artifacts
83+
uses: actions/download-artifact@v3
84+
with:
85+
name: ${{ env.ARTIFACT_NAME }}
86+
path: ${{ env.DIST_DIR }}
87+
88+
- name: Import Code-Signing Certificates
89+
env:
90+
KEYCHAIN: "sign.keychain"
91+
INSTALLER_CERT_MAC_PATH: "/tmp/ArduinoCerts2020.p12"
92+
KEYCHAIN_PASSWORD: keychainpassword # Arbitrary password for a keychain that exists only for the duration of the job, so not secret
93+
run: |
94+
echo "${{ secrets.INSTALLER_CERT_MAC_P12 }}" | base64 --decode > "${{ env.INSTALLER_CERT_MAC_PATH }}"
95+
security create-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}"
96+
security default-keychain -s "${{ env.KEYCHAIN }}"
97+
security unlock-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}"
98+
security import \
99+
"${{ env.INSTALLER_CERT_MAC_PATH }}" \
100+
-k "${{ env.KEYCHAIN }}" \
101+
-f pkcs12 \
102+
-A \
103+
-T "/usr/bin/codesign" \
104+
-P "${{ secrets.INSTALLER_CERT_MAC_PASSWORD }}"
105+
security set-key-partition-list \
106+
-S apple-tool:,apple: \
107+
-s \
108+
-k "${{ env.KEYCHAIN_PASSWORD }}" \
109+
"${{ env.KEYCHAIN }}"
110+
111+
- name: Install gon for code signing and app notarization
112+
run: |
113+
wget -q https://github.com/mitchellh/gon/releases/download/v0.2.3/gon_macos.zip
114+
unzip gon_macos.zip -d /usr/local/bin
115+
116+
- name: Write gon config to file
117+
# gon does not allow env variables in config file (https://github.com/mitchellh/gon/issues/20)
118+
run: |
119+
cat > "${{ env.GON_CONFIG_PATH }}" <<EOF
120+
# See: https://github.com/mitchellh/gon#configuration-file
121+
source = ["${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/${{ env.PROJECT_NAME }}"]
122+
bundle_id = "cc.arduino.${{ env.PROJECT_NAME }}"
123+
124+
sign {
125+
application_identity = "Developer ID Application: ARDUINO SA (7KT7ZWMCJT)"
126+
}
127+
128+
# Ask Gon for zip output to force notarization process to take place.
129+
# The CI will ignore the zip output, using the signed binary only.
130+
zip {
131+
output_path = "unused.zip"
132+
}
133+
EOF
134+
135+
- name: Sign and notarize binary
136+
env:
137+
AC_USERNAME: ${{ secrets.AC_USERNAME }}
138+
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
139+
run: |
140+
gon "${{ env.GON_CONFIG_PATH }}"
141+
142+
- name: Re-package binary and output checksum
143+
id: re-package
144+
working-directory: ${{ env.DIST_DIR }}
145+
# This step performs the following:
146+
# 1. Repackage the signed binary replaced in place by Gon (ignoring the output zip file)
147+
# 2. Recalculate package checksum
148+
# 3. Output the new checksum to include in the nnnnnn-checksums.txt file
149+
# (it cannot be done there because of workflow job parallelization)
150+
run: |
151+
# GitHub's upload/download-artifact actions don't preserve file permissions,
152+
# so we need to add execution permission back until the action is made to do this.
153+
chmod +x "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/${{ env.PROJECT_NAME }}"
154+
TAG="${GITHUB_REF/refs\/tags\//}"
155+
PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${TAG}_${{ matrix.artifact.path }}"
156+
tar -czvf "$PACKAGE_FILENAME" \
157+
-C "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/" "${{ env.PROJECT_NAME }}" \
158+
-C ../../ LICENSE.txt
159+
CHECKSUM_LINE="$(shasum -a 256 $PACKAGE_FILENAME)"
160+
echo "PACKAGE_FILENAME=$PACKAGE_FILENAME" >> $GITHUB_ENV
161+
echo "checksum-${{ matrix.artifact.name }}=$CHECKSUM_LINE" >> $GITHUB_OUTPUT
162+
163+
- name: Upload artifacts
164+
uses: actions/upload-artifact@v3
165+
with:
166+
if-no-files-found: error
167+
name: ${{ env.ARTIFACT_NAME }}
168+
path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }}
169+
170+
create-release:
171+
runs-on: ubuntu-latest
172+
needs: notarize-macos
173+
174+
steps:
175+
- name: Download artifact
176+
uses: actions/download-artifact@v3
177+
with:
178+
name: ${{ env.ARTIFACT_NAME }}
179+
path: ${{ env.DIST_DIR }}
180+
181+
- name: Update checksum
182+
run: |
183+
declare -a checksum_lines=("${{ needs.notarize-macos.outputs.checksum-darwin_amd64 }}" "${{ needs.notarize-macos.outputs.checksum-darwin_arm64 }}")
184+
for checksum_line in "${checksum_lines[@]}"
185+
do
186+
CHECKSUM=$(echo ${checksum_line} | cut -d " " -f 1)
187+
PACKAGE_FILENAME=$(echo ${checksum_line} | cut -d " " -f 2)
188+
perl -pi -w -e "s/.*${PACKAGE_FILENAME}/${CHECKSUM} ${PACKAGE_FILENAME}/g;" ${{ env.DIST_DIR }}/*-checksums.txt
189+
done
190+
191+
- name: Identify Prerelease
192+
# This is a workaround while waiting for create-release action
193+
# to implement auto pre-release based on tag
194+
id: prerelease
195+
run: |
196+
wget -q -P /tmp https://github.com/fsaintjacques/semver-tool/archive/3.2.0.zip
197+
unzip -p /tmp/3.2.0.zip semver-tool-3.2.0/src/semver >/tmp/semver && chmod +x /tmp/semver
198+
if [[ "$(/tmp/semver get prerel "${GITHUB_REF/refs\/tags\//}")" ]]; then echo "IS_PRE=true" >> $GITHUB_OUTPUT; fi
199+
200+
- name: Create Github Release and upload artifacts
201+
uses: ncipollo/release-action@v1
202+
with:
203+
token: ${{ secrets.GITHUB_TOKEN }}
204+
bodyFile: ${{ env.DIST_DIR }}/CHANGELOG.md
205+
draft: false
206+
prerelease: ${{ steps.prerelease.outputs.IS_PRE }}
207+
# NOTE: "Artifact is a directory" warnings are expected and don't indicate a problem
208+
# (all the files we need are in the DIST_DIR root)
209+
artifacts: ${{ env.DIST_DIR }}/*
210+
211+
- name: Upload release files on Arduino downloads servers
212+
uses: docker://plugins/s3
213+
env:
214+
PLUGIN_SOURCE: "${{ env.DIST_DIR }}/*"
215+
PLUGIN_TARGET: ${{ env.AWS_PLUGIN_TARGET }}
216+
PLUGIN_STRIP_PREFIX: "${{ env.DIST_DIR }}/"
217+
PLUGIN_BUCKET: ${{ secrets.DOWNLOADS_BUCKET }}
218+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
219+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

0 commit comments

Comments
 (0)