Skip to content

fix(deploy): force-upload Mermaid runtime to S3 + add pre/post-deploy guards#2681

Merged
pethers merged 1 commit into
mainfrom
copilot/fix-mermaid-loading-issues
May 22, 2026
Merged

fix(deploy): force-upload Mermaid runtime to S3 + add pre/post-deploy guards#2681
pethers merged 1 commit into
mainfrom
copilot/fix-mermaid-loading-issues

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 22, 2026

Articles embedding Mermaid diagrams (e.g. 2026-05-22-committee-reports-en.html) render blank with:

mermaid-init.mjs:56 [mermaid-init] Failed to load Mermaid:
TypeError: Failed to fetch dynamically imported module:
  https://riksdagsmonitor.com/js/lib/mermaid/mermaid.esm.min.mjs

Root cause

Browser attributes the failure to the top-level URL, but the actual 4xx is on the entry module's nested static imports:

URL Status
/js/lib/mermaid/mermaid.esm.min.mjs (entry) 200
/js/lib/mermaid/chunks/mermaid.esm.min/chunk-*.mjs (~80 files) 403

Verified against deploy run 26294355929: copy-vendor-mermaid.ts stages 82 chunks into js/, cp -r js/* dist/js/ copies them into dist/, minify-dist.ts correctly skips js/lib/mermaid — but scripts/deploy-s3.sh's per-type aws s3 sync --include '*.mjs' --size-only pass uploaded zero .mjs files despite the chunks being absent from S3. The subsequent --delete --size-only orphan pass also uploaded nothing. Reproducing the exact sync decision in the sandbox without AWS creds is non-trivial, so the fix is defensive rather than a filter tweak.

Changes

  • scripts/deploy-s3.sh — unconditional aws s3 cp --recursive pass for dist/js/lib/mermaid/*.mjs between per-type sync and orphan cleanup. cp doesn't size-compare, so the chunks are guaranteed to upload regardless of what sync decides. Same application/javascript + public, max-age=31536000, immutable headers as the per-type sync, so cache behavior is unchanged.

    aws s3 cp "$SRC/js/lib/mermaid" "$BUCKET/js/lib/mermaid" \
      --recursive --exclude '*' --include '*.mjs' \
      --no-guess-mime-type --content-type 'application/javascript' \
      --cache-control 'public, max-age=31536000, immutable'
  • .github/workflows/deploy-s3.yml — two guards so a recurrence fails the workflow instead of silently shipping:

    • Pre-deploy assert (after cp -r js/* dist/js/): entry exists and chunks dir has ≥50 .mjs files.
    • Post-deploy probe (after CloudFront invalidation): HEAD the entry and the first staged chunk against the S3 bucket URL directly (bypasses CloudFront so a stale cache can't mask a real miss); any non-200 fails the run.

Runtime payload (~2.6 MB, 82 chunks) only changes on Mermaid version bumps, so the always-upload cost is negligible vs. the cost of articles silently rendering without diagrams.

… guards

`aws s3 sync --include '*.mjs' --size-only` was silently skipping the
deeply-nested chunk files under `dist/js/lib/mermaid/chunks/mermaid.esm.min/`,
leaving CloudFront serving 403s for ~80 chunks while the entry module
`mermaid.esm.min.mjs` returned 200. Browsers then fail the whole module
graph with `Failed to fetch dynamically imported module: …mermaid.esm.min.mjs`
(error attributed to the parent module), so every article with Mermaid
diagrams renders without them.

Fix is defensive:

1. scripts/deploy-s3.sh: add unconditional `aws s3 cp --recursive` pass
   for `dist/js/lib/mermaid/*.mjs` with explicit `application/javascript`
   content-type and the same long-lived immutable cache-control as the
   per-type sync. Placed AFTER per-type sync and BEFORE orphan cleanup
   so headers stick and cleanup sees the keys as in-sync.

2. .github/workflows/deploy-s3.yml: assert ≥50 chunks staged in
   `dist/js/lib/mermaid/chunks/mermaid.esm.min/` BEFORE deploy (fails
   fast on a broken vendor copy), and HEAD-probe the entry + first
   chunk on S3 (direct, bypassing CloudFront) AFTER deploy so a
   recurrence is caught before the next nightly news-* run publishes
   articles that won't render.

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copilot AI requested a review from pethers May 22, 2026 15:36
@github-actions github-actions Bot added workflow GitHub Actions workflows ci-cd CI/CD pipeline changes deployment Deployment configuration refactor Code refactoring size-m Medium change (50-250 lines) labels May 22, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🏷️ Automatic Labeling Summary

This PR has been automatically labeled based on the files changed and PR metadata.

Applied Labels: workflow,ci-cd,deployment,refactor,size-m

Label Categories

  • 🗳️ Content: news, dashboard, visualization, intelligence
  • 💻 Technology: html-css, javascript, workflow, security
  • 📊 Data: cia-data, riksdag-data, data-pipeline, schema
  • 🌍 I18n: i18n, translation, rtl
  • 🔒 ISMS: isms, iso-27001, nist-csf, cis-controls
  • 🏗️ Infrastructure: ci-cd, deployment, performance, monitoring
  • 🔄 Quality: testing, accessibility, documentation, refactor
  • 🤖 AI: agent, skill, agentic-workflow

For more information, see .github/labeler.yml.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

@pethers pethers marked this pull request as ready for review May 22, 2026 15:38
Copilot AI review requested due to automatic review settings May 22, 2026 15:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@pethers pethers merged commit bb66090 into main May 22, 2026
13 checks passed
@pethers pethers deleted the copilot/fix-mermaid-loading-issues branch May 22, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-cd CI/CD pipeline changes deployment Deployment configuration refactor Code refactoring size-m Medium change (50-250 lines) workflow GitHub Actions workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants