Skip to content

Deployment

Partner Documentation

DCS-integrated sites deploy to Azure Static Web Apps through a workflow that dcs init generates for you. Deployment authenticates with OpenID Connect (OIDC) — there is no long-lived Static Web App token stored in the repository.

Deployment Overview

Push to release/** → Build → Deploy to Preview → Review
Push to master     → Build → Deploy to Production

Environments

BranchEnvironmentTrigger
release/**PreviewPush to a release branch
masterProductionPush to master (after review)

You can also run the workflow manually from the GitHub Actions tab (workflow_dispatch).

The Generated Workflow

dcs init writes .github/workflows/site-deploy.yml. You do not hand-write or hand-maintain it. On each push it:

  1. Determines the environment from the branch (master → Production, otherwise Preview).
  2. Reads site identity and Azure config from .dcs/site.yaml.
  3. Logs in to Azure with OIDC (azure/login@v2) — no stored secret.
  4. Exchanges the OIDC-obtained Azure access token with the DCS API for a short-lived SWA deployment token (masked, never persisted).
  5. Builds the site and deploys with Azure/static-web-apps-deploy@v1.

The load-bearing OIDC parts:

yaml
permissions:
  contents: read
  id-token: write          # required for OIDC — replaces the deployment secret

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Azure login via OIDC
        uses: azure/login@v2
        with:
          client-id: ${{ vars.AZURE_CLIENT_ID }}
          tenant-id: ${{ vars.AZURE_TENANT_ID }}
          subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

      - name: Get deployment token
        id: tokens
        run: |
          ACCESS_TOKEN=$(az account get-access-token --resource "api://<dcs-app-id>" --query accessToken -o tsv)
          SWA_TOKEN=$(curl -s -X POST "$PORTAL_API_URL/api/v1/sites/deployment-tokens" \
            -H "Authorization: Bearer $ACCESS_TOKEN" \
            -H "Content-Type: application/json" \
            -d "{\"siteSlug\": \"$SITE_SLUG\"}" | jq -r .swaToken)
          echo "::add-mask::$SWA_TOKEN"
          echo "swa_token=$SWA_TOKEN" >> "$GITHUB_OUTPUT"

      - name: Deploy to Azure Static Web Apps
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ steps.tokens.outputs.swa_token }}
          action: upload
          skip_app_build: true

The three Azure identifiers are non-secret; keep them in .dcs/site.yaml (committed) or repository Variables — not Secrets. See GitHub Setup for the federated-credential setup.

Deployment-Complete Webhook

After a deployment finishes, GitHub Actions notifies the DCS server so the portal can update version, status, and release state for the site. The server exposes a single deployment webhook for this:

http
POST /api/v1/webhooks/github/deployment-complete

It is authenticated with an API token (not a public endpoint). The generated workflow and DCS onboarding handle this wiring — you do not configure it by hand.

Static Web App Configuration

staticwebapp.config.json controls routing and headers for the deployed site:

json
{
  "navigationFallback": {
    "rewrite": "/index.html",
    "exclude": ["/images/*", "/fonts/*", "/*.ico", "/*.xml"]
  },
  "responseOverrides": {
    "404": { "rewrite": "/404.html" }
  },
  "globalHeaders": {
    "X-Frame-Options": "DENY",
    "X-Content-Type-Options": "nosniff",
    "Referrer-Policy": "strict-origin-when-cross-origin"
  }
}

Rollback

Via Portal

  1. Go to Site → Revisions
  2. Find the version to roll back to
  3. Roll back and confirm

Via GitHub

bash
# Revert the problematic commit and let the workflow redeploy
git revert HEAD
git push

Monitoring Deployments

  • GitHub Actions — the repository's Actions tab shows each deploy run.
  • Azure Portal — Static Web Apps → your app → Deployment History.
  • DCS Portal — shows current version, deployment status, and environment URLs for the site.

Troubleshooting

OIDC Login Denied

  1. Confirm the workflow has permissions: id-token: write
  2. Verify the app registration has a federated credential whose subject matches the branch being deployed
  3. Check that AZURE_CLIENT_ID / AZURE_TENANT_ID / AZURE_SUBSCRIPTION_ID (Variables or .dcs/site.yaml) are correct

Deployment Failures

  1. Confirm the DCS API returned a deployment token (check the token step logs)
  2. Verify the build output path
  3. Test the build locally: pnpm build

Preview Not Updating

  1. Confirm you pushed to a release/** branch
  2. Check the Actions run for errors
  3. Verify the site total is within the Static Web Apps size limit

Next Steps