-
Notifications
You must be signed in to change notification settings - Fork 0
210 lines (199 loc) · 11.5 KB
/
build_binaries.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
name: 🍏 🏁 macOS and Windows Build, Bundle, and Publish
on:
push:
branches:
- main
- 'cicd/**'
jobs:
build_macos:
runs-on: macos-latest
outputs:
zip_filename: ${{ steps.create_zip_filename.outputs.zip_filename }}
steps:
- name: Get repository name
id: get_repo_name
run: echo "repo_name=$(basename $GITHUB_REPOSITORY)" >> "$GITHUB_OUTPUT"
- name: Checkout code
uses: actions/checkout@v4
with:
# Fetch all history for all tags and branches instead of `1`, which fetches only the current branch.
fetch-depth: 0
# Include icon images.
lfs: true
- name: Install Rust toolchain with M1 chip support
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: aarch64-apple-darwin, x86_64-apple-darwin
- name: Set up Rust Build Caching
uses: Swatinem/rust-cache@v2
# Build binaries in parallel to speed up build times.
- name: Build x86_64 binary and Apple Silicon binaries
run: cargo build --release --target x86_64-apple-darwin --target aarch64-apple-darwin
# Cargo Bundle can't create universal binaries, so make one with `lipo` and put it where Cargo Bundle expects to find it (`target/release/`).
- name: Create a universal binary from the x86_64 and ARM64 binaries and put it in `target/release/`
run: lipo -create -output target/release/${{ steps.get_repo_name.outputs.repo_name }} -arch x86_64 target/x86_64-apple-darwin/release/${{ steps.get_repo_name.outputs.repo_name }} -arch arm64 target/aarch64-apple-darwin/release/${{ steps.get_repo_name.outputs.repo_name }}
- name: Install `cargo-bundle` for creating `.app` directory structure and `.plist` with `cargo bundle`
uses: baptiste0928/cargo-install@v2
with:
crate: cargo-bundle
# Future: Cargo Bundle will build a universal binary and bundle it into an `*.app`.
- name: Create `*.app` directory structure and `.plist` file
env:
# Skip building binaries because they've already been built and combined.
CARGO_BUNDLE_SKIP_BUILD: "true"
run: cargo bundle --release --format osx
# Move the `*.app` directory to the top level of the repo so it's easier to access for code signing and notarization.
- name: Move bundled `*.app` directory to top level
run: mv target/release/bundle/osx/${{ steps.get_repo_name.outputs.repo_name }}.app .
- name: Codesign app bundle
env:
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
run: |
# Convert base64-encoded certificate back to .p12 file.
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
# Create a new keychain so no UI dialogs are generated.
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
# Codesign the app bundle with hardened runtime so it passes notarization.
/usr/bin/codesign --force -s "$MACOS_CERTIFICATE_NAME" --options runtime ${{ steps.get_repo_name.outputs.repo_name }}.app -v
- name: "Notarize app bundle"
env:
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
run: |
# Prevent UI password dialog by storing notarization credentials.
echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
# We can't notarize an app bundle directly, but we need to compress it as an archive.
# Compress app bundle to zip file for notarization (because we can't notarize app bundles directly).
echo "Creating temporary notarization archive"
ditto -c -k --keepParent "${{ steps.get_repo_name.outputs.repo_name }}.app" "notarization.zip"
# Send the notarization request to the Apple's Notarization service.
echo "Notarizing compressed app bundle"
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
# "Attach the staple" to executable for offline MacOS validation.
echo "Attach staple"
xcrun stapler staple "${{ steps.get_repo_name.outputs.repo_name }}.app"
# Get the current SemVer from Cargo.toml. Ex. 2.0.3 would make v2.0.3 in this step.
- name: Get current SemVer version from Cargo.toml
id: get_current_semver
run: echo "semver=v$(cargo metadata --format-version 1 | jq -r '.packages | .[] | select(.name=="${{ steps.get_repo_name.outputs.repo_name }}") | .version')" >> "$GITHUB_OUTPUT"
- name: Create a filename for the macOS binary's zip file
id: create_zip_filename
run: echo "zip_filename=${{ steps.get_repo_name.outputs.repo_name }}_${{ steps.get_current_semver.outputs.semver }}_macos_universal.zip" >> "$GITHUB_OUTPUT"
- name: Compress *.app directory to *.zip, preserving resource fork and Finder information
run: ditto -c -k --sequesterRsrc --keepParent ${{ steps.get_repo_name.outputs.repo_name }}.app ${{ steps.create_zip_filename.outputs.zip_filename }}
- name: Create job summary about macOS binary creation
run: echo "## Created universal macOS binary" >> $GITHUB_STEP_SUMMARY
- name: Upload macOS executable for release
uses: actions/upload-artifact@v4
with:
# Give the artifact the same name as the zip file, otherwise it'll default to "artifact" and fail b/c already exists.
name: ${{ steps.create_zip_filename.outputs.zip_filename }}
path: ${{ steps.create_zip_filename.outputs.zip_filename }}
# Fail the Action if no zip was found.
if-no-files-found: error
build_windows:
runs-on: ubuntu-latest
outputs:
zip_filename: ${{ steps.create_zip_filename.outputs.zip_filename }}
steps:
- name: Get repository name
id: get_repo_name
run: echo "repo_name=$(basename $GITHUB_REPOSITORY)" >> "$GITHUB_OUTPUT"
- name: Checkout code
uses: actions/checkout@v4
with:
# Fetch all history for all tags and branches instead of `1`, which fetches only the current branch.
fetch-depth: 0
# Include icon images.
lfs: true
- name: Install Rust toolchain with M1 chip support
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: x86_64-pc-windows-gnu
- name: Install cross-compilation tools for building Windows executables on Ubuntu
run: |
sudo apt-get update
sudo apt-get install mingw-w64
- name: Set up rust build caching
uses: Swatinem/rust-cache@v2
- name: Build x86_64 Windows binary
run: cargo build --release --target x86_64-pc-windows-gnu
# Move the `*.exe` to the top level of the repo so it's easier to access.
- name: Move bundled `*.app` directory to top level
run: mv target/x86_64-pc-windows-gnu/release/${{ steps.get_repo_name.outputs.repo_name }}.exe .
- name: Get current SemVer version from Cargo.toml
id: get_current_semver
run: echo "semver=v$(cargo metadata --format-version 1 | jq -r '.packages | .[] | select(.name=="${{ steps.get_repo_name.outputs.repo_name }}") | .version')" >> "$GITHUB_OUTPUT"
- name: Create a filename for the Windows executable's zip file
id: create_zip_filename
run: echo "zip_filename=${{ steps.get_repo_name.outputs.repo_name }}_${{ steps.get_current_semver.outputs.semver }}_windows_gnu_x86_64.zip" >> "$GITHUB_OUTPUT"
- name: Zip the Windows executable
id: zip_executable
run: zip -j ${{ steps.create_zip_filename.outputs.zip_filename }} ${{ steps.get_repo_name.outputs.repo_name }}.exe
- name: Create job summary about executable creation
run: echo "## Created Windows executable" >> $GITHUB_STEP_SUMMARY
- name: Upload Windows executable for release
uses: actions/upload-artifact@v4
with:
# Give the artifact the same name as the zip file, otherwise it'll default to "artifact" and fail b/c already exists.
name: ${{ steps.create_zip_filename.outputs.zip_filename }}
path: ${{ steps.create_zip_filename.outputs.zip_filename }}
# Fail the Action if no zip was found.
if-no-files-found: error
publish_release:
needs: [build_macos, build_windows]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
# We still need to check out the code for this job so we can get the SemVer.
- name: Checkout code
uses: actions/checkout@v4
with:
# Fetch all history for all tags and branches instead of `1`, which fetches only the current branch.
fetch-depth: 0
- name: Get repository name
id: get_repo_name
run: echo "repo_name=$(basename $GITHUB_REPOSITORY)" >> "$GITHUB_OUTPUT"
- name: Get current SemVer version from Cargo.toml
id: get_current_semver
run: echo "semver=v$(cargo metadata --format-version 1 | jq -r '.packages | .[] | select(.name=="${{ steps.get_repo_name.outputs.repo_name }}") | .version')" >> "$GITHUB_OUTPUT"
# Download all artifacts for this run.
- name: download artifacts
uses: actions/download-artifact@v4
with:
# Put artifacts in root instead of giving them their own directories.
merge-multiple: true
- name: Publish a new release
id: publish_release
uses: ncipollo/release-action@v1
with:
tag: ${{ steps.get_current_semver.outputs.semver }}
# Gate release publishing to only happen on main branch. Otherwise, releasing will fail due to duplicate release names.
draft: ${{ github.ref == 'refs/heads/main' && 'false' || 'true' }}
commit: main
# Expect the macOS and windows zips to be available.
artifacts: "${{ needs.build_macos.outputs.zip_filename }},${{ needs.build_windows.outputs.zip_filename }}"
token: ${{ secrets.GITHUB_TOKEN }}
body: |
# New Release: ${{ steps.get_repo_name.outputs.repo_name }} ${{ steps.get_current_semver.outputs.semver }}
This is a new release of FolSum triggered by commit `${{ github.sha }}` on branch `${{ github.ref_name}}`.
## Changelog
- Add feature X
- Fix bug Y
- name: Generate "new release" message with a hyperlink to the release page
id: generate_release_message
run: echo "message=Created new release ${{ steps.get_current_semver.outputs.semver }} at ${{ steps.publish_release.outputs.html_url }}" >> $GITHUB_OUTPUT
- name: Create job summary about new release
run: echo "## ${{ steps.generate_release_message.outputs.message }}" >> $GITHUB_STEP_SUMMARY