[Add] 타이포 토큰 업데이트 #51
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Design Tokens | |
| on: | |
| push: | |
| branches: [token-sync] | |
| paths: | |
| - 'tokens/**' | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: macos-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: token-sync | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build tokens | |
| run: npm run build | |
| - name: Generate token diff | |
| env: | |
| BEFORE_SHA: ${{ github.event.before }} | |
| AFTER_SHA: ${{ github.event.after }} | |
| run: | | |
| node << 'EOF' | |
| const { execSync } = require('child_process'); | |
| const fs = require('fs'); | |
| function flattenTokens(obj, prefix = '') { | |
| const result = {}; | |
| for (const [key, val] of Object.entries(obj)) { | |
| const path = prefix ? `${prefix}.${key}` : key; | |
| if (val && typeof val === 'object' && '$value' in val) { | |
| const v = val['$value']; | |
| result[path] = typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v); | |
| } else if (val && typeof val === 'object') { | |
| Object.assign(result, flattenTokens(val, path)); | |
| } | |
| } | |
| return result; | |
| } | |
| function parseTokenFile(content) { | |
| try { return flattenTokens(JSON.parse(content)); } catch { return {}; } | |
| } | |
| const beforeSha = process.env.BEFORE_SHA; | |
| const afterSha = process.env.AFTER_SHA; | |
| function isValidSha(sha) { | |
| try { execSync(`git cat-file -e ${sha}`); return true; } catch { return false; } | |
| } | |
| function resolveBase(afterSha) { | |
| if (beforeSha && isValidSha(beforeSha)) return beforeSha; | |
| try { | |
| return execSync(`git merge-base ${afterSha} origin/default`).toString().trim(); | |
| } catch { return null; } | |
| } | |
| const baseSha = resolveBase(afterSha); | |
| const changedFiles = baseSha | |
| ? execSync(`git diff --name-only ${baseSha} ${afterSha} -- tokens/`) | |
| .toString().trim().split('\n').filter(f => f.endsWith('.json')) | |
| : []; | |
| const rows = []; | |
| for (const file of changedFiles) { | |
| let before = {}, after = {}; | |
| try { before = parseTokenFile(execSync(`git show ${baseSha}:${file}`).toString()); } catch {} | |
| try { after = parseTokenFile(fs.readFileSync(file, 'utf-8')); } catch {} | |
| const keys = new Set([...Object.keys(before), ...Object.keys(after)]); | |
| for (const key of keys) { | |
| const b = before[key], a = after[key]; | |
| if (b === a) continue; | |
| const status = !b ? '✅ 추가' : !a ? '🗑 삭제' : '✏️ 변경'; | |
| rows.push(`| ${status} | \`${key}\` | ${b ?? '_(없음)_'} | ${a ?? '_(삭제됨)_'} |`); | |
| } | |
| } | |
| const table = rows.length === 0 | |
| ? '_Swift 파일만 업데이트되었습니다._' | |
| : `| 상태 | 토큰 | 이전 값 | 변경 값 |\n|---|---|---|---|\n${rows.join('\n')}`; | |
| fs.writeFileSync('/tmp/token_diff.md', table); | |
| EOF | |
| - name: Validate Swift build | |
| shell: bash | |
| run: | | |
| set -o pipefail | |
| xcodebuild build \ | |
| -scheme MDS \ | |
| -destination 'generic/platform=iOS Simulator' \ | |
| -skipPackagePluginValidation \ | |
| | xcpretty || exit 1 | |
| - name: Commit generated Swift files | |
| uses: stefanzweifel/git-auto-commit-action@v5 | |
| with: | |
| commit_message: '[Style Dictionary] Update generated Swift token files' | |
| file_pattern: 'MDS/Sources/Foundation/Base/Base*.swift MDS/Sources/Tokens/Typography.swift MDS/Sources/Tokens/SemanticColor.swift MDSStoryBook/MDSStoryBook/Token/Color/ColorTokenDataSource.swift MDSStoryBook/MDSStoryBook/Token/Typography/TypographyTokenDataSource.swift' | |
| - name: Create Pull Request if not exists | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| DIFF=$(cat /tmp/token_diff.md) | |
| EXISTING=$(gh pr list --head token-sync --base default --state open --json number --jq '.[0].number') | |
| if [ -z "$EXISTING" ]; then | |
| gh pr create \ | |
| --base default \ | |
| --head token-sync \ | |
| --title '[Style Dictionary] 디자인 토큰 업데이트' \ | |
| --body "## 디자인 토큰 변경 사항 | |
| $DIFF | |
| --- | |
| > 🤖 이 PR은 GitHub Actions에 의해 자동 생성되었습니다." | |
| else | |
| echo "PR #$EXISTING already exists. Skipping creation." | |
| fi |