Deployment
Partner Documentation
Deploy your DCS-integrated site to Azure Static Web Apps.
Deployment Overview
DCS uses a staged deployment model:
Code Push → Build → Deploy to Dev → Review → Deploy to ProductionEnvironments
| Environment | Purpose | Trigger |
|---|---|---|
| Development | Preview changes | Push to release branch |
| Draft | PR previews | Pull request |
| Production | Live site | Manual approval |
Automated Deployment
Push to Development
When you push to a release branch:
- GitHub Actions triggers
- Site builds
- Deploys to development environment
- Portal shows "Preview Available"
Draft Deployments
For development requests:
- Copilot creates PR
- PR preview deploys automatically
- Stakeholders can review
- Approval triggers dev deployment
Production Deployment
- Review changes in development
- Click "Approve for Production" in portal
- Release branch merges to main
- Production deploys automatically
- Version tag created
GitHub Actions Workflows
Basic Deployment
yaml
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches:
- main
- 'release/**'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- 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
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: trueEnvironment-Specific Deployment
yaml
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches:
- main
- 'release/**'
jobs:
build:
runs-on: ubuntu-latest
outputs:
environment: ${{ steps.determine-env.outputs.environment }}
steps:
- uses: actions/checkout@v4
- name: Determine environment
id: determine-env
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "environment=production" >> $GITHUB_OUTPUT
else
echo "environment=development" >> $GITHUB_OUTPUT
fi
- name: Setup and build
# ... build steps ...
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: site
path: .vitepress/dist
deploy-dev:
needs: build
if: needs.build.outputs.environment == 'development'
runs-on: ubuntu-latest
environment: development
steps:
- uses: actions/download-artifact@v4
with:
name: site
path: dist
- name: Deploy to development
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_SWA_DEV_TOKEN }}
action: 'upload'
app_location: 'dist'
skip_app_build: true
deploy-prod:
needs: build
if: needs.build.outputs.environment == 'production'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@v4
with:
name: site
path: dist
- name: Deploy to production
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_SWA_PROD_TOKEN }}
action: 'upload'
app_location: 'dist'
skip_app_build: truePR Preview Deployment
yaml
# .github/workflows/preview.yml
name: PR Preview
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
# ... build steps ...
- name: Deploy preview
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'
- name: Comment preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🚀 Preview deployed! URL: https://preview-${{ github.event.pull_request.number }}.azurestaticapps.net'
})Build Configuration
VitePress Build
json
{
"scripts": {
"build": "vitepress build docs",
"build:prod": "NODE_ENV=production vitepress build docs"
}
}Environment Variables
yaml
- name: Build
run: pnpm build
env:
# Required
VITE_DCS_API: ${{ secrets.VITE_DCS_API }}
VITE_SITE_ID: ${{ secrets.VITE_SITE_ID }}
# Optional
VITE_ANALYTICS_ID: ${{ secrets.ANALYTICS_ID }}
NODE_ENV: productionAzure Static Web Apps
Resource Configuration
bash
# Create development SWA
az staticwebapp create \
--name my-site-dev \
--resource-group my-resource-group \
--location eastus2 \
--sku Free \
--branch release/1.0.0 \
--source https://github.com/org/my-site
# Create production SWA
az staticwebapp create \
--name my-site-prod \
--resource-group my-resource-group \
--location eastus2 \
--sku Standard \
--branch main \
--source https://github.com/org/my-siteCustom Domains
bash
# Add custom domain
az staticwebapp hostname set \
--name my-site-prod \
--hostname www.mysite.com
# Verify domain
az staticwebapp hostname show \
--name my-site-prod \
--hostname www.mysite.comstaticwebapp.config.json
json
{
"navigationFallback": {
"rewrite": "/index.html",
"exclude": [
"/images/*",
"/fonts/*",
"/*.ico",
"/*.xml"
]
},
"routes": [
{
"route": "/api/*",
"rewrite": "/api/{*}"
}
],
"responseOverrides": {
"404": {
"rewrite": "/404.html"
}
},
"globalHeaders": {
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
}
}Rollback
Via Portal
- Go to Site → Revisions
- Find the version to rollback to
- Click "Rollback"
- Confirm
Via GitHub
bash
# Revert the problematic commit
git revert HEAD
git push origin mainVia Azure CLI
bash
# List builds
az staticwebapp build list \
--name my-site-prod
# Rollback to specific build
az staticwebapp environment delete \
--name my-site-prod \
--environment-name previewMonitoring Deployments
GitHub Actions
Monitor workflows at:
https://github.com/org/repo/actionsAzure Portal
Monitor deployments in Azure Portal:
- Static Web Apps → Your App → Deployment History
DCS Portal
The portal shows:
- Current version
- Deployment status
- Last deployment time
- Environment URLs
Troubleshooting
Build Failures
- Check workflow logs
- Verify environment variables
- Test build locally:
pnpm build - Check for missing dependencies
Deployment Failures
- Verify SWA token is valid
- Check output directory path
- Verify file size limits (< 250MB total)
- Check for unsupported file types
Preview Not Working
- Ensure PR previews are enabled
- Check for workflow permissions
- Verify branch protection rules
Custom Domain Issues
- Verify DNS configuration
- Wait for DNS propagation (up to 48 hours)
- Check SSL certificate status
- Verify domain ownership
Best Practices
1. Use Environments
Separate secrets and approvals by environment:
yaml
jobs:
deploy-prod:
environment: production
# Requires manual approval2. Artifact Caching
yaml
- name: Cache dependencies
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}3. Health Checks
Add a health check after deployment:
yaml
- name: Health check
run: |
response=$(curl -s -o /dev/null -w "%{http_code}" https://mysite.com)
if [ "$response" != "200" ]; then
echo "Health check failed"
exit 1
fi4. Deployment Notifications
yaml
- name: Notify on success
if: success()
uses: slackapi/slack-github-action@v1
with:
payload: |
{"text": "✅ Deployment successful: ${{ github.ref }}"}Next Steps
- Release Management — Version control
- GitHub Setup — Repository configuration
- Performance — Monitor deployed site
