Skip to content

Commit 4eeba93

Browse files
authored
Add notarization step in the CI (#11)
* remove version number from release folder created, we'll need to hard-code the path_name in `gon.config.hcl` file later for notarization * add notarization step * pin pyinstaller version used * add entitlements file (required for pyinstaller binary notarization) https://developer.apple.com/forums/thread/695989 pyinstaller/pyinstaller#4629 * Improve maintainability of the workflow * pin pyinstaller in `build-crosscompile` step the same version that is in the workflow
1 parent 0b5af34 commit 4eeba93

File tree

4 files changed

+124
-18
lines changed

4 files changed

+124
-18
lines changed

.github/workflows/release.yml

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ env:
1212
MCUBOOT_PATH: ${{ github.workspace }}/mcuboot
1313
IMGTOOL_PACKING_PATH: ${{ github.workspace }}/imgtool-packing
1414

15-
1615
on:
1716
push:
1817
tags:
@@ -74,29 +73,35 @@ jobs:
7473
run: pip install -r requirements.txt
7574

7675
- name: Install pyinstaller
77-
run: pip install pyinstaller
76+
run: pip install pyinstaller==5.0.1
7877

7978
- name: Build
79+
if: runner.os != 'macOS'
8080
working-directory: ${{ env.MCUBOOT_PATH }}/scripts/
8181
run: pyinstaller --onefile main.py -n ${{ env.PROJECT_NAME }}
8282

83+
- name: Build macOS
84+
if: runner.os == 'macOS'
85+
working-directory: ${{ env.MCUBOOT_PATH }}/scripts/
86+
run: pyinstaller --osx-entitlements-file ${{ env.IMGTOOL_PACKING_PATH }}/entitlements.plist --onefile main.py -n ${{ env.PROJECT_NAME }}
87+
8388
- name: Package
84-
if: matrix.os == 'windows-latest'
89+
if: runner.os == 'Windows'
8590
working-directory: ${{ env.MCUBOOT_PATH }}/scripts/${{ env.DIST_DIR }}
8691
run: | # we need to create the subdir where to place binaries
87-
mkdir ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
88-
mv -v ./${{ env.PROJECT_NAME }}.exe ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
89-
mv -v "${{ env.IMGTOOL_PACKING_PATH }}/LICENSE.txt" ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
90-
7z a ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}.zip ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
92+
mkdir ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
93+
mv -v ./${{ env.PROJECT_NAME }}.exe ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
94+
mv -v "${{ env.IMGTOOL_PACKING_PATH }}/LICENSE.txt" ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
95+
7z a ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}.zip ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
9196
9297
- name: Package
93-
if: matrix.os != 'windows-latest'
98+
if: runner.os != 'Windows'
9499
working-directory: ${{ env.MCUBOOT_PATH }}/scripts/${{ env.DIST_DIR }}
95100
run: | # we need to create the subdir where to place binaries
96-
mkdir ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
97-
mv -v ./${{ env.PROJECT_NAME }} ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
98-
mv -v ${{ env.IMGTOOL_PACKING_PATH }}/LICENSE.txt ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
99-
${{ matrix.archive_util }} -cz ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }} -f ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}.tar.gz
101+
mkdir ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
102+
mv -v ./${{ env.PROJECT_NAME }} ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
103+
mv -v ${{ env.IMGTOOL_PACKING_PATH }}/LICENSE.txt ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
104+
${{ matrix.archive_util }} -cz ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }} -f ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}.tar.gz
100105
101106
- name: Upload artifacts
102107
uses: actions/upload-artifact@v3
@@ -161,10 +166,10 @@ jobs:
161166
- name: Package
162167
working-directory: ${{ env.MCUBOOT_PATH }}/scripts/${{ env.DIST_DIR }}
163168
run: | # we need to create the subdir where to place binaries
164-
sudo mkdir ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
165-
sudo mv -v ./${{ env.PROJECT_NAME }} ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
166-
sudo mv -v ${{ env.IMGTOOL_PACKING_PATH }}/LICENSE.txt ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}
167-
sudo tar -cz ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }} -f ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}.tar.gz #dist dir is created in the container with different user/grp
169+
sudo mkdir ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
170+
sudo mv -v ./${{ env.PROJECT_NAME }} ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
171+
sudo mv -v ${{ env.IMGTOOL_PACKING_PATH }}/LICENSE.txt ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }}
172+
sudo tar -cz ${{ env.PROJECT_NAME }}_${{ matrix.package_platform }} -f ${{ env.PROJECT_NAME }}_${GITHUB_REF/refs\/tags\//}_${{ matrix.package_platform }}.tar.gz #dist dir is created in the container with different user/grp
168173
169174
- name: Upload artifacts
170175
uses: actions/upload-artifact@v3
@@ -173,9 +178,77 @@ jobs:
173178
name: ${{ env.ARTIFACT_NAME }}
174179
path: ${{ env.MCUBOOT_PATH }}/scripts/dist/${{ env.PROJECT_NAME }}_*
175180

181+
notarize-macos:
182+
runs-on: macos-latest
183+
needs: build
184+
185+
steps:
186+
- name: Checkout repository
187+
uses: actions/checkout@v3
188+
189+
- name: Download artifacts
190+
uses: actions/download-artifact@v3
191+
with:
192+
name: ${{ env.ARTIFACT_NAME }}
193+
path: ${{ env.DIST_DIR }}
194+
195+
- name: Import Code-Signing Certificates
196+
env:
197+
KEYCHAIN: "sign.keychain"
198+
INSTALLER_CERT_MAC_PATH: "/tmp/ArduinoCerts2020.p12"
199+
KEYCHAIN_PASSWORD: keychainpassword # Arbitrary password for a keychain that exists only for the duration of the job, so not secret
200+
run: |
201+
echo "${{ secrets.INSTALLER_CERT_MAC_P12 }}" | base64 --decode > "${{ env.INSTALLER_CERT_MAC_PATH }}"
202+
security create-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}"
203+
security default-keychain -s "${{ env.KEYCHAIN }}"
204+
security unlock-keychain -p "${{ env.KEYCHAIN_PASSWORD }}" "${{ env.KEYCHAIN }}"
205+
security import \
206+
"${{ env.INSTALLER_CERT_MAC_PATH }}" \
207+
-k "${{ env.KEYCHAIN }}" \
208+
-f pkcs12 \
209+
-A \
210+
-T "/usr/bin/codesign" \
211+
-P "${{ secrets.INSTALLER_CERT_MAC_PASSWORD }}"
212+
security set-key-partition-list \
213+
-S apple-tool:,apple: \
214+
-s \
215+
-k "${{ env.KEYCHAIN_PASSWORD }}" \
216+
"${{ env.KEYCHAIN }}"
217+
218+
- name: Install gon for code signing and app notarization
219+
run: |
220+
wget -q https://github.com/mitchellh/gon/releases/download/v0.2.3/gon_macos.zip
221+
unzip gon_macos.zip -d /usr/local/bin
222+
223+
- name: Sign and notarize binary
224+
env:
225+
AC_USERNAME: ${{ secrets.AC_USERNAME }}
226+
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
227+
run: |
228+
gon gon.config.hcl
229+
230+
- name: Re-package binary
231+
# This step performs the following:
232+
# 1. Repackage the signed binary replaced in place by Gon (ignoring the output zip file)
233+
run: |
234+
# GitHub's upload/download-artifact@v2 actions don't preserve file permissions,
235+
# so we need to add execution permission back until the action is made to do this.
236+
chmod +x ${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_macOS_64bit/${{ env.PROJECT_NAME }}
237+
TAG="${GITHUB_REF/refs\/tags\//}"
238+
tar -czvf "${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_${TAG}_macOS_64bit.tar.gz" \
239+
-C ${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_macOS_64bit/ ${{ env.PROJECT_NAME }} \
240+
LICENSE.txt
241+
242+
- name: Upload artifacts
243+
uses: actions/upload-artifact@v3
244+
with:
245+
if-no-files-found: error
246+
name: ${{ env.ARTIFACT_NAME }}
247+
path: ${{ env.DIST_DIR }}
248+
176249
create-release:
177250
runs-on: ubuntu-latest
178-
needs: [build, build-crosscompile]
251+
needs: [build, build-crosscompile, notarize-macos]
179252

180253
steps:
181254
- name: Download artifact

build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ apt-get install -y upx
55
python -m pip install --upgrade pip setuptools wheel
66
cd workspace/
77
pip install -r requirements.txt
8-
pip install pyinstaller==4.2
8+
pip install pyinstaller==5.0.1
99
echo "
1010
---
1111
Available PyInstaller bootloaders:"

entitlements.plist

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<!--
5+
These are required for binaries built by PyInstaller.
6+
For more info, see:
7+
https://developer.apple.com/documentation/security/hardened_runtime
8+
https://github.com/pyinstaller/pyinstaller/issues/4629
9+
-->
10+
<dict>
11+
<key>com.apple.security.cs.allow-jit</key>
12+
<true/>
13+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
14+
<true/>
15+
<key>com.apple.security.cs.disable-library-validation</key>
16+
<true/>
17+
</dict>
18+
</plist>

gon.config.hcl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/general/gon.config.hcl
2+
# See: https://github.com/mitchellh/gon#configuration-file
3+
source = ["dist/imgtool_macOS_64bit/imgtool"]
4+
bundle_id = "cc.arduino.imgtool"
5+
6+
sign {
7+
application_identity = "Developer ID Application: ARDUINO SA (7KT7ZWMCJT)"
8+
entitlements_file = "entitlements.plist"
9+
}
10+
11+
# Ask Gon for zip output to force notarization process to take place.
12+
# The CI will ignore the zip output, using the signed binary only.
13+
zip {
14+
output_path = "unused.zip"
15+
}

0 commit comments

Comments
 (0)