add theme studio #505
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: CI | |
| on: | |
| push: | |
| branches: | |
| - '**' | |
| pull_request: | |
| branches: [main, dev] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ───────────────────────────────────────────── | |
| # Validate: type-check, lint, format, tests, build | |
| # ───────────────────────────────────────────── | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| - name: Verify lockfile cross-platform natives | |
| run: node scripts/verify-lockfile-natives.mjs | |
| - name: Cache Electron binary | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v4 | |
| with: | |
| path: | | |
| ~/.cache/electron | |
| ~/.cache/electron-builder | |
| key: electron-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| restore-keys: | | |
| electron-${{ runner.os }}- | |
| - name: Cache Go binaries | |
| id: go-bin-cache | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v4 | |
| with: | |
| path: resources/bin/linux | |
| key: go-binaries-linux-${{ hashFiles('scripts/binary-versions.json') }} | |
| - name: Setup Go | |
| if: steps.go-bin-cache.outputs.cache-hit != 'true' | |
| uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v5 | |
| with: | |
| go-version: '1.25' | |
| - name: Build Go binaries from source | |
| if: steps.go-bin-cache.outputs.cache-hit != 'true' | |
| run: bash scripts/build-binaries-from-source.sh linux | |
| - name: Verify Go binaries | |
| run: node scripts/verify-binaries.mjs linux | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Verify release metadata | |
| run: npm run verify:release-metadata | |
| - name: Type check | |
| run: npm run type-check | |
| - name: Architecture boundaries | |
| run: npm run architecture | |
| - name: Theme token contract | |
| run: npm run verify:theme-tokens | |
| - name: Lint | |
| run: npm run lint | |
| - name: Format check | |
| run: npm run format:check | |
| - name: Test coverage | |
| run: npm run test:coverage | |
| - name: Upload coverage report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: coverage-report | |
| path: coverage/ | |
| retention-days: 30 | |
| if-no-files-found: ignore | |
| - name: Verify build compiles | |
| run: npm run build && npm run verify:bundle-budgets | |
| - name: Security audit | |
| run: npm audit --audit-level=high | |
| - name: Generate supply-chain metadata | |
| run: | | |
| npm --silent run generate:sbom > sbom.cdx.json | |
| npm run generate:provenance -- build-provenance.json | |
| - name: Upload supply-chain metadata | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: supply-chain-metadata | |
| path: | | |
| sbom.cdx.json | |
| build-provenance.json | |
| retention-days: 30 | |
| # ───────────────────────────────────────────── | |
| # Notify: Telegram (one summary per push, any branch) | |
| # ───────────────────────────────────────────── | |
| notify: | |
| needs: validate | |
| runs-on: ubuntu-latest | |
| if: always() && github.event_name == 'push' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Send Telegram notification | |
| env: | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| TELEGRAM_CHAT_ID: '-1003461541563' | |
| VALIDATE_RESULT: ${{ needs.validate.result }} | |
| BEFORE_SHA: ${{ github.event.before }} | |
| AFTER_SHA: ${{ github.event.after }} | |
| BRANCH: ${{ github.ref_name }} | |
| run: | | |
| if [ -z "$TELEGRAM_BOT_TOKEN" ]; then | |
| echo "Telegram bot token not configured, skipping" | |
| exit 0 | |
| fi | |
| NULL_SHA="0000000000000000000000000000000000000000" | |
| REPO_URL="${{ github.server_url }}/${{ github.repository }}" | |
| # One summary notification per push for every branch (avoid per-commit spam) | |
| if [ -n "$BRANCH" ]; then | |
| if [ "$BEFORE_SHA" = "$NULL_SHA" ] || ! git merge-base --is-ancestor "$BEFORE_SHA" "$AFTER_SHA" 2>/dev/null; then | |
| COUNT=$(git rev-list --count "$AFTER_SHA") | |
| RANGE="$AFTER_SHA" | |
| URL="$REPO_URL/commits/$BRANCH" | |
| else | |
| COUNT=$(git rev-list --count "$BEFORE_SHA..$AFTER_SHA") | |
| RANGE="$BEFORE_SHA..$AFTER_SHA" | |
| URL="$REPO_URL/compare/$BEFORE_SHA...$AFTER_SHA" | |
| fi | |
| NOUN=commits; [ "$COUNT" = "1" ] && NOUN=commit | |
| REPO_NAME=${REPO_URL##*/} | |
| LABEL=$(printf '%s' "$BRANCH" | tr '[:lower:]' '[:upper:]') | |
| TEXT="<b>[$LABEL] $REPO_NAME</b>" | |
| if [ "$VALIDATE_RESULT" = "success" ]; then | |
| printf -v TEXT '%s\n%s %s pushed to %s' "$TEXT" "$COUNT" "$NOUN" "$BRANCH" | |
| else | |
| printf -v TEXT '%s\nCI failed on %s (%s %s)' "$TEXT" "$BRANCH" "$COUNT" "$NOUN" | |
| fi | |
| # Commit titles (HTML-escaped), oldest first, capped to avoid huge messages. | |
| MAX=50 | |
| TITLES=$(git log --reverse --max-count="$MAX" --pretty=format:'%s' "$RANGE" \ | |
| | sed -e 's/&/\&/g' -e 's/</\</g' -e 's/>/\>/g') | |
| if [ "$COUNT" -gt "$MAX" ]; then | |
| printf -v TITLES '%s\n… and %s more' "$TITLES" "$((COUNT - MAX))" | |
| fi | |
| if [ "$COUNT" -gt 1 ]; then | |
| # Multiple commits: collapse the title list into an expandable quote. | |
| printf -v TEXT '%s\n\n<blockquote expandable>%s</blockquote>' "$TEXT" "$TITLES" | |
| elif [ -n "$TITLES" ]; then | |
| printf -v TEXT '%s\n\n<blockquote>%s</blockquote>' "$TEXT" "$TITLES" | |
| fi | |
| printf -v TEXT '%s\n\n<a href="%s">View commits</a>' "$TEXT" "$URL" | |
| curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ | |
| -d chat_id="${TELEGRAM_CHAT_ID}" \ | |
| -d parse_mode="HTML" \ | |
| -d disable_web_page_preview="true" \ | |
| --data-urlencode text="$TEXT" | |
| exit 0 | |
| fi | |
| # ───────────────────────────────────────────── | |
| # Dependency review (PRs only) | |
| # ───────────────────────────────────────────── | |
| dependency-review: | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4 | |
| - name: Dependency review | |
| uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 |