Skip to content

GitHub Setup

Partner Documentation

Configure your GitHub repository for DCS integration.

Required Setup

1. Repository Secrets

Navigate to your repository → Settings → Secrets and variables → Actions.

Add these secrets:

SecretDescription
AZURE_CLIENT_IDService principal client ID
AZURE_CLIENT_SECRETService principal secret
AZURE_TENANT_IDAzure tenant ID
AZURE_SUBSCRIPTION_IDAzure subscription ID
AZURE_SWA_TOKENStatic Web App deployment token
DCS_SERVER_URLDCS API URL

Getting Azure Credentials

Create Service Principal

bash
az ad sp create-for-rbac \
  --name "dcs-site-deployer" \
  --role contributor \
  --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}

This outputs:

json
{
  "appId": "...",         AZURE_CLIENT_ID
  "password": "...",      AZURE_CLIENT_SECRET
  "tenant": "..." AZURE_TENANT_ID
}

Get SWA Token

bash
az staticwebapp secrets list \
  --name your-static-web-app \
  --resource-group your-resource-group

2. Copilot Instructions

Create .github/copilot-instructions.md:

markdown
# Copilot Instructions for [Site Name]

## Project Overview

This is a [VitePress/Vue] site integrated with DCS for content management.

## Technology Stack

- **Framework:** VitePress 1.x
- **Styling:** Tailwind CSS
- **Language:** TypeScript
- **Package Manager:** pnpm

## DCS Integration

### Text Content

Use the `useTextContent` composable for all editable text:

\`\`\`vue
<script setup lang="ts">
import { useTextContent } from '@/lib/use-text-content'
const { t } = useTextContent()
</script>

<template>
  <h1>{{ t('section.element', 'Default text') }}</h1>
</template>
\`\`\`

### Text Key Naming

Follow this pattern: `{page}.{section}.{element}`

Examples:
- `home.hero.title`
- `about.team.description`
- `footer.copyright`

## Component Guidelines

1. Use Vue 3 Composition API with `<script setup lang="ts">`
2. Keep components focused and small
3. Use Tailwind for styling
4. Add prop types and emit declarations

## When Creating Pages

1. Add the page to `.dcs/pages.yaml`
2. Use semantic HTML structure
3. Include proper heading hierarchy
4. Add SEO frontmatter

## Development Workflow

1. Branch from release branch (not main)
2. Make changes
3. Test locally with `pnpm dev`
4. Create PR to release branch

## Common Patterns

### Hero Section

\`\`\`vue
<section class="hero">
  <h1>{{ t('page.hero.title', 'Welcome') }}</h1>
  <p>{{ t('page.hero.subtitle', 'Description') }}</p>
</section>
\`\`\`

### Feature Card

\`\`\`vue
<div class="feature-card">
  <Icon :name="icon" />
  <h3>{{ t(\`page.features.\${id}.title\`, title) }}</h3>
  <p>{{ t(\`page.features.\${id}.description\`, description) }}</p>
</div>
\`\`\`

3. Deployment Workflow

Create .github/workflows/deploy.yml:

yaml
name: Deploy Site

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    types: [opened, synchronize, reopened]
  workflow_dispatch:

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          
      - name: Setup pnpm
        uses: pnpm/action-setup@v2
        with:
          version: 9
          
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
        
      - name: Build
        run: pnpm build
        env:
          VITE_DCS_API: ${{ secrets.VITE_DCS_API }}
          VITE_SITE_ID: ${{ secrets.VITE_SITE_ID }}
          
      - name: Deploy to Azure Static Web Apps
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_SWA_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          action: 'upload'
          app_location: '/'
          output_location: '.vitepress/dist'
          skip_app_build: true

4. Draft Release Workflow

For automated deployment when dev requests complete:

yaml
# .github/workflows/draft-release.yml
name: Draft Release Deploy

on:
  issues:
    types: [labeled]

jobs:
  deploy-draft:
    if: github.event.label.name == 'draft-release'
    runs-on: ubuntu-latest
    
    steps:
      - name: Parse Issue Body
        id: parse
        uses: actions/github-script@v7
        with:
          script: |
            const body = context.payload.issue.body
            const resourceId = body.match(/<!-- DCS_DEV_SWA_RESOURCE_ID: (.+) -->/)?.[1]
            const requestId = body.match(/<!-- DCS_REQUEST_ID: (.+) -->/)?.[1]
            
            if (!resourceId) {
              core.setFailed('No dev SWA resource ID found')
              return
            }
            
            core.setOutput('resource_id', resourceId)
            core.setOutput('request_id', requestId)
            
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.issue.milestone && format('release/{0}', github.event.issue.milestone.title) || 'main' }}
          
      - name: Setup and Build
        # ... build steps ...
        
      - name: Deploy to Dev SWA
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_SWA_TOKEN }}
          action: 'upload'
          
      - name: Update DCS Status
        run: |
          curl -X PATCH "${{ secrets.DCS_SERVER_URL }}/api/development-requests/${{ steps.parse.outputs.request_id }}/status" \
            -H "Authorization: Bearer ${{ secrets.DCS_API_TOKEN }}" \
            -H "Content-Type: application/json" \
            -d '{"status": "deployed", "environment": "draft"}'

Branch Protection

For main branch:

  • ✅ Require pull request reviews
  • ✅ Require status checks
  • ✅ Require branches to be up to date
  • ✅ Restrict pushes (admin only)

For release/* branches:

  • ✅ Require pull request reviews
  • ✅ Require status checks
  • ⬜ Allow direct pushes for automation

Labels

Create these labels for automation:

LabelColorPurpose
dcs-automation#0052CCDCS-managed issues
development-request#5319E7User dev requests
draft-release#FBCA04Trigger draft deploy
copilot#1D76DBAssigned to Copilot

Webhooks

DCS uses GitHub webhooks for:

  • Issue status tracking
  • PR merge detection
  • Deployment notifications

Webhook Configuration

The DCS server automatically registers webhooks when a site is onboarded. If manual setup is needed:

  1. Go to repository → Settings → Webhooks
  2. Add webhook:
    • URL: https://portal.duffcloudservices.com/api/webhooks/github
    • Content type: application/json
    • Secret: (provided by DCS)
    • Events: Issues, Pull requests, Pushes

GitHub Apps

Copilot for Pull Requests

Ensure GitHub Copilot is enabled for the repository:

  1. Go to repository → Settings → Copilot
  2. Enable Copilot access
  3. Configure code review settings

DCS GitHub App (Optional)

For enhanced integration:

  1. Install the DCS GitHub App
  2. Grant repository access
  3. App handles webhooks automatically

Troubleshooting

Workflow Not Triggering

  1. Check branch protection rules
  2. Verify workflow file syntax
  3. Check for workflow disabled status
  4. Review Actions permissions

Secret Access Denied

  1. Verify secrets are added correctly
  2. Check secret names match workflow
  3. Ensure workflow has appropriate permissions

Deployment Failures

  1. Check Azure SWA token validity
  2. Verify build output path
  3. Review Azure resource permissions

Security Best Practices

Secrets

  • Never commit secrets to code
  • Rotate secrets periodically
  • Use environment-specific secrets

Permissions

  • Limit service principal scope
  • Use least-privilege access
  • Review access logs regularly

Code

  • Enable Dependabot
  • Review PR changes carefully
  • Use signed commits for production

Next Steps

Duff Cloud Services Documentation