Skip to main content

GitHub Actions Integration

Automatically sync your design tokens to your repository using GitHub Actions.

Basic Workflow

Create .github/workflows/sync-tokens.yml:
name: Sync Design Tokens

on:
  schedule:
    - cron: '0 0 * * *'  # Daily at midnight UTC
  workflow_dispatch:  # Manual trigger

jobs:
  sync-tokens:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      
      - name: Download Tokens
        run: |
          curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/light/export?format=css" \
            -o src/styles/tokens.css
      
      - name: Commit Changes
        run: |
          git config user.name "GitHub Actions"
          git config user.email "[email protected]"
          git add src/styles/tokens.css
          git diff --staged --quiet || git commit -m "Update design tokens"
          git push

Setup Steps

1. Create GitHub Secrets

Go to your repository → Settings → Secrets and variables → Actions Add these secrets:
Secret NameValueExample
TOKENCRAFT_TOKENYour API tokendtk_abc123...
TOKENCRAFT_API_BASEAPI base URLhttps://app.tokencraft.dev/api/v1
TOKENSET_IDTokenset IDtokenset-123
MODE_IDMode IDmode-light

2. Create Workflow File

Add the workflow file to your repository:
mkdir -p .github/workflows
touch .github/workflows/sync-tokens.yml

3. Test the Workflow

Trigger manually from GitHub:
  • Go to Actions tab
  • Select “Sync Design Tokens”
  • Click “Run workflow”

Advanced Workflows

Multi-Mode Sync

Sync both light and dark modes:
name: Sync Design Tokens

on:
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:

jobs:
  sync-tokens:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Download Light Mode
        run: |
          curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/light/export?format=css" \
            -o src/styles/tokens-light.css
      
      - name: Download Dark Mode
        run: |
          curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/dark/export?format=css" \
            -o src/styles/tokens-dark.css
      
      - name: Commit Changes
        run: |
          git config user.name "GitHub Actions"
          git config user.email "[email protected]"
          git add src/styles/tokens-*.css
          git diff --staged --quiet || git commit -m "Update design tokens [skip ci]"
          git push

Multi-Format Export

Export in multiple formats:
- name: Export JSON
  run: |
    curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
      "$API/tokensets/$ID/modes/$MODE/export?format=json" \
      -o src/tokens.json

- name: Export CSS
  run: |
    curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
      "$API/tokensets/$ID/modes/$MODE/export?format=css" \
      -o src/tokens.css

With Pull Request

Create a PR instead of direct commit:
name: Sync Design Tokens

on:
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:

jobs:
  sync-tokens:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Download Tokens
        run: |
          curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/light/export?format=css" \
            -o src/styles/tokens.css
      
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v5
        with:
          commit-message: Update design tokens
          title: 'chore: Update design tokens'
          body: |
            Automated update of design tokens from Tokencraft.
            
            - Tokenset: ${{ secrets.TOKENSET_ID }}
            - Mode: light
            - Format: CSS
          branch: update-tokens
          delete-branch: true

With Slack Notification

Notify on updates:
- name: Notify Slack
  if: success()
  uses: 8398a7/action-slack@v3
  with:
    status: success
    text: 'Design tokens updated successfully!'
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Mobile App Workflows

iOS

name: Sync iOS Tokens

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  sync:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Download iOS Tokens
        run: |
          curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/light/export?format=ios" \
            -o ios/DesignSystem/DesignTokens.swift
      
      - name: Build iOS App
        run: |
          cd ios
          xcodebuild -scheme MyApp -configuration Debug

Android

name: Sync Android Tokens

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Download Android Tokens
        run: |
          curl -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/light/export?format=android" \
            -o android/app/src/main/res/values/tokens.xml
      
      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'adopt'
      
      - name: Build Android App
        run: |
          cd android
          ./gradlew assembleDebug

Best Practices

1. Use Branch Protection

Prevent direct pushes to main:
- name: Create PR
  uses: peter-evans/create-pull-request@v5
  # Don't push directly to main

2. Add Validation

Validate tokens before committing:
- name: Validate CSS
  run: |
    npm install -g csslint
    csslint src/styles/tokens.css

3. Cache Dependencies

Speed up workflows:
- name: Cache node modules
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

4. Skip CI on Token Updates

Avoid infinite loops:
git commit -m "Update tokens [skip ci]"

Troubleshooting

Authentication Failed

Error: 401 Unauthorized Solution:
  1. Verify TOKENCRAFT_TOKEN secret is set
  2. Check token hasn’t been revoked
  3. Ensure no extra spaces in secret value

File Not Found

Error: curl: failed to write Solution: Create directory first:
- name: Create directory
  run: mkdir -p src/styles

- name: Download Tokens
  run: curl ... -o src/styles/tokens.css

No Changes to Commit

Error: nothing to commit Solution: Use conditional commit:
git diff --staged --quiet || git commit -m "Update tokens"

Example: Complete Production Workflow

name: Sync Design Tokens

on:
  schedule:
    - cron: '0 */6 * * *'  # Every 6 hours
  workflow_dispatch:

jobs:
  sync-tokens:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Download Light Mode
        run: |
          curl -f -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/light/export?format=css" \
            -o src/styles/tokens-light.css
      
      - name: Download Dark Mode
        run: |
          curl -f -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/dark/export?format=css" \
            -o src/styles/tokens-dark.css
      
      - name: Download JSON
        run: |
          curl -f -H "Authorization: Bearer ${{ secrets.TOKENCRAFT_TOKEN }}" \
            "${{ secrets.TOKENCRAFT_API_BASE }}/tokensets/${{ secrets.TOKENSET_ID }}/modes/light/export?format=json" \
            -o src/tokens/tokens.json
      
      - name: Validate CSS
        run: |
          npm install -g csslint
          csslint src/styles/tokens-light.css
          csslint src/styles/tokens-dark.css
      
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v5
        with:
          commit-message: 'chore: update design tokens'
          title: 'Update Design Tokens'
          body: |
            Automated token sync from Tokencraft
            
            - Light mode CSS
            - Dark mode CSS
            - JSON export
          branch: sync-tokens-${{ github.run_number }}
          delete-branch: true
          labels: design-tokens, automated
      
      - name: Notify on Failure
        if: failure()
        uses: 8398a7/action-slack@v3
        with:
          status: failure
          text: 'Token sync failed!'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Next Steps