fix(ops): repair the tinystudio.in release lane - stop failing every main merge while the Pages token is missing - #111
Conversation
…very main merge while the Pages token is missing The deploy lane has been failing every main push since PR #81 landed: without CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID the publish step throws after a full npm ci + check + prepare cycle (~6 minutes), leaving the live site permanently stale on the June-20 bundle. PR #85 attempted to gate the publish step on the secrets, but its step-level `if: ${{ secrets... != '' }}` conditions are invalid - the secrets context is not available in step-level if conditions (context availability table), so the workflow failed validation and never ran. Hoist both secrets into the job-level env (where the secrets context is allowed) and gate every expensive step with `if: env.X != ''`: - Dormant (no secrets): seconds-long green run printing the exact one-time provisioning steps as a warning annotation. - Active (both secrets set): unchanged fail-closed publish + live verification on every main merge; the moment the token is provisioned the lane deploys without any code change.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
📝 WalkthroughWalkthroughThe public site workflow now exits successfully with provisioning instructions when Cloudflare credentials are missing. When both credentials exist, it runs the setup, validation, bundle, and publish-and-verify steps. ChangesPublic site deployment
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 25f521694b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| env: | ||
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | ||
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} |
There was a problem hiding this comment.
Keep the Pages token scoped to the publishing step
When the credentials are provisioned, this job-level env exposes the Pages:Edit token to every action and command in the job—including checkout, setup-node, the repository test suite, and bundle preparation—whereas the previous workflow exposed it only to the publisher. Any compromised action or newly merged test code could read the token and use it to replace the production Pages deployment; derive a non-secret readiness output in a narrowly scoped step, then continue passing the actual credentials only to the publish step.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/deploy-public-site.yml:
- Around line 44-46: Move CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID out of
the job-level env and define the raw secrets only within the “Publish to
Cloudflare Pages and verify live” step. Keep job scope limited to non-secret
presence flags, ensuring checkout, checks, tests, and bundle preparation cannot
access the credentials.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f95f9d1c-5d3a-4fe1-bf90-a17d8fba152e
📒 Files selected for processing (1)
.github/workflows/deploy-public-site.yml
| env: | ||
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | ||
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
workflow=.github/workflows/deploy-public-site.yml
# Expect: raw Cloudflare credentials appear only in the publish step's env map.
rg -n -C 3 'CLOUDFLARE_API_TOKEN|CLOUDFLARE_ACCOUNT_ID|HAS_CLOUDFLARE' "$workflow"Repository: nish3451/tinystudio-in
Length of output: 3164
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/deploy-public-site.yml
printf '%s\n' '--- Cloudflare credential references ---'
rg -n -C 4 'CLOUDFLARE_API_TOKEN|CLOUDFLARE_ACCOUNT_ID|secrets\.' .github/workflows scripts package.json
printf '%s\n' '--- publish script environment access ---'
rg -n -C 5 'process\.env|CLOUDFLARE|deploy|prepare-only' scripts/publish-public-site.mjsRepository: nish3451/tinystudio-in
Length of output: 19418
🌐 Web query:
GitHub Actions workflow syntax job-level env step-level env secrets context if condition env context documentation
💡 Result:
In GitHub Actions, environment variables (env) and secrets can be used throughout your workflows using specific syntax and scoping rules [1][2][3]. Env Scope and Precedence You can define environment variables at the workflow, job, or step level [2][4]. When the same variable name is defined at multiple levels, the most specific definition overrides the others [2][5]. - Step-level env overrides job-level and workflow-level env [2][5]. - Job-level env overrides workflow-level env [2][5]. - Workflow-level env acts as a default for all jobs [5][4]. Context Syntax - Env context: Use ${{ env.VAR_NAME }} to access environment variables in your workflow expressions (such as if conditions) [1][6]. - Secrets context: Use ${{ secrets.SECRET_NAME }} to access your repository secrets [1][3]. - Expressions: Use ${{... }} syntax to evaluate expressions [7]. In if conditional clauses, the ${{ }} syntax is optional [7]. If Conditions and Secrets Secrets cannot be directly referenced in if conditional statements for security reasons [3]. To use a secret in a conditional: 1. Map the secret to a job-level environment variable [3]. 2. Reference that environment variable in your step's if conditional using the env context [6][3]. Example: jobs: example-job: runs-on: ubuntu-latest env: # Map secret to a job-level env var MY_SECRET_VAR: ${{ secrets.MY_SECRET }} steps: - name: Conditional step # Access the env var via the env context if: ${{ env.MY_SECRET_VAR!= '' }} run: echo "Secret is available"
Citations:
- 1: https://docs.github.com/en/actions/reference/workflows-and-actions/contexts
- 2: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax?use_case=
- 3: https://docs.github.com/actions/security-guides/using-secrets-in-github-actions
- 4: https://www.codegenes.net/blog/how-to-read-environment-variables-in-env-section-of-github-action-workflow/
- 5: https://latchkey.dev/learn/github-actions/gha-env-scope-workflow-job-step
- 6: https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-variables
- 7: https://docs.github.com/en/actions/concepts/workflows-and-actions/expressions
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import json
import re
from pathlib import Path
workflow = Path(".github/workflows/deploy-public-site.yml").read_text()
package = json.loads(Path("package.json").read_text())
for name in ("CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"):
matches = [
(i + 1, line)
for i, line in enumerate(workflow.splitlines())
if name in line and "secrets." in line
]
print(f"{name}:")
for line_no, line in matches:
print(f" line {line_no}: {line.strip()}")
print("\nRelevant package scripts:")
for name, command in package.get("scripts", {}).items():
if name == "check" or "publish-public-site" in command:
print(f" {name}: {command}")
print("\nCurrent workflow commands:")
for i, line in enumerate(workflow.splitlines(), 1):
if re.search(r"\brun:\s*(npm run check|node scripts/publish-public-site\.mjs)", line):
print(f" line {i}: {line.strip()}")
PYRepository: nish3451/tinystudio-in
Length of output: 803
Restrict Cloudflare credentials to the publish step.
The job-level env exposes both credentials to actions/checkout@v7, npm run check (npm test), and bundle preparation. Keep only non-secret presence flags at job scope. Define the raw credentials in Publish to Cloudflare Pages and verify live.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/deploy-public-site.yml around lines 44 - 46, Move
CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID out of the job-level env and
define the raw secrets only within the “Publish to Cloudflare Pages and verify
live” step. Keep job scope limited to non-secret presence flags, ensuring
checkout, checks, tests, and bundle preparation cannot access the credentials.
What this repairs
The tinystudio.in production deploy path has been red on every main merge since the release lane landed (PR #81). Merged public fixes keep piling up on main while the live site stays on the June-20 bundle.
Root cause (two layers)
CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDare not set in repo secrets, so the publish step throws after a fullnpm ci+npm run check+ bundle-prepare cycle. Every main push burned ~6m20s on the self-hosted runner and ended red: https://github.com/nish3451/tinystudio-in/actions/runs/31496974636if: ${{ secrets.X != '' }}at step level. Thesecretscontext is not available in step-levelif:conditions (GitHub context-availability table allows onlygithub, needs, strategy, matrix, job, runner, env, vars, steps, inputs). The workflow failed validation ("workflow file issue", 0s run: https://github.com/nish3451/tinystudio-in/actions/runs/31490699530), so the lane stayed broken.The fix
Hoist both secrets into the job-level
env(wheresecretsis allowed) and gate every step withif: env.X != ''(envis allowed in stepif:):::warning::annotation. No more 6-minute red failures on every merge; the nightlylive-site-check.ymlremains the loud staleness alarm.npm run checkgate, filtered bundle prepare, wrangler direct upload, live verification — runs automatically on the next main merge. No code change needed once the token is provisioned.Validated
live-site-check.yml→ 5/9 failures proving the site is stale (unknown URLs return HTTP 200,/404.htmlserves the homepage): https://github.com/nish3451/tinystudio-in/actions/runs/31557743215Remaining one-time step (cannot be done from the repo or this VPS)
A Cloudflare Pages:Edit API token for account
f670a698e17bf160c8e4679823e68916must be created in the dashboard and set as a repo secret:gh secret set CLOUDFLARE_API_TOKEN -R nish3451/tinystudio-ingh secret set CLOUDFLARE_ACCOUNT_ID -R nish3451/tinystudio-in -b f670a698e17bf160c8e4679823e68916Deploy public site(or wait for the next main merge)Verified unavailable on this VPS: the fleet Workers token (
fleet-console/cf.env) has no Pages permission and no token-management permission (API errors 10000/9109), and no other Cloudflare credential exists on the VPS or the self-hosted runners.Supersedes the unmerged attempt in PR #85.
Summary by CodeRabbit