Skip to content

add theme studio

add theme studio #505

Workflow file for this run

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/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/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