Skip to content

docs(site): add prod SWA + OIDC deploy + /docs base path#2

Merged
takyyon merged 1 commit into
mainfrom
feat/prod-docs-swa-and-afd
May 31, 2026
Merged

docs(site): add prod SWA + OIDC deploy + /docs base path#2
takyyon merged 1 commit into
mainfrom
feat/prod-docs-swa-and-afd

Conversation

@takyyon
Copy link
Copy Markdown
Contributor

@takyyon takyyon commented May 30, 2026

Summary

Stands up a production Azure Static Web App for the docs site and reworks the
deploy pipeline so it actually runs end-to-end again. After this PR plus a
small amount of out-of-band setup (see Post-merge follow-ups below), the
docs will be served from https://auto.azure.com/docs/ behind Azure Front
Door.

Closes the issue where the docs link in the portal pointed at the raw
canary SWA hostname (https://lemon-mud-…azurestaticapps.net).

What changed

New prod infrastructure (already provisioned)

Canary (existing) Prod (new)
Resource group otto-docs-canary-rg otto-docs-rg
Static Web App otto-docs-canary-swa otto-docs-swa
Hostname lemon-mud-0e10bdd1e.7.azurestaticapps.net kind-river-0d9e9ac1e.7.azurestaticapps.net
Public URL (same as hostname) https://auto.azure.com/docs/ via AFD
SKU Free Free

Both run in westus2 in the existing Logic Apps subscription. The new RG
is tagged environment=prod project=otto-docs.

Workflow rewrite — /.github/workflows/docs-site-deploy.yml

Replaces a workflow that was failing on every run since May 27
("deployment_token was not provided", because the secret it referenced
didn't exist) with a 4-job pipeline that authenticates via OIDC and
fetches deployment tokens just-in-time:

  • build — single Astro build, uploaded once as an artifact.
  • deploy_canary — auto on push to main, on in-repo PRs (preview
    environment), and on manual dispatch with target=canary (restricted
    to main to match federated cred coverage).
  • deploy_prodworkflow_dispatch only with target=prod. Gated
    by a docs-prod GitHub environment so prod never deploys without a
    reviewer's click.
  • close_pr_preview — tears down preview environments when same-repo
    PRs close.

Fork PRs build but don't deploy (GitHub doesn't pass secrets to fork
workflows — by design). A preflight step fails fast with a clear error
message if the required Azure secrets aren't set.

Astro reconfigured for /docs base path

To serve cleanly behind an AFD route, the site is now built with:

  • base: '/docs' — Astro emits links and asset URLs under /docs/….
  • outDir: './dist/docs' — file paths on disk match URL paths in HTML.
  • A small remark plugin (scripts/remarkBasePrefix.mjs) prepends
    /docs to plain markdown links so content stays portable.
  • A postbuild script (scripts/postbuild.mjs) hoists
    staticwebapp.config.json back to the dist root (where SWA requires
    it) after astro build.

The canary hostname keeps working because staticwebapp.config.json
adds / → /docs/ and /docs → /docs/ 301 redirects, plus a
navigationFallback rewrite to /docs/404.html.

Content

  • Replaced otto.azure.com with auto.azure.com in 5 doc pages
    (introduction.md, setup.md, permissions.md, workflows.md, and
    inline references). The otto.azure.com domain is being decommissioned.

INFRA.md

Fully rewritten with the canary + prod resource map, the OIDC auth flow,
disaster-recovery az commands for re-provisioning everything from
scratch, and the one-time repo configuration that has to happen out of
band.

How auth works now (no stored deploy tokens)

GitHub Actions OIDC token
        │
        ▼
azure/login@v2 (federated credential trust)
        │
        ▼
Azure access token for "Otto E2E GitHub Actions" SP
        │
        ▼
az staticwebapp secrets list  ← JIT-fetch deploy token (masked in logs)
        │
        ▼
Azure/static-web-apps-deploy@v1 (upload)

Federated credentials trusted by the SP (already configured):

Subject Used by
repo:Azure/Logic-Apps-Automation:ref:refs/heads/main push to main + manual canary
repo:Azure/Logic-Apps-Automation:pull_request in-repo PR previews
repo:Azure/Logic-Apps-Automation:environment:docs-prod gated prod deploys

To rotate a deployment token (or after a suspected leak), run
az staticwebapp secrets reset-api-key … — no workflow or secret change
is needed.

Files changed

  • .github/workflows/docs-site-deploy.yml — rewritten
  • docs-site/astro.config.mjsbase, outDir, remark plugin
  • docs-site/package.json — build now runs postbuild script; added unist-util-visit
  • docs-site/scripts/postbuild.mjs (new)
  • docs-site/scripts/remarkBasePrefix.mjs (new)
  • docs-site/staticwebapp.config.json — moved out of public/; new redirects + headers
  • docs-site/INFRA.md — fully rewritten
  • docs-site/README.md — updated tree + URL refs
  • docs-site/src/components/Video.astro — fixed a stale JSDoc example
  • docs-site/src/content/docs/index.mdx — hero link: frontmatter prefixed
  • docs-site/src/content/docs/demos/index.mdxLinkCard uses BASE_URL
  • 4 content pages — otto.azure.comauto.azure.com

Testing

  • npm ci — clean install.
  • npm run check — 0 errors / 0 warnings / 0 hints across 6 Astro files.
  • npm run build — 21 pages built, 5.5 MB output.
  • Verified asset URLs (/docs/_astro/*), favicon (/docs/favicon.svg),
    markdown links, and LinkCard hrefs all resolve to real files in the
    dist/ tree.
  • actionlint — clean on the new workflow.

Stand up a production Azure Static Web App for the docs site, served at
https://auto.azure.com/docs/ through Azure Front Door, and rework the
deploy pipeline so it actually runs end-to-end again.

What changed:

- New prod resources: otto-docs-rg / otto-docs-swa (Free SKU, westus2),
  fronted by AFD profile otto-portal-afd. The canary SWA stays where it
  is (otto-docs-canary-swa / lemon-mud-…azurestaticapps.net) and continues
  to deploy on every push to main.

- Workflow rewrite (.github/workflows/docs-site-deploy.yml):
  - Single build job uploads the artifact; deploy_canary, deploy_prod,
    and close_pr_preview consume it.
  - All Azure auth flows through GitHub OIDC + a federated credential on
    the Otto E2E GitHub Actions SP. No long-lived deployment tokens are
    stored in this repo; the workflow JIT-fetches the SWA deploy token
    via 'az staticwebapp secrets list' on every run.
  - deploy_prod is workflow_dispatch-only and gated by the docs-prod
    GitHub environment (required reviewers).
  - PRs from forks build but skip deploy (no secret access by design);
    same-repo PRs get a free preview environment that's torn down on
    close.
  - Preflight check fails fast with a clear error if AZURE_CLIENT_ID /
    AZURE_TENANT_ID / AZURE_SUBSCRIPTION_ID are missing.
  - Concurrency groups normalize push and manual canary to the same
    'canary' group so they cancel each other; prod runs in its own group
    and is never auto-cancelled.

- Astro site reconfigured for the /docs URL prefix:
  - base: '/docs' + outDir: './dist/docs' so URLs in HTML and file paths
    on disk both line up with the AFD route.
  - scripts/postbuild.mjs hoists staticwebapp.config.json back to dist/
    root (where SWA requires it) after astro build.
  - scripts/remarkBasePrefix.mjs prepends /docs to plain markdown links
    so content stays portable.
  - staticwebapp.config.json gets / → /docs/ and /docs → /docs/ 301
    redirects; navigationFallback rewrites to /docs/404.html.

- Content: replaced otto.azure.com with auto.azure.com in 5 pages now
  that the new portal domain is live.

- INFRA.md fully rewritten with the canary + prod resource map, the
  OIDC auth flow, and the one-time repo / Azure setup commands needed
  for disaster recovery.

Post-merge follow-ups (done out of band):
  1. Repo admin sets AZURE_CLIENT_ID / AZURE_TENANT_ID /
     AZURE_SUBSCRIPTION_ID secrets and creates the docs-prod
     environment with required reviewers.
  2. Manual workflow_dispatch with target=prod does the first prod
     deploy.
  3. AFD route /docs and /docs/* added on otto-portal-afd pointing to
     the new prod SWA origin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@takyyon takyyon merged commit bbb42ac into main May 31, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants