feat(infra): add Render staging + refactor CI/CD workflows#65
Conversation
- Add experiments.baseUrl: "/thumbcode" for GitHub Pages subdirectory - Inject no-cache meta tags into HTML files for staging environment - Fixes Expo app loading issue on GitHub Pages deployment Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Changes ### Deployment Infrastructure - Add render.yaml for Render.com staging deployment - Configure security headers (X-Frame-Options, X-Content-Type-Options) - Set up SPA routing with proper cache headers - Remove baseUrl from app.json (Render serves from root) ### Version Management (DRY) - Add .nvmrc with Node 22 LTS - Add packageManager field to package.json (pnpm@10.11.0) - Update setup-thumbcode action to read from .nvmrc - Remove hardcoded version numbers from workflows ### Workflow Refactoring - Refactor ci.yml with latest action SHAs and E2E job - Create cd.yml for EAS builds and deployments - Update deploy-gh-pages.yml for documentation only - Pin all GitHub Actions to latest SHAs: - checkout@v6.0.2 - setup-node@v6 - pnpm/action-setup@v4 - expo/expo-github-action@v8 - codecov-action@v5 - coverallsapp@v2 - sonarcloud-github-action@v5 ### CI/CD Structure - ci.yml: lint, typecheck, test, build, e2e - cd.yml: EAS updates, Android/iOS builds, store submissions - deploy-gh-pages.yml: documentation with TypeDoc Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
📝 WalkthroughWalkthroughReplaces Node/pnpm version sourcing to use Changes
Sequence Diagram(s)sequenceDiagram
participant GHA as GitHub Actions
participant Repo as Repository
participant EAS as Expo EAS
participant StoreA as Google Play
participant StoreB as Apple App Store
rect rgba(100,150,200,0.5)
note over GHA,Repo: CD workflow — checkout & setup
end
GHA->>Repo: checkout
GHA->>GHA: setup-thumbcode (node from .nvmrc, pnpm from package.json)
GHA->>EAS: trigger build / create preview update
EAS-->>GHA: build artifact / update result
alt platform includes Android & profile=production
GHA->>StoreA: submit Android build
StoreA-->>GHA: submission response
end
alt platform includes iOS & profile=production
GHA->>StoreB: submit iOS build
StoreB-->>GHA: submission response
end
sequenceDiagram
participant GHA as GitHub Actions
participant Runner as CI Runner
participant Artifact as Web Build Artifact
participant Playwright as Playwright
rect rgba(150,100,200,0.5)
note over GHA,Playwright: CI E2E Web flow
end
GHA->>Runner: build-web job -> produce artifact
Runner->>Artifact: upload artifact
GHA->>Runner: e2e-web job downloads artifact
Runner->>Playwright: install browsers
Runner->>Playwright: run tests against artifact
alt tests fail
Playwright-->>GHA: upload report
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @.github/workflows/cd.yml:
- Around line 41-43: The eas-update job is unreachable because its conditional
if: github.event_name == 'pull_request' doesn't match the workflow triggers;
update the workflow triggers (the top-level on: block) to include pull_request,
or alternatively remove/adjust the job's if condition to match existing triggers
(push/workflow_dispatch). Locate the eas-update job and the on: triggers in the
same file, then either add pull_request to the on: block or change the job's if
to a condition that matches push/workflow_dispatch so the job can run.
- Around line 202-205: The Android submission step "Submit to Play Store" is
missing the required EXPO_ANDROID_SERVICE_ACCOUNT_KEY_PATH env var needed by
eas.json; update the Android submit step that runs "eas submit --platform
android --latest --non-interactive" to include an env block setting
EXPO_ANDROID_SERVICE_ACCOUNT_KEY_PATH: ${{
secrets.EXPO_ANDROID_SERVICE_ACCOUNT_KEY_PATH }} so the Play Store submission
has the service account key available.
In `@render.yaml`:
- Around line 22-32: The Cache-Control rules overlap because the general rule
"path: /*" can match asset requests like "/assets/*" and "/_expo/*"; reorder the
rules so the specific patterns ("/assets/*" and "/_expo/*") appear before the
general "/*" entry or replace the general rule with a root-only pattern for HTML
(e.g., a root-level or explicit HTML path) to ensure static assets keep "public,
max-age=31536000, immutable" while HTML uses "no-cache, no-store,
must-revalidate".
🧹 Nitpick comments (4)
render.yaml (1)
11-25: Consider adding HSTS and CSP security headers.The current security headers are good. For a staging environment, consider adding:
Strict-Transport-Security(HSTS) to enforce HTTPSContent-Security-Policyfor XSS protection🔒 Suggested additional security headers
- path: /* name: Referrer-Policy value: strict-origin-when-cross-origin + - path: /* + name: Strict-Transport-Security + value: max-age=31536000; includeSubDomains.github/workflows/deploy-gh-pages.yml (2)
46-49: Silent failure in TypeDoc generation may hide issues.Using
|| truesuppresses all TypeDoc errors, meaning the workflow will succeed even if API documentation generation completely fails. Consider logging a warning or checking if output was generated.🔧 Suggested improvement to detect TypeDoc failures
- name: Generate API documentation with TypeDoc run: | pnpm add -D typedoc typedoc-plugin-markdown - npx typedoc --out docs-dist/api src/index.ts --plugin typedoc-plugin-markdown || true + if ! npx typedoc --out docs-dist/api src/index.ts --plugin typedoc-plugin-markdown; then + echo "::warning::TypeDoc generation failed - API docs may be missing" + fi
113-116: Markdown links won't render as HTML on GitHub Pages.Links like
./README.mdwill prompt users to download raw markdown files rather than viewing rendered content. Consider using a static site generator (e.g., Jekyll which GitHub Pages supports natively) or converting markdown to HTML.If you want a quick fix without adding a build tool, you could link to the GitHub repo's rendered markdown instead:
- <li><a href="./README.md">README</a></li> - <li><a href="./CLAUDE.md">Agent Playbook (CLAUDE.md)</a></li> - <li><a href="./DECISIONS.md">Technical Decisions</a></li> + <li><a href="https://github.com/agentic-dev-library/thumbcode/blob/main/README.md">README</a></li> + <li><a href="https://github.com/agentic-dev-library/thumbcode/blob/main/CLAUDE.md">Agent Playbook (CLAUDE.md)</a></li> + <li><a href="https://github.com/agentic-dev-library/thumbcode/blob/main/DECISIONS.md">Technical Decisions</a></li>Alternatively, consider enabling Jekyll or adding a markdown-to-HTML conversion step.
.github/workflows/cd.yml (1)
51-57: Consider using environment variable for secret check.The current pattern works, but using
${{ secrets.EXPO_TOKEN }}directly in the shell expands the secret value. A cleaner pattern uses an environment variable, which GitHub Actions will mask regardless.♻️ Alternative pattern
- name: Check for EXPO_TOKEN + env: + EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} run: | - if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then + if [ -z "$EXPO_TOKEN" ]; then echo "EXPO_TOKEN secret is required for EAS operations" echo "Learn more: https://docs.expo.dev/eas-update/github-actions" exit 1 fi
## Fixes from code review ### Critical - Fix EXPO_TOKEN secret check to use env block pattern (prevents secret leakage) ### Major - Add pull_request trigger to cd.yml so eas-update job will run - Add path filters to conserve EAS build minutes (src/**, app.json, eas.json) - Add typedoc and typedoc-plugin-markdown to devDependencies - Fix render.yaml: add corepack enable for packageManager support - Remove runtime typedoc installation in deploy-gh-pages.yml ### Minor - Pin exact Node version in .nvmrc (22.12.0) - Add HSTS header (Strict-Transport-Security) - Add Permissions-Policy header for additional security Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…precedence CodeRabbit review fixes: - Add EXPO_ANDROID_SERVICE_ACCOUNT_KEY_PATH env var to submit-android job matching the iOS submission pattern - Reorder render.yaml Cache-Control headers: specific paths (/assets/*, /_expo/*) now come before general /* to avoid nondeterministic matching Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CodeRabbit Review - Fixes Applied ✅Addressed the remaining review comments in commit e332f68: 1. Android submission credentials (cd.yml:222)Added 2. render.yaml header precedence (render.yaml:38)Reordered Cache-Control headers so specific paths ( Both threads can now be resolved. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @.github/workflows/cd.yml:
- Around line 11-17: The pull_request paths filter currently lists 'src/**',
'app.json', and 'eas.json' which means changes to package.json won't trigger the
PR preview; update the pull_request.paths array to include 'package.json' so
dependency or script changes trigger the workflow (locate the pull_request ->
paths block in .github/workflows/cd.yml and add 'package.json' to that list).
- Around line 62-88: The "Check for EXPO_TOKEN" step currently exits 0 but does
not prevent later steps ("Setup Expo and EAS", "Create preview update") from
running; change the check to set a step output (e.g., has_token) or set
EXPO_TOKEN at the job env level and then add conditional guards (if:
steps.<check-step-id>.outputs.has_token == 'true' or if: env.EXPO_TOKEN != '')
to the subsequent steps so they are skipped when the token is missing; update
the "Check for EXPO_TOKEN" step to emit the chosen output (true/false) when it
detects the secret and ensure "Setup Expo and EAS" and "Create preview update"
reference that output in their if conditions.
In @.github/workflows/deploy-gh-pages.yml:
- Around line 111-114: The links in deploy-gh-pages.yml point to raw markdown
(README.md, CLAUDE.md, DECISIONS.md) which will be served unrendered; update the
workflow to either (a) add a build step that converts those markdown files to
HTML (e.g., run Jekyll build or a pandoc/markdown-to-html step) so the output
contains README.html, CLAUDE.html, DECISIONS.html (and an HTML version of the
api/ docs), or (b) change the nav links to point to the rendered pages produced
by your site generator (e.g., README.html) and ensure the deploy step publishes
the generated site folder; modify the job in deploy-gh-pages.yml that produces
the site artifact to run the converter (or jekyll build) and deploy the
generated HTML files instead of raw .md files.
♻️ Duplicate comments (1)
.github/workflows/cd.yml (1)
192-193: Add Play Store service account env for Android submit.The Play Store submission step still doesn’t supply
EXPO_ANDROID_SERVICE_ACCOUNT_KEY_PATH, whicheas.jsonexpects. This will likely fail at submit time.🛠️ Suggested fix
- name: Submit to Play Store run: eas submit --platform android --latest --non-interactive + env: + EXPO_ANDROID_SERVICE_ACCOUNT_KEY_PATH: ${{ secrets.EXPO_ANDROID_SERVICE_ACCOUNT_KEY_PATH }}
🧹 Nitpick comments (3)
.github/workflows/deploy-gh-pages.yml (2)
6-10: Consider adding path filters for TypeDoc configuration files.The path filters may miss documentation-relevant changes:
package.jsonchanges (TypeDoc version updates)tsconfig.jsonchanges (affects TypeDoc's type resolution)typedoc.jsonif a config file is added laterSuggested path filters
paths: - 'docs/**' - 'src/**/*.ts' - 'src/**/*.tsx' - '.github/workflows/deploy-gh-pages.yml' + - 'package.json' + - 'tsconfig.json' + - 'typedoc.json'
46-47: Preferpnpm execovernpxfor installed dependencies.Since
typedocis a devDependency, usingpnpm execensures the installed version is used rather than potentially downloading a different one vianpx.Suggested change
- name: Generate API documentation with TypeDoc - run: npx typedoc --out docs-dist/api src/index.ts --plugin typedoc-plugin-markdown + run: pnpm exec typedoc --out docs-dist/api src/index.ts --plugin typedoc-plugin-markdown.github/workflows/cd.yml (1)
78-82: Pineas-versionto a specific version instead oflatestfor reproducible builds.Using
latestcauses non-deterministic builds across workflow runs. While EAS CLI follows semantic versioning with breaking changes only on major version bumps (reducing surprise breakage), pinning to an explicit version (e.g.,16.18.0) ensures consistency across all jobs and makes dependency updates intentional. Updateeas-versionat lines 81, 119, 157, 189, and 218.
- Remove submit-android and submit-ios jobs (see issue #66) - Fix typedoc-plugin-markdown version (^5.0.0 → ^4.9.0) - Update pnpm-lock.yaml with corrected dependencies Current release strategy: - Web staging: Render.com (automatic via render.yaml) - Mobile builds: Download from expo.dev after EAS build - App store submissions: Pending credential configuration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Additional Fixes (b111e5b)1. App Store Submission Jobs RemovedRemoved Current Release Strategy:
2. Fixed typedoc-plugin-markdown VersionChanged from CI should now pass with the corrected lockfile. |
Use step outputs and conditionals to skip subsequent steps when EXPO_TOKEN is not configured, instead of just exiting the check step with code 0 (which doesn't stop subsequent steps). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Dependency changes should trigger EAS Update PR previews to keep previews in sync with package changes. Addresses CodeRabbit review comment. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CodeRabbit Review - Final Fixes (15edabe)1. Added
|
Re: Markdown Rendering on GitHub PagesThe remaining CodeRabbit comment about markdown files not rendering as HTML has been tracked in issue #67 (Astro SSG upgrade). This is a larger enhancement that doesn't block the current PR goals:
Ready for merge pending any final review. |
- development-builds.yml: PR builds for Android + iOS simulator - production-deploy.yml: Smart deployment with fingerprinting - Skips rebuilds when native code unchanged (OTA updates) - Parallel iOS/Android builds when needed - preview-update.yml: OTA updates for feature branches Enables full mobile CI/CD pipeline without GitHub Actions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.eas/workflows/production-deploy.yml:
- Around line 47-55: The workflow currently may skip in-progress builds because
get_android_build (the job producing needs.get_android_build.outputs.build_id)
relies on the default behavior that returns only completed builds; update the
get_android_build job configuration to include wait_for_in_progress: true if you
want the workflow to wait for any matching in-progress builds to finish and thus
ensure publish_android_update runs, otherwise document that skipping in-progress
builds is intentional; reference the get_android_build job and the
publish_android_update step when making the change so the outputs and
conditional if: ${{ needs.get_android_build.outputs.build_id }} behave as
expected.
🧹 Nitpick comments (1)
.github/workflows/cd.yml (1)
86-89: Consider pinning EAS CLI version for reproducibility.Using
eas-version: latestacross all jobs (lines 88, 127, 165) may cause unexpected behavior if EAS CLI introduces breaking changes. Consider pinning to a specific version to match the reproducibility approach used for other action SHAs.♻️ Suggested change
uses: expo/expo-github-action@c7b66a9c327a43a8fa7c0158e7f30d6040d2481e # v8 with: - eas-version: latest + eas-version: 16.x token: ${{ secrets.EXPO_TOKEN }}Also applies to: 125-128, 163-166
- Added AI coding assistant market analysis ($4.91B → $30.1B market) - Documented competitive landscape (Copilot, Cursor, Claude, etc.) - Identified ThumbCode's unique positioning (mobile-first + BYOK) - Created phased 1.0 execution roadmap - Added 2026 market trends analysis Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Link documentation pages to GitHub rendered markdown instead of raw .md files - Document intentional behavior of skipping in-progress builds in production-deploy.yml Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add EAS project ID (36e52acc-b39a-4bfa-a9dc-4a1053e87032) - Update owner from thumbcode to jbcom - Set EXPO_PUBLIC_APP_ENV=production in PR preview workflow to match EAS project slug Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Required for EAS Update PR previews in CI workflow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
🚀 Expo preview is ready!
|
Incorporates EAS project configuration from PR #65



Summary
Changes
Deployment Infrastructure
Version Management (DRY)
packageManager: "pnpm@10.11.0"Workflow Refactoring
Action SHAs Updated
actions/checkout@v6.0.2→de0fac2e4500dabe0009e67214ff5f5447ce83ddactions/setup-node@v6→6044e13b5dc448c55e2357c09f80417699197238pnpm/action-setup@v4→c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08cexpo/expo-github-action@v8→c7b66a9c327a43a8fa7c0158e7f30d6040d2481ecodecov/codecov-action@v5→671740ac38dd9b0130fbe1cec585b89eea48d3decoverallsapp/github-action@v2→5cbfd81b66ca5d10c19b062c04de0199c215fb6eSonarSource/sonarcloud-github-action@v5→ffc3010689be73b8e5ae0c57ce35968afd7909e8Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.