-
Notifications
You must be signed in to change notification settings - Fork 0
311 lines (279 loc) · 12.4 KB
/
Copy pathone.yml
File metadata and controls
311 lines (279 loc) · 12.4 KB
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
name: one
on:
push:
tags:
- 'one-v*'
workflow_dispatch:
inputs:
release:
description: 'Create a GitHub release with the artifacts'
type: boolean
default: false
permissions:
contents: write
jobs:
build:
name: ${{ matrix.label }}
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- label: macOS (arm64)
os: macos-14
target: aarch64-apple-darwin
target-arch: arm64
bundle-dir: macos
- label: macOS (x64)
os: macos-14
target: x86_64-apple-darwin
target-arch: x64
bundle-dir: macos
- label: Windows (x64)
os: windows-2022
target: x86_64-pc-windows-msvc
target-arch: x64
bundle-dir: nsis
- label: Linux (x64)
os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
target-arch: x64
bundle-dir: deb
steps:
- uses: actions/checkout@v4
- name: Linux build deps
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev libssl-dev libayatana-appindicator3-dev \
librsvg2-dev patchelf libgtk-3-dev libsoup-3.0-dev
- uses: pnpm/action-setup@v4
with:
version: 10.28.2
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
workspaces: apps/objectos-one/src-tauri
- name: Install workspace deps
run: pnpm install --frozen-lockfile
- name: Sync app version to @objectstack/cli
run: pnpm --filter @objectos/one sync-version
- name: Verify tag matches @objectstack/cli version
if: startsWith(github.ref, 'refs/tags/one-v')
shell: bash
run: |
set -euo pipefail
# Tag form: one-v<X.Y.Z>; must equal the resolved cli version that
# sync-version wrote into the bundle, otherwise the updater's
# latest.json (built from the tag) will not match the installed
# app version and auto-update will silently fail.
TAG_VERSION="${GITHUB_REF_NAME#one-v}"
PKG_VERSION=$(node -p "require('./apps/objectos-one/package.json').version")
echo "tag version : $TAG_VERSION"
echo "pkg version : $PKG_VERSION"
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "::error::tag $GITHUB_REF_NAME does not match @objectstack/cli version $PKG_VERSION. Re-tag as one-v$PKG_VERSION."
exit 1
fi
- name: Stage Node runtime
env:
TARGET_ARCH: ${{ matrix.target-arch }}
run: pnpm --filter @objectos/one stage
- name: Import Apple signing certificate
if: runner.os == 'macOS'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
set -euo pipefail
if [ -z "${APPLE_CERTIFICATE:-}" ]; then
echo "APPLE_CERTIFICATE not set — skipping (build will be unsigned)."
exit 0
fi
KEYCHAIN="$RUNNER_TEMP/build.keychain-db"
KEYCHAIN_PASSWORD="$(openssl rand -base64 24)"
CERT_PATH="$RUNNER_TEMP/cert.p12"
echo "$APPLE_CERTIFICATE" | base64 --decode > "$CERT_PATH"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
security set-keychain-settings -lut 21600 "$KEYCHAIN"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
security import "$CERT_PATH" -k "$KEYCHAIN" \
-P "$APPLE_CERTIFICATE_PASSWORD" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list \
-S apple-tool:,apple:,codesign: \
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN" >/dev/null
# Put new keychain first in the search list (keep existing ones too).
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
echo "Available signing identities:"
security find-identity -v -p codesigning "$KEYCHAIN"
rm -f "$CERT_PATH"
- name: Debug Apple secret presence
if: runner.os == 'macOS'
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
# Print only the byte-length of each Apple secret so we can
# tell whether the value reached the runner without leaking it.
echo "APPLE_CERTIFICATE length=${#APPLE_CERTIFICATE}"
echo "APPLE_CERTIFICATE_PASSWORD length=${#APPLE_CERTIFICATE_PASSWORD}"
echo "APPLE_SIGNING_IDENTITY length=${#APPLE_SIGNING_IDENTITY}"
echo "APPLE_TEAM_ID length=${#APPLE_TEAM_ID}"
echo "APPLE_ID length=${#APPLE_ID}"
echo "APPLE_PASSWORD length=${#APPLE_PASSWORD}"
- name: Pre-sign staged runtime binaries (macOS)
if: runner.os == 'macOS'
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
set -euo pipefail
if [ -z "${APPLE_SIGNING_IDENTITY:-}" ]; then
echo "APPLE_SIGNING_IDENTITY not set — skipping pre-sign."
exit 0
fi
RUNTIME="apps/objectos-one/src-tauri/runtime"
if [ ! -d "$RUNTIME" ]; then
echo "Runtime dir not found at $RUNTIME"
exit 1
fi
# Notarization requires every Mach-O inside the .app to be signed
# with the same Developer ID, hardened runtime, and a secure
# timestamp. Tauri's own codesign pass doesn't deep-sign embedded
# Node native binaries, so we sign them here before Tauri bundles.
#
# CRITICAL: the Node binary runs V8, which maps executable (JIT)
# memory at startup. Under hardened runtime that is blocked unless
# the binary carries the JIT entitlements below — otherwise macOS
# kills node with SIGTRAP (exit 133) the instant it launches, which
# surfaces as the bundled runtime crash-looping on every start
# ("sidecar exited; restarting"). Always pass --entitlements.
ENTITLEMENTS="apps/objectos-one/src-tauri/runtime-entitlements.plist"
echo "Scanning $RUNTIME for Mach-O binaries..."
find "$RUNTIME" -type f \
\( -name '*.node' -o -name '*.dylib' -o -name '*.so' \
-o -path '*/bin/*' -o -name 'node' \) \
| while read -r f; do
# Skip anything that isn't actually a Mach-O.
if file -b "$f" | grep -qE 'Mach-O'; then
echo " signing $f"
codesign --force --sign "$APPLE_SIGNING_IDENTITY" \
--timestamp --options runtime \
--entitlements "$ENTITLEMENTS" "$f"
fi
done
echo "Done. Verifying a sample:"
find "$RUNTIME" -type f -name '*.node' | head -1 | while read -r f; do
codesign -dv --verbose=2 "$f" 2>&1 | head -10 || true
done
# Guard against the JIT-entitlement regression: the node binary MUST
# carry com.apple.security.cs.allow-jit or the runtime crash-loops at
# launch. Fail the build loudly here rather than shipping a brick.
NODE_BIN="$RUNTIME/node"
if [ -f "$NODE_BIN" ]; then
echo "Verifying node JIT entitlement:"
if codesign -d --entitlements - --xml "$NODE_BIN" 2>/dev/null \
| tr -d '\0' | grep -q 'com.apple.security.cs.allow-jit'; then
echo " ✓ allow-jit present on node"
else
echo " ✗ allow-jit MISSING on node — runtime would crash-loop." >&2
exit 1
fi
fi
- name: Build Tauri bundle
env:
# AppImage tools need FUSE on Linux; ubuntu-22.04 dropped it.
# Setting this forces AppImage runtime to extract-and-run instead.
APPIMAGE_EXTRACT_AND_RUN: "1"
# Tauri updater key (no-password key generated via `signer generate --ci`).
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ""
# macOS code signing (only used if cert was imported above).
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
# macOS notarization (only triggered if APPLE_ID + APPLE_PASSWORD are set).
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
shell: bash
run: |
set -euo pipefail
# Tauri treats any defined APPLE_ID/APPLE_PASSWORD as a request to
# notarize; unset them when empty so we just sign without notarizing.
if [ -z "${APPLE_ID:-}" ] || [ -z "${APPLE_PASSWORD:-}" ]; then
unset APPLE_ID APPLE_PASSWORD
echo "APPLE_ID/APPLE_PASSWORD not set — will sign without notarization."
fi
pnpm --filter @objectos/one tauri build --target ${{ matrix.target }}
- name: Rename macOS updater bundle (avoid name clash)
if: runner.os == 'macOS'
shell: bash
env:
TARGET_ARCH: ${{ matrix.target-arch }}
TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
# Tauri names the macOS updater archive `ObjectOS.app.tar.gz` for
# both arm64 and x64 builds. Renaming includes the target so the
# GH release keeps both, and build-update-manifest.mjs can pick
# the correct one per platform key.
DIR="apps/objectos-one/src-tauri/target/$TARGET/release/bundle/macos"
if [ -f "$DIR/ObjectOS.app.tar.gz" ]; then
mv "$DIR/ObjectOS.app.tar.gz" "$DIR/ObjectOS-$TARGET.app.tar.gz"
mv "$DIR/ObjectOS.app.tar.gz.sig" "$DIR/ObjectOS-$TARGET.app.tar.gz.sig"
fi
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: objectos-one-${{ matrix.target }}
path: |
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*.dmg
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*-setup.exe
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*.msi
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*.deb
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*.AppImage
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*.app.tar.gz
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*.nsis.zip
apps/objectos-one/src-tauri/target/${{ matrix.target }}/release/bundle/**/*.sig
if-no-files-found: warn
release:
name: Publish release
needs: build
if: startsWith(github.ref, 'refs/tags/one-v') || inputs.release
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: artifacts
- name: Generate latest.json (updater manifest)
env:
TAG: ${{ github.ref_name }}
run: node .github/scripts/build-update-manifest.mjs artifacts "$TAG" > artifacts/latest.json
- name: Create release
uses: softprops/action-gh-release@v2
with:
draft: false
generate_release_notes: true
name: ObjectOS One ${{ github.ref_name }}
files: |
artifacts/**/*.dmg
artifacts/**/*-setup.exe
artifacts/**/*.msi
artifacts/**/*.deb
artifacts/**/*.AppImage
artifacts/**/*.app.tar.gz
artifacts/**/*.nsis.zip
artifacts/**/*.sig
artifacts/latest.json