-
Notifications
You must be signed in to change notification settings - Fork 0
335 lines (282 loc) · 11.8 KB
/
release.yml
File metadata and controls
335 lines (282 loc) · 11.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
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
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
name: Build and Release
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
tag_name:
description: "Tag name for release (e.g., v0.1.1)"
required: true
default: "v0.1.1"
env:
# Mask sensitive values in logs
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
# CI and build configuration
CI: true
# Code signing configuration
CSC_IDENTITY_AUTO_DISCOVERY: true
permissions:
contents: write
jobs:
# === 2단계 빌드/배포 아키텍처 ===
# Job 1: Build - 앱 빌드 및 코드사이닝만 수행
build:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: latest
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Cache pnpm dependencies
uses: actions/cache@v4
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Fix electron installation
run: |
if [ -f "node_modules/electron/install.js" ]; then
node node_modules/electron/install.js
fi
shell: bash
- name: Build application
run: pnpm run build
- name: Import Apple certificate
run: |
if [ -n "$APPLE_CERTIFICATE" ]; then
echo "Setting up Apple certificate..."
# Create variables for keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
# Decode certificate from base64 (secure method)
echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12
# Create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Import certificate (GitHub Actions masks the password in logs)
security import certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH login.keychain-db
security default-keychain -s $KEYCHAIN_PATH
# Allow codesign to access the certificate without password prompt
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH >/dev/null 2>&1
echo "Certificate imported successfully"
# Verify certificate (minimal output)
if security find-identity -p codesigning $KEYCHAIN_PATH >/dev/null 2>&1; then
echo "Certificate verification successful"
else
echo "Certificate verification failed"
exit 1
fi
# Clean up certificate file
rm -f certificate.p12
else
echo "No Apple certificate found in secrets"
fi
- name: Validate secrets
run: |
# Apple 인증서 관련 secrets 검증
if [ -z "$APPLE_CERTIFICATE" ]; then
echo "❌ ERROR: APPLE_CERTIFICATE secret이 설정되지 않았습니다."
echo "macOS 코드 사이닝을 위해 APPLE_CERTIFICATE secret을 설정해주세요."
exit 1
fi
if [ -z "$APPLE_CERTIFICATE_PASSWORD" ]; then
echo "❌ ERROR: APPLE_CERTIFICATE_PASSWORD secret이 설정되지 않았습니다."
echo "macOS 코드 사이닝을 위해 APPLE_CERTIFICATE_PASSWORD secret을 설정해주세요."
exit 1
fi
# Apple ID 관련 secrets 검증
if [ -z "$APPLE_ID" ]; then
echo "❌ ERROR: APPLE_ID secret이 설정되지 않았습니다."
echo "macOS 노타리제이션을 위해 APPLE_ID secret을 설정해주세요."
exit 1
fi
if [ -z "$APPLE_APP_SPECIFIC_PASSWORD" ]; then
echo "❌ ERROR: APPLE_APP_SPECIFIC_PASSWORD secret이 설정되지 않았습니다."
echo "macOS 노타리제이션을 위해 APPLE_APP_SPECIFIC_PASSWORD secret을 설정해주세요."
exit 1
fi
if [ -z "$APPLE_TEAM_ID" ]; then
echo "❌ ERROR: APPLE_TEAM_ID secret이 설정되지 않았습니다."
echo "macOS 노타리제이션을 위해 APPLE_TEAM_ID secret을 설정해주세요."
exit 1
fi
echo "✅ macOS 코드 사이닝 및 노타리제이션 secrets가 모두 설정되었습니다."
shell: bash
- name: Package application
run: |
# Check if certificate was imported (suppress sensitive output)
if security find-identity -p codesigning | grep -q "Developer ID Application" 2>/dev/null; then
echo "Certificate found, building with code signing and notarization"
# Debug: Check environment variables before building (completely safe - no values exposed)
echo "Environment variables for notarization:"
if [ -n "$APPLE_ID" ]; then echo " APPLE_ID: ***SET***"; else echo " APPLE_ID: NOT_SET"; fi
if [ -n "$APPLE_APP_SPECIFIC_PASSWORD" ]; then echo " APPLE_APP_SPECIFIC_PASSWORD: ***SET***"; else echo " APPLE_APP_SPECIFIC_PASSWORD: NOT_SET"; fi
if [ -n "$APPLE_TEAM_ID" ]; then echo " APPLE_TEAM_ID: ***SET***"; else echo " APPLE_TEAM_ID: NOT_SET"; fi
echo " CI: $CI"
# === 2단계 빌드/배포 아키텍처 - 1단계: 빌드만 ===
# 빌드만 수행하고 GitHub 배포는 하지 않음 (--publish never)
# 2단계에서 별도 액션(softprops/action-gh-release)이 배포 담당
pnpm run package:gh-action
# Verify signing (minimal output to avoid exposing sensitive info)
echo "Verifying code signature..."
for app in release/**/*.app; do
if [ -e "$app" ]; then
echo "Checking: $(basename "$app")"
if codesign --verify --deep --strict "$app" >/dev/null 2>&1; then
echo "✓ Code signature valid for $(basename "$app")"
else
echo "⚠ Code signature verification failed for $(basename "$app")"
fi
fi
done
else
echo "Unexpected: Certificate not found after validation"
exit 1
fi
- name: List built files
run: |
echo "=== Built files for macOS ==="
find . -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.app" \) -exec ls -la {} \;
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: macos-artifacts
path: |
release/*.dmg
release/*.zip
release/*.yml
release/*.blockmap
retention-days: 5
# Job 2: Release - 빌드된 파일들을 GitHub Releases에 배포
release:
needs: build
runs-on: ubuntu-latest
outputs:
release_files: ${{ steps.get_files.outputs.files }}
tag_name: ${{ steps.get_tag.outputs.tag_name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get tag name
id: get_tag
run: echo "tag_name=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: List downloaded artifacts
run: |
echo "=== Downloaded artifacts ==="
find . -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.yml" -o -name "*.blockmap" \) -exec ls -la {} \;
echo "=== All files in current directory ==="
ls -la
- name: Get release files info
id: get_files
run: |
echo "files<<EOF" >> $GITHUB_OUTPUT
find . -type f \( -name "*.dmg" -o -name "*.zip" \) | while read file; do
filename=$(basename "$file")
size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || echo "0")
echo "{\"name\":\"$filename\",\"size\":$size}"
done | jq -s . >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# 릴리즈 노트 파일 확인
- name: Check for release notes
id: check_release_notes
run: |
TAG_NAME=${GITHUB_REF#refs/tags/}
RELEASE_NOTES_FILE="release-notes/${TAG_NAME}.md"
if [ -f "$RELEASE_NOTES_FILE" ]; then
echo "release_notes_exists=true" >> $GITHUB_OUTPUT
echo "release_notes_file=$RELEASE_NOTES_FILE" >> $GITHUB_OUTPUT
echo "Found release notes file: $RELEASE_NOTES_FILE"
else
echo "release_notes_exists=false" >> $GITHUB_OUTPUT
echo "No release notes file found for $TAG_NAME, will use auto-generated notes"
fi
# === 2단계 빌드/배포 아키텍처 - 2단계: 배포만 ===
# 1단계에서 생성된 파일들을 GitHub Releases에 배포
# electron-builder 대신 GitHub Actions 전용 액션 사용
# 장점: 더 안정적, 유연한 배포 옵션, 자동 릴리즈 노트 생성
- name: Create Release (with custom release notes)
if: steps.check_release_notes.outputs.release_notes_exists == 'true'
id: create_release_custom
uses: softprops/action-gh-release@v1
with:
draft: false
prerelease: false
body_path: ${{ steps.check_release_notes.outputs.release_notes_file }}
files: |
*.dmg
*.zip
*.yml
*.blockmap
- name: Create Release (with auto-generated notes)
if: steps.check_release_notes.outputs.release_notes_exists == 'false'
id: create_release_auto
uses: softprops/action-gh-release@v1
with:
draft: false
prerelease: false
generate_release_notes: true
files: |
*.dmg
*.zip
*.yml
*.blockmap
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Job 3: Deploy Pages - 다운로드 랜딩 페이지 생성 및 배포
deploy-pages:
if: always()
needs: release
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Generate landing page using script
run: |
# Use tag from GitHub ref if release job outputs are not available
if [ -n "${{ needs.release.outputs.tag_name }}" ]; then
TAG_NAME="${{ needs.release.outputs.tag_name }}"
else
TAG_NAME="${GITHUB_REF#refs/tags/}"
fi
# Run the page generation script
./scripts/generate-page.sh "$TAG_NAME" "${{ github.repository }}"
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: "_site"
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4