fix: auto-trigger S3 deploy after release, fix stale doc-asset caching, clean corrupted .gitignore#2086
Merged
Merged
Conversation
โฆan .gitignore Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
pethers
July 3, 2026 17:11
View session
Contributor
Dependency Reviewโ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
pethers
approved these changes
Jul 3, 2026
Contributor
๐ธ Automated UI Screenshots๐ Screenshots Captured (8)
๐ฆ Download Screenshots๐ฅ Download all screenshots from workflow artifacts
๐ค Generated by Playwright automation |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes production documentation/site staleness by restoring an automatic S3 deploy after releases and correcting cache headers so stable-named documentation assets (e.g., TypeDoc/coverage/mochawesome) are revalidated instead of being cached as immutable.
Changes:
- Added
workflow_runauto-trigger so S3 deploy runs after โBuild, Attest and Releaseโ completes successfully, while keepingworkflow_dispatchfor manual runs. - Split S3 sync caching behavior into โimmutable for hashed build outputโ vs โmust-revalidate for stable-named docs/report assetsโ, applied to both
/and/docs/prefixes. - Replaced a corrupted, overly-broad
.gitignorewith a minimal, anchored version.
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| .github/workflows/deploy-s3.yml | Adds release-to-S3 auto-deploy trigger and refactors S3 sync cache-control policies. |
| .gitignore | Replaces corrupted ignore rules with a concise, anchored ignore set. |
Comment on lines
+10
to
+19
| # Automatically sync docs/api, generated reports and the game build to S3 | ||
| # once "Build, Attest and Release" finishes committing them to main. | ||
| # Without this, the deploy was only ever triggered manually and blacktrigram.com | ||
| # could silently go stale after a release. | ||
| # NOTE: no `branches:` filter here โ release.yml's primary trigger is a | ||
| # `v*` tag push, so `head_branch` on that workflow_run is the tag, not | ||
| # `main`. The job always checks out `ref: main` explicitly below. | ||
| workflow_run: | ||
| workflows: ["Build, Attest and Release"] | ||
| types: [completed] |
Comment on lines
62
to
75
| - name: Deploy to S3 with minimal API calls | ||
| run: | | ||
| # Optimized deployment: 6 sync operations instead of 16 | ||
| # - Hashed/static assets use --size-only (content-addressed, safe to skip by size) | ||
| # Optimized deployment: 8 sync operations instead of 16+ | ||
| # - Content-hashed assets (Vite build output) use --size-only + a 1-year | ||
| # immutable cache, since their filenames change whenever content changes. | ||
| # - Non-hashed static assets (TypeDoc/coverage/mochawesome CSS+JS, which | ||
| # keep the SAME filename across releases, e.g. docs/api/assets/style.css) | ||
| # must NOT be marked immutable, otherwise browsers/CDNs never refetch | ||
| # updated CSS/JS and the docs pages render as broken/unstyled. | ||
| # - HTML and metadata use default sync (size+mtime) to catch same-size content changes | ||
| # - Does NOT use --delete to preserve legacy URLs on S3 | ||
|
|
||
| if [ "${{ github.event.inputs.force_metadata_update }}" = "true" ]; then | ||
| # Force mode: use --exact-timestamps to force re-evaluation + metadata replace |
Comment on lines
+88
to
+111
| # 1. Sync content-hashed Vite build assets (game bundle + test-results app) with immutable cache | ||
| echo "โก [root] Syncing content-hashed assets with immutable cache..." | ||
| aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/ \ | ||
| --exclude "*" \ | ||
| --include "assets/*" \ | ||
| --include "test-results/assets/*" \ | ||
| --cache-control "public, max-age=31536000, immutable" \ | ||
| $HASHED_SYNC_FLAGS | ||
|
|
||
| # 2. Sync all other static assets (TypeDoc api docs, coverage, cypress | ||
| # mochawesome, dependency/architecture diagrams, images, etc.) with a | ||
| # short revalidating cache, since these filenames are stable across | ||
| # releases and must be refetched whenever content changes. | ||
| echo "๐ฆ [root] Syncing non-hashed static assets with revalidation cache..." | ||
| aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/ \ | ||
| --exclude ".git/*" \ | ||
| --exclude "assets/*" \ | ||
| --exclude "test-results/assets/*" \ | ||
| --exclude "*.html" \ | ||
| --exclude "*.xml" \ | ||
| --exclude "*.json" \ | ||
| --exclude "*.txt" \ | ||
| --cache-control "public, max-age=31536000, immutable" \ | ||
| $HASHED_SYNC_FLAGS | ||
| --cache-control "public, max-age=3600, must-revalidate" \ | ||
| $DOCUMENT_SYNC_FLAGS |
Comment on lines
+134
to
+154
| # 5. Sync content-hashed assets to /docs/ with immutable cache | ||
| echo "โก [/docs/] Syncing content-hashed assets with immutable cache..." | ||
| aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/docs/ \ | ||
| --exclude "*" \ | ||
| --include "assets/*" \ | ||
| --include "test-results/assets/*" \ | ||
| --cache-control "public, max-age=31536000, immutable" \ | ||
| $HASHED_SYNC_FLAGS | ||
|
|
||
| # 6. Sync all other static assets to /docs/ with revalidation cache | ||
| echo "๐ฆ [/docs/] Syncing non-hashed static assets with revalidation cache..." | ||
| aws s3 sync docs/. s3://${{ env.S3_BUCKET_NAME }}/docs/ \ | ||
| --exclude ".git/*" \ | ||
| --exclude "assets/*" \ | ||
| --exclude "test-results/assets/*" \ | ||
| --exclude "*.html" \ | ||
| --exclude "*.xml" \ | ||
| --exclude "*.json" \ | ||
| --exclude "*.txt" \ | ||
| --cache-control "public, max-age=31536000, immutable" \ | ||
| $HASHED_SYNC_FLAGS | ||
| --cache-control "public, max-age=3600, must-revalidate" \ | ||
| $DOCUMENT_SYNC_FLAGS |
Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Contributor
๐ธ Automated UI Screenshots๐ Screenshots Captured (8)
๐ฆ Download Screenshots๐ฅ Download all screenshots from workflow artifacts
๐ค Generated by Playwright automation |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://blacktrigram.com/docs/api/was rendering without content/CSS. Root cause was a combination of a manual-only deploy trigger and an incorrect long-lived cache policy on non-hashed documentation assets, compounded by a corrupted.gitignore.Findings
deploy-s3.ymlwasworkflow_dispatch-only, so docs/reports committed tomainbyrelease.ymlwere never actually synced to the production S3 bucket unless someone manually ran "Deploy" โ production could silently go stale indefinitely.Cache-Control: immutable, max-age=1yrto all non-html/xml/json/txt files, including non-content-hashed assets (docs/api/assets/style.css,docs/coverage/*.css|js,docs/cypress/mochawesome/assets/*). These filenames never change across releases, so browsers/CDN would never refetch updated CSS/JS โ this is what produced the "broken/unstyled"docs/apipage..gitignorehad ~5700 lines of an accidentally-committed literalnode_modules/dist/coveragefile-path dump (from a recent merge), including an unanchored baretest-results.xmlpattern that could silently exclude a regenerated report file from future commits.typedoc.jsonwas verified correct (out: docs/api,cleanOutputDir: true,githubPages: true) โ no changes needed there.Changes
deploy-s3.ymlworkflow_runtrigger firing after "Build, Attest and Release" completes (kept manualworkflow_dispatchfor on-demand runs), gated onconclusion == 'success'.ref: mainso the deploy always picks up the docs/reports the release just committed, regardless of whether the triggering event was a branch push or a tag push.assets/*,test-results/assets/*) โ 1-year immutable cache./docs/prefix..gitignoredocs/**remains fully trackable and root-levelnode_modules/,dist/,build/,coverage/,lib/,cypress/results|videos|screenshotsare still correctly ignored.Notes / caveats
GithubWorkFlowRole) may need to permit theworkflow_runevent's subject claim if it was previously scoped only toworkflow_dispatchโ this can't be verified from the repository alone and should be checked in AWS.