Skip to content

feat(previews): deploy full-site PR previews to staging S3 instead of gh-pages#7481

Draft
jstirnaman wants to merge 5 commits into
masterfrom
claude/pr-preview-issues-3fked8
Draft

feat(previews): deploy full-site PR previews to staging S3 instead of gh-pages#7481
jstirnaman wants to merge 5 commits into
masterfrom
claude/pr-preview-issues-3fked8

Conversation

@jstirnaman

Copy link
Copy Markdown
Contributor

Summary

Addresses #7430, #6674 (and the broader bug class discussed with several other closed/open PR Preview issues).

The PR Preview workflow already paid for a full Hugo build, then pruned it to a hand-picked subset of pages (prepare-preview-files.js) and deployed to gh-pages. That pruning step was the root cause of a recurring bug class (missing pages, blank pages, broken shared-content links) — and gh-pages can't hold full-site deploys anyway, since cleanup only removes the working tree, not git history, so every push's payload accumulates forever.

This PR replaces that with a full-site deploy to the existing staging bucket (test2.docs.influxdata.com) under pr-preview/pr-<N>/, built with --environment production for production parity (real GA/GTM, fingerprinted+SRI JS, minification, the same __tests__/test_only exclusions production applies).

What changed

  1. layouts/partials/base-path-offset.html (new) — replaces the static, gh-pages-specific prPreviewPathOffset config param with a value computed from site.BaseURL's path depth, so product/version detection works under any subdirectory baseURL. config/pr-preview/ deleted.
  2. deploy/edge.js — fixes two latent bugs in the Lambda@Edge origin-request rewriter that would otherwise break previews on the staging distribution: a trailing-slash redirect hardcoded to docs.influxdata.com (bounces staging visitors to production), and unanchored archive/version redirects that would hijack /pr-preview/pr-<N>/... subpaths. Added deploy/__tests__/edge.test.mjs covering both, plus a regression check against the existing redirect chain.
  3. scripts/deploy-staging.sh — adds -ignore='^pr-preview/' so a manual root staging deploy can never delete a live PR preview (verified against the pinned s3deploy v2.11.0 source: -force doesn't override -ignore).
  4. pr-preview.yml / cleanup-stale-previews.yml / detect-preview-pages.js / preview-comment.js / doc-review.yml — the workflow restructure: full-site deploy via s3deploy (OIDC auth, incremental sync, .s3deploy.yml header parity) scoped to the PR's own S3 prefix, explicit CloudFront invalidation, no more "needs author input" gate. detect-preview-pages.js is repurposed from a deploy gate into a comment-link generator. prepare-preview-files.js deleted. Also fixed a latent bug in the stale-preview cleanup's PR-open check (JSON.stringify emits unquoted numbers, so the old quote-matching grep never matched and every preview was being deleted weekly regardless of PR state — replaced with a jq membership check).
  5. DocsDOCS-DEPLOYING.md, DOCS-TESTING.md, two agent skills updated; .github/PREVIEW_SETUP.md (gh-pages-specific) deleted.

CI checks that need __tests__ fixtures or test_only content (Cypress, render checks) are unaffected — they build their own copy of the site in their own job with the testing/development environment and never consume this deployed preview.

⚠️ Prerequisites before this workflow can run

This PR ships the code, but the preview/cleanup jobs will fail until an AWS admin completes one-time setup:

  1. GitHub OIDC provider trusted by the AWS account (if not already present for this org).
  2. IAM role assumable by this repo's pull_request and refs/heads/master workflows, scoped to the pr-preview/* object prefix in the staging bucket only (s3:GetObject/PutObject/DeleteObject, s3:ListBucket conditioned on that prefix, s3:GetBucketLocation, cloudfront:CreateInvalidation on the staging distribution only). Full trust + permissions policy JSON available on request — not included here since it needs the real account/bucket/distribution IDs filled in.
  3. Repo secrets/variables: AWS_PR_PREVIEW_ROLE_ARN, STAGING_BUCKET, STAGING_CF_DISTRIBUTION_ID, AWS_REGION.
  4. Lambda@Edge redeploy: the updated deploy/edge.js needs to be deployed to the staging distribution's Lambda@Edge association (publish version + update association) before previews will resolve correctly. Worth confirming whether that distribution forwards the viewer Host header — affects the host-aware redirect logic (falls back to a relative Location if not, so it degrades safely either way).
  5. Optional: an S3 lifecycle rule on the pr-preview/ prefix (e.g. expire after 60 days) as a backstop if cleanup ever fails to remove a preview.
  6. Please double-check the pin: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2 — I resolved this SHA via a single web fetch and couldn't independently cross-verify it (the action's repo is outside my GitHub MCP scope in this session). Worth a second look before merge.

Until 1–4 are done, pr-preview.yml will fail on Configure AWS credentials. That's expected — hence draft.

Known parity gaps

Same as before this change, not introduced by it: AI discovery artifacts, llms-full.txt, and the Rust markdown converter are still skipped in preview builds. The preview's HTML also advertises Markdown-twin alternates that 404, since twin generation isn't run for previews.

Checklist

  • Signed the InfluxData CLA (if necessary)
  • Rebased/mergeable
  • Local build passes (npx hugo --quiet)
  • AWS OIDC role + secrets configured (see Prerequisites above)
  • Updated edge.js deployed to the staging Lambda@Edge association
  • aws-actions/configure-aws-credentials SHA pin double-checked

