GitHub Action Deployment
This repository uses .github/workflows/deploy.yml for pull-request validation and production deployment. The workflow is designed for a static SPA that depends on a private photo source repository during build time.
Triggers
The workflow runs on:
- pull requests targeting
main - pushes to
mainthat touch app, package, script, workflow, or project configuration paths workflow_dispatchrepository_dispatchwith typephotos-updated, sent byJackyhq/Photography-Photos
Pull requests use a pr-<number> concurrency group and cancel stale runs. Non-PR deployments use the deploy concurrency group.
Pull-Request Validation
The validate job is intentionally independent of private media and deployment credentials. It sets fixture-specific storage variables, then:
- Checks out this source repository.
- Installs pnpm
10.19.0, Node.js24, and frozen workspace dependencies. - Runs
pnpm run fixtures:photosto create public synthetic photos underapps/web/public/__fixtures/photos. - Runs
pnpm run photos:standardizeagainst that fixture. - Runs
pnpm run build:manifest -- --force --strict. - Runs
pnpm run lint:checkandpnpm run type-check. - Runs
pnpm run test:coverageso unit tests and coverage gates share one command. - Builds the documentation site and production web app.
- Checks the bundle budget, which also requires the current build output.
- Installs the Chromium headless shell and runs the full desktop/mobile suite with
PLAYWRIGHT_PRODUCTION=true pnpm run test:e2e.
PR validation never checks out Jackyhq/Photography-Photos, reads deployment secrets, pushes photo changes, syncs R2, or mirrors deployment output.
Production Validation
The build-and-deploy job first verifies that every required deployment secret is present. It then checks out Jackyhq/Photography-Photos into ./photos, rejects every symlink outside the nested .git directory, and runs the real-photo pipeline:
- Install frozen dependencies and run
pnpm run lint:check. - Run
pnpm run photos:standardize. - Run
pnpm run build:manifest -- --strict. - Run
pnpm run type-checkandpnpm run test:coverage. - Build the documentation site and production web app.
- Check the bundle budget and web output.
- Prepare the Google sitemap alias and README preview image.
- Run
PLAYWRIGHT_PRODUCTION=true pnpm run test:e2e:smokeagainst the real-photo build.
The web build uses AFILMORY_SKIP_MANIFEST_PRECHECK=true because the strict manifest build has already completed explicitly.
The deployment browser suite selects @smoke tests: normal gallery click and viewer close, public manifest and no-JavaScript photo/video pages, and missing-route metadata. These run on desktop and mobile. They use bundled thumbnails or video posters and do not require newly uploaded R2 originals, because R2 synchronization happens after validation.
The full fixture suite retains keyboard navigation, focus, filtering, sharing, language switching, Live Photo behavior, original-load failures, and metadata history regression checks. Smoke tests run there too. Lint, types, unit coverage, and the docs build remain in production validation because direct pushes, manual runs, and photo dispatches cannot assume the deployed source was validated by a PR.
Playwright media preferences are configured through use.contextOptions. The shared gallery helper checks the browser's reduced-motion preference before a single normal click; it does not retry clicks or wait for an arbitrary animation timeout.
Deployment-Only Steps
Pushes to main, manual runs, and photo-repository dispatches run the build-and-deploy job. External writes start only after every validation step above succeeds. The job then:
- Commits standardized photo changes back to
Jackyhq/Photography-Photoswith[skip dispatch]. - Syncs
./photosto Cloudflare R2 under thephotos/prefix. - Checks out
Jackyhq/Photography-Weband mirrorsapps/web/dist/into it. - Commits and pushes deployment output only when the mirrored repository changed.
Required Secrets
The source repository requires:
PHOTO_REPO_TOKEN: fine-grained PAT with Contents access toJackyhq/Photography-Photos.DEPLOY_REPO_TOKEN: token used to push static output toJackyhq/Photography-Web.CLOUDFLARE_R2_ACCESS_KEY_ID: Cloudflare R2 S3 API access key.CLOUDFLARE_R2_SECRET_ACCESS_KEY: Cloudflare R2 S3 API secret key.CLOUDFLARE_R2_ENDPOINT: R2 S3 API endpoint, such ashttps://<account_id>.r2.cloudflarestorage.com.CLOUDFLARE_R2_BUCKET: bucket name only, such asjackywhq.
The private photo repository requires MAIN_REPO_DISPATCH_TOKEN, a token that can send repository_dispatch events to Jackyhq/Photography.
Cloudflare R2 Sync
The workflow separates bucket name, object prefix, and public URL:
CLOUDFLARE_R2_BUCKETis the bucket name only.R2_PHOTOS_PREFIX=photosmakes the upload targets3://<bucket>/photos/.CLOUDFLARE_R2_ENDPOINTis the S3 API endpoint.https://photos3.jackyw.cn/photos/is the public URL used in the manifest.
The sync command uses aws s3 sync ./photos "s3://${R2_BUCKET}/${R2_PHOTOS_PREFIX}/" --size-only --delete --no-follow-symlinks.
It excludes:
.git/.github/.gitignoreREADME.mdincoming/
--size-only avoids re-uploading unchanged photos when GitHub Actions creates a fresh checkout with new local timestamps. If a same-path replacement has a different file body but the exact same byte size, delete the affected object from R2 or change the file name before redeploying.
Permissions
The workflow defaults to contents: read. The deploy job expands permissions for production deployment:
contents: write
Output Targets
The primary build output is:
apps/web/dist/
The deploy job mirrors that output to:
Jackyhq/Photography-Web
Photo source files are not tracked in this public repository. The public site loads original photos from https://photos3.jackyw.cn/photos/, backed by Cloudflare R2.
Notes
photos/incoming/is excluded from the manifest and R2 sync.- Photo-repository commits made by CI include
[skip dispatch]to avoid deployment loops. pnpm run buildnormally runs the web precheck; CI setsAFILMORY_SKIP_MANIFEST_PRECHECK=trueafter explicitly running the builder.- Keep workflow documentation synchronized with
.github/workflows/deploy.yml.
| Created At | |
| Last Modified |