forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
253 lines (243 loc) · 10.8 KB
/
Copy pathdesktop_publish_preview.yml
File metadata and controls
253 lines (243 loc) · 10.8 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
name: Publish Desktop Preview
on:
workflow_dispatch:
inputs:
source_ref:
description: 'Canonical preview branch, exactly preview/<slug>'
required: true
type: string
tester_notes:
description: 'Optional tester-facing notes for this preview'
required: false
default: ''
type: string
backend_mode:
description: 'API compatibility declaration for this preview'
required: true
default: production_compatible
type: choice
options:
- production_compatible
- preview_backend
python_api_url:
description: 'Required only for preview_backend; HTTPS Python API URL'
required: false
default: ''
type: string
desktop_api_url:
description: 'Required only for preview_backend; HTTPS Desktop API URL'
required: false
default: ''
type: string
permissions:
contents: read
jobs:
resolve:
name: Resolve canonical preview ref
runs-on: ubuntu-latest
outputs:
slug: ${{ steps.preview.outputs.slug }}
preview_id: ${{ steps.preview.outputs.preview_id }}
source_sha: ${{ steps.preview.outputs.source_sha }}
source_ref: ${{ steps.preview.outputs.source_ref }}
python_api_url: ${{ steps.backend.outputs.python_api_url }}
desktop_api_url: ${{ steps.backend.outputs.desktop_api_url }}
steps:
- name: Checkout publishing controls from main
uses: actions/checkout@v7
with:
# workflow_dispatch can be invoked against another ref. Controls must
# remain default-branch owned before an Environment exposes secrets.
ref: main
fetch-depth: 0
- name: Resolve a canonical preview branch to an immutable SHA
id: preview
env:
REPOSITORY: ${{ github.repository }}
SOURCE_REF: ${{ inputs.source_ref }}
run: |
set -euo pipefail
test "$REPOSITORY" = "BasedHardware/omi" || {
echo "Desktop previews may only publish from BasedHardware/omi." >&2
exit 1
}
if ! [[ "$SOURCE_REF" =~ ^preview/([a-z][a-z0-9-]{0,47})$ ]]; then
echo "source_ref must be exactly preview/<lowercase-slug>." >&2
exit 1
fi
slug="${BASH_REMATCH[1]}"
resolved="$(git ls-remote --exit-code origin "refs/heads/$SOURCE_REF" | awk 'NR == 1 { print $1 }')"
if ! [[ "$resolved" =~ ^[0-9a-f]{40}$ ]]; then
echo "source_ref did not resolve to a canonical commit SHA." >&2
exit 1
fi
preview_id="p$(printf '%s' "$slug" | sha256sum | cut -c1-10)"
{
echo "slug=$slug"
echo "preview_id=$preview_id"
echo "source_sha=$resolved"
echo "source_ref=$SOURCE_REF"
} >> "$GITHUB_OUTPUT"
- name: Validate the declared backend contract
id: backend
env:
BACKEND_MODE: ${{ inputs.backend_mode }}
PYTHON_API_URL: ${{ inputs.python_api_url }}
DESKTOP_API_URL: ${{ inputs.desktop_api_url }}
run: |
set -euo pipefail
case "$BACKEND_MODE" in
production_compatible)
test -z "$PYTHON_API_URL" && test -z "$DESKTOP_API_URL" || {
echo "production_compatible previews must use the canonical production URLs." >&2
exit 1
}
python_api_url="https://api.omi.me"
desktop_api_url="https://desktop-backend-hhibjajaja-uc.a.run.app/"
;;
preview_backend)
[[ "$PYTHON_API_URL" =~ ^https:// ]] && [[ "$DESKTOP_API_URL" =~ ^https:// ]] || {
echo "preview_backend requires HTTPS Python and Desktop API URLs." >&2
exit 1
}
python_api_url="$PYTHON_API_URL"
desktop_api_url="$DESKTOP_API_URL"
;;
*)
echo "Unsupported backend mode: $BACKEND_MODE" >&2
exit 1
;;
esac
{
echo "python_api_url=$python_api_url"
echo "desktop_api_url=$desktop_api_url"
} >> "$GITHUB_OUTPUT"
- name: Summarize exact preview awaiting approval
env:
PREVIEW_SLUG: ${{ steps.preview.outputs.slug }}
PREVIEW_ID: ${{ steps.preview.outputs.preview_id }}
PREVIEW_SOURCE_REF: ${{ steps.preview.outputs.source_ref }}
PREVIEW_SOURCE_SHA: ${{ steps.preview.outputs.source_sha }}
PREVIEW_BACKEND_MODE: ${{ inputs.backend_mode }}
OMI_PYTHON_API_URL: ${{ steps.backend.outputs.python_api_url }}
OMI_DESKTOP_API_URL: ${{ steps.backend.outputs.desktop_api_url }}
PREVIEW_NOTES: ${{ inputs.tester_notes }}
run: |
set -euo pipefail
notes_json="$(jq -Rn --arg value "$PREVIEW_NOTES" '$value')"
{
echo "### Preview approval context"
echo
echo "- Source branch: \`${PREVIEW_SOURCE_REF}\`"
echo "- Source commit: [\`${PREVIEW_SOURCE_SHA}\`](https://github.com/${GITHUB_REPOSITORY}/commit/${PREVIEW_SOURCE_SHA})"
echo "- Preview identity: \`${PREVIEW_SLUG}\` (\`${PREVIEW_ID}\`)"
echo "- Backend mode: \`${PREVIEW_BACKEND_MODE}\`"
echo "- Python API: \`${OMI_PYTHON_API_URL}\`"
echo "- Desktop API: \`${OMI_DESKTOP_API_URL}\`"
echo "- Tester notes (JSON-escaped): ${notes_json}"
} >> "$GITHUB_STEP_SUMMARY"
publish:
name: Build and publish approved preview
needs: resolve
runs-on: ubuntu-latest
# Configure desktop-preview-publish with release-maintainers as required
# reviewers, no self-review, and no administrator bypass.
environment: desktop-preview-publish
concurrency:
group: desktop-preview-publish-${{ needs.resolve.outputs.preview_id }}
cancel-in-progress: false
steps:
- name: Checkout publishing controls from main
uses: actions/checkout@v7
with:
ref: main
fetch-depth: 1
- name: Start the trusted Codemagic preview workflow
id: dispatch
env:
CODEMAGIC_APP_ID: ${{ vars.CODEMAGIC_APP_ID || '66c95e6ec76853c447b8bcbb' }}
CODEMAGIC_API_TOKEN: ${{ secrets.CODEMAGIC_API_TOKEN }}
PREVIEW_SLUG: ${{ needs.resolve.outputs.slug }}
PREVIEW_ID: ${{ needs.resolve.outputs.preview_id }}
PREVIEW_SOURCE_REF: ${{ needs.resolve.outputs.source_ref }}
PREVIEW_SOURCE_SHA: ${{ needs.resolve.outputs.source_sha }}
PREVIEW_NOTES: ${{ inputs.tester_notes }}
PREVIEW_BACKEND_MODE: ${{ inputs.backend_mode }}
OMI_PYTHON_API_URL: ${{ needs.resolve.outputs.python_api_url }}
OMI_DESKTOP_API_URL: ${{ needs.resolve.outputs.desktop_api_url }}
run: |
set -euo pipefail
test -n "$CODEMAGIC_API_TOKEN" || {
echo "CODEMAGIC_API_TOKEN must be an environment secret." >&2
exit 1
}
notes_base64="$(printf '%s' "$PREVIEW_NOTES" | base64 | tr -d '\n')"
payload="$(jq -n \
--arg app_id "$CODEMAGIC_APP_ID" \
--arg slug "$PREVIEW_SLUG" \
--arg preview_id "$PREVIEW_ID" \
--arg source_ref "$PREVIEW_SOURCE_REF" \
--arg source_sha "$PREVIEW_SOURCE_SHA" \
--arg notes "$notes_base64" \
--arg backend_mode "$PREVIEW_BACKEND_MODE" \
--arg python_api_url "$OMI_PYTHON_API_URL" \
--arg desktop_api_url "$OMI_DESKTOP_API_URL" \
'{appId: $app_id, workflowId: "omi-desktop-swift-preview", branch: "main", environment: {variables: {PREVIEW_MODE: "true", PREVIEW_SLUG: $slug, PREVIEW_ID: $preview_id, PREVIEW_SOURCE_REF: $source_ref, PREVIEW_SOURCE_SHA: $source_sha, PREVIEW_NOTES_BASE64: $notes, PREVIEW_BACKEND_MODE: $backend_mode, OMI_PYTHON_API_URL: $python_api_url, OMI_DESKTOP_API_URL: $desktop_api_url}}}')"
response="$(curl --fail --show-error --silent \
-H 'Content-Type: application/json' \
-H "x-auth-token: $CODEMAGIC_API_TOKEN" \
--data "$payload" \
https://api.codemagic.io/builds)"
build_id="$(jq -r '.buildId // empty' <<<"$response")"
test -n "$build_id" || { echo "Codemagic did not return a build ID." >&2; exit 1; }
[[ "$build_id" =~ ^[A-Za-z0-9_-]+$ ]] || {
echo "Codemagic returned an invalid build ID." >&2
exit 1
}
echo "build_id=$build_id" >> "$GITHUB_OUTPUT"
{
echo "### Desktop preview requested"
echo
echo "- Ref: \`${PREVIEW_SOURCE_REF}\`"
echo "- SHA: \`${PREVIEW_SOURCE_SHA}\`"
echo "- Preview: \`${PREVIEW_SLUG}\` (\`${PREVIEW_ID}\`)"
echo "- Landing page: \`https://macos.omi.me/preview/${PREVIEW_SLUG}\`"
echo "- Codemagic build: \`${build_id}\`"
} >> "$GITHUB_STEP_SUMMARY"
# Dispatch alone is not proof the preview published. Without this poll the
# GitHub job went green while Codemagic died at startup (#10145 / #9895).
- name: Observe Codemagic preview build to a terminal status
env:
CODEMAGIC_API_TOKEN: ${{ secrets.CODEMAGIC_API_TOKEN }}
# Pass provider IDs via env (not ${{ }} inside run) so malformed
# Codemagic values cannot become shell syntax (#10145 cubic P1).
CODEMAGIC_APP_ID: ${{ vars.CODEMAGIC_APP_ID || '66c95e6ec76853c447b8bcbb' }}
CODEMAGIC_BUILD_ID: ${{ steps.dispatch.outputs.build_id }}
PREVIEW_SLUG: ${{ needs.resolve.outputs.slug }}
PREVIEW_SOURCE_SHA: ${{ needs.resolve.outputs.source_sha }}
run: |
set -euo pipefail
python3 .github/scripts/observe-codemagic-preview-build.py \
--app-id "$CODEMAGIC_APP_ID" \
--build-id "$CODEMAGIC_BUILD_ID" \
--preview-slug "$PREVIEW_SLUG" \
--source-sha "$PREVIEW_SOURCE_SHA" \
--timeout-seconds 7200 \
--poll-seconds 30 \
--output "$RUNNER_TEMP/codemagic-preview-build-observation.json"
{
echo
echo "### Codemagic preview observation"
echo
echo '```json'
jq -c . "$RUNNER_TEMP/codemagic-preview-build-observation.json"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
- name: Retain Codemagic preview build observation evidence
if: always() && steps.dispatch.outcome == 'success'
uses: actions/upload-artifact@v7
with:
name: codemagic-preview-build-observation-${{ needs.resolve.outputs.slug }}-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/codemagic-preview-build-observation.json
if-no-files-found: warn
retention-days: 30