Suggested reviewers

Infrastructure/CI change (workflows, deploy/, scripts/, a Hugo partial, and docs) — no single product content team applies. influxdata/docs-team is auto-assigned via CODEOWNERS; please loop in whoever owns the staging AWS account for the prerequisites above.


Generated by Claude Code

claude added 5 commits July 15, 2026 12:31
Replace the static prPreviewPathOffset param (hardcoded to 3, tied to
the gh-pages URL depth) with a partial that derives the offset from
site.BaseURL's path depth at build time. This lets PR previews build
under any subdirectory baseURL (e.g. a shorter S3/CloudFront prefix)
without a per-environment config file.
Two bugs in the Lambda@Edge origin-request rewriter would break
full-site PR previews on the staging distribution:

- The trailing-slash redirect hardcoded https://docs.influxdata.com,
  so any preview URL requested without a trailing slash bounced
  visitors off the staging host onto production. Now it prefers the
  actual viewer Host header when it's a docs domain, falling back to
  a relative Location otherwise (origin-request events don't reliably
  forward Host, per docs-website.yml's origin config).
- The unanchored product/version/archive redirects (e.g.
  /influxdb/v1.x/ -> archive.docs.influxdata.com) would fire on
  /pr-preview/pr-<N>/... subpaths and hijack preview URLs to
  unrelated domains. Requests under /pr-preview/ now bypass that
  whole block while keeping the same trailing-slash and index.html
  handling every other path gets.

Add deploy/package.json (type: commonjs) so this CommonJS-only file
(deployed by pasting into the Lambda console, per docs-website.yml)
can be required from a node:test suite despite the repo's root
"type": "module". Add deploy/__tests__/edge.test.mjs covering both
fixes plus a regression check against the pre-existing archive/version
redirect chain.
Full-site PR previews will be deployed to the staging bucket under
pr-preview/pr-<N>/. Root staging deploys use s3deploy's -force, which
diffs and deletes anything under the bucket not present locally --
without a guard, a manual staging deploy would wipe every live preview.

-ignore='^pr-preview/' excludes matching remote keys from that
deletion pass (verified against s3deploy's source: it strips the
bucket path before matching, so remote objects under the prefix are
never enqueued for delete, and -force only affects the upload
comparison, not this exclusion).

Also quote $AWS_ACCESS_KEY_ID/$AWS_SECRET_KEY per shellcheck SC2086,
required to pass the pre-commit hook on this file.
… gh-pages

Replaces the selective gh-pages preview deploy with a full-site deploy
to the existing staging bucket (test2.docs.influxdata.com) under
pr-preview/pr-<N>/. This removes the pruning layer that caused a
recurring bug class (missing/blank preview pages, broken shared-content
links) and gh-pages can't hold full-site deploys anyway (git history
retains every build forever).

- pr-preview.yml: build with -e production (not pr-preview) for full
  production parity -- fingerprinted/SRI JS, minification, real GA/GTM,
  and the __tests__/test_only exclusions production applies. Deploy via
  s3deploy (OIDC auth, incremental sync, .s3deploy.yml header parity)
  scoped to the PR's own prefix, then an explicit CloudFront
  invalidation of that prefix. Deploy is now unconditional once the job
  runs -- no more "needs author input" gate or 50-page selective cap.
- detect-preview-pages.js: repurposed from a deploy gate into a
  comment-link generator. It still maps changed content files and
  PR-description URLs to a page list, but that list only becomes deep
  links in the sticky comment -- it no longer decides what gets
  deployed (the whole site does, every time).
- preview-comment.js: drops the "needs input" pending state (moot --
  nothing needs author-specified pages anymore) and renders the changed
  page list as links into the full preview instead of a plain list.
- prepare-preview-files.js: deleted. Selective staging-directory
  copying is unnecessary when the full build is deployed as-is.
- cleanup-stale-previews.yml: reconciles S3 prefixes against open PRs
  instead of gh-pages directories. Also fixes a latent bug in the
  PR-number membership check: JSON.stringify() emits unquoted numbers
  (e.g. [1,42]), so the old grep -q "\"$PR_NUM\"" pattern never matched
  and every preview was deleted weekly regardless of PR state. Replaced
  with a jq membership check.
- doc-review.yml: updates the three hardcoded gh-pages preview URLs the
  visual-review check waits on and links to.
- build-docs-site/action.yml: drops pr-preview from the hugo-environment
  description now that no workflow passes it.

Root staging deploys still go to the bucket root and are guarded
against ever deleting these prefixes (see the previous
scripts/deploy-staging.sh commit). AWS OIDC role, S3 bucket/CloudFront
secrets, and a Lambda@Edge redeploy of the previous edge.js commit are
required before this workflow can run -- see the PR description.
Updates PR Preview documentation to match the new deploy model: full
site to staging S3 under pr-preview/pr-<N>/, production-parity build,
AWS OIDC setup steps, and known parity gaps. Deletes
.github/PREVIEW_SETUP.md (gh-pages-specific setup guide, superseded by
the AWS Setup section in DOCS-DEPLOYING.md). Updates the two agent
skills that described the old selective-deploy/GitHub-Pages behavior.
@github-actions

Copy link
Copy Markdown
Contributor

Vale Style Check Results

Metric Count
Errors 0
Warnings 0

Check 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