Skip to content

fix: restore worker.ts in cloudflare templates and add template sync#478

Merged
ascorbic merged 7 commits intomainfrom
fix/cloudflare-template-worker-and-sync
Apr 12, 2026
Merged

fix: restore worker.ts in cloudflare templates and add template sync#478
ascorbic merged 7 commits intomainfrom
fix/cloudflare-template-worker-and-sync

Conversation

@ascorbic
Copy link
Copy Markdown
Collaborator

What does this PR do?

Cloudflare templates were missing src/worker.ts and the "main" field in wrangler.jsonc, so the custom worker entrypoint (Astro handler + PluginBridge re-export) was never used. Also adds worker-configuration.d.ts to the three cloudflare templates that were missing it.

Adds scripts/sync-templates-repo.mjs to automatically sync templates to the standalone emdash-cms/templates repo with resolved dependency versions (workspace:*^0.1.1, catalog: → real versions). A new sync-templates workflow runs after changesets publishes or on manual dispatch.

Also fixes sync-cloudflare-templates.sh to use rsync with --exclude=worker.ts so it preserves cloudflare-specific files when copying src/ from base templates.

Type of change

  • Bug fix
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation and pnpm locale:extract has been run (if applicable)
  • I have added a changeset (if this PR changes a published package)
  • New features link to an approved Discussion: https://github.com/emdash-cms/emdash/discussions/...

AI-generated code disclosure

  • This PR includes AI-generated code

Screenshots / test output

Dry-run output of sync-templates-repo.mjs --dry-run --local ../emdash-templates:

Workspace packages:
  emdash = 0.1.1
  @emdash-cms/cloudflare = 0.1.1
  ...

Syncing blank
  Transformed package.json
Syncing blog
  Transformed package.json
...
143 files changed, 806 insertions(+), 8701 deletions(-)

Dry run — not pushing.

Cloudflare templates were missing src/worker.ts and the "main" field in
wrangler.jsonc, so the custom worker entrypoint (Astro handler +
PluginBridge re-export) was never used. Also adds worker-configuration.d.ts
to the three templates that were missing it.

Adds scripts/sync-templates-repo.mjs to sync templates to the standalone
emdash-cms/templates repo with resolved dependency versions. A new
sync-templates workflow runs after publish or on manual dispatch.

Also fixes sync-cloudflare-templates.sh to use rsync with --exclude so
it preserves worker.ts when copying src/ from base templates.
Copilot AI review requested due to automatic review settings April 12, 2026 07:14
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 12, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
emdash-playground 48954b5 Apr 12 2026, 10:36 AM

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 12, 2026

⚠️ No Changeset found

Latest commit: 48954b5

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

Scope check

This PR changes 36,495 lines across 15 files. Large PRs are harder to review and more likely to be closed without review.

If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs.

See CONTRIBUTING.md for contribution guidelines.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 12, 2026

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@478

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@478

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@478

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@478

emdash

npm i https://pkg.pr.new/emdash@478

create-emdash

npm i https://pkg.pr.new/create-emdash@478

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@478

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@478

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@478

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@478

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@478

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@478

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@478

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@478

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@478

commit: 48954b5

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restores Cloudflare templates’ custom worker entrypoint usage and introduces automation to sync templates into the standalone emdash-cms/templates repository after releases.

Changes:

  • Add main: ./src/worker.ts to Cloudflare template wrangler.jsonc files and restore src/worker.ts entrypoints that re-export PluginBridge.
  • Add scripts/sync-templates-repo.mjs plus a reusable workflow to sync templates to emdash-cms/templates and open a PR.
  • Update sync-cloudflare-templates.sh to rsync directories while preserving Cloudflare-specific worker.ts.

Reviewed changes

Copilot reviewed 12 out of 15 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
templates/starter-cloudflare/wrangler.jsonc Points Wrangler to the intended Cloudflare worker entrypoint.
templates/starter-cloudflare/src/worker.ts Restores the worker entrypoint (Astro handler + PluginBridge re-export).
templates/portfolio-cloudflare/wrangler.jsonc Points Wrangler to the intended Cloudflare worker entrypoint.
templates/portfolio-cloudflare/src/worker.ts Restores the worker entrypoint (Astro handler + PluginBridge re-export).
templates/marketing-cloudflare/wrangler.jsonc Points Wrangler to the intended Cloudflare worker entrypoint.
templates/marketing-cloudflare/src/worker.ts Restores the worker entrypoint (Astro handler + PluginBridge re-export).
templates/blog-cloudflare/wrangler.jsonc Points Wrangler to the intended Cloudflare worker entrypoint.
templates/blog-cloudflare/src/worker.ts Restores the worker entrypoint (Astro handler + PluginBridge re-export).
scripts/sync-templates-repo.mjs New script to clone/sync templates repo, resolve dependency protocols, and open a PR.
scripts/sync-cloudflare-templates.sh Switches to rsync for directories with an exclude to preserve Cloudflare-specific files.
.github/workflows/sync-templates.yml Adds a reusable workflow to run the sync script with an app token.
.github/workflows/release.yml Triggers template sync workflow after a successful publish.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Use gh repo clone instead of embedding token in clone URL
- Use execFileSync with arg array for gh pr create (no shell injection)
- Use -B and --force-with-lease for re-runnable branch push
- Guard against non-directory dest in sync-cloudflare-templates.sh
- Replace all execSync/run() calls with execFileSync arg arrays so
  interpolated values (version strings from package.json) never pass
  through a shell
- Add ref guard (github.ref == refs/heads/main) to sync-templates
  workflow so it can't be dispatched from arbitrary branches
- Wrap post-clone logic in try/finally to clean up temp dir on error
@github-actions
Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 15 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +255 to +259
git(["checkout", "-B", branch], targetDir);
git(["add", "-A"], targetDir);
git(["commit", "-m", `chore: sync templates from emdash v${emdashVersion}`], targetDir);
git(["push", "--force-with-lease", "-u", "origin", branch], targetDir);

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git push will likely fail in CI because the repo is cloned via gh repo clone but git isn’t configured with credentials for the generated app token. Other workflows in this repo set up authenticated pushes via GIT_ASKPASS/x-access-token (see .github/workflows/auto-format.yml:96-107). Consider configuring git auth before pushing (e.g., gh auth setup-git for the provided GH_TOKEN, or an askpass/remote approach that doesn’t leak the token).

Copilot uses AI. Check for mistakes.

- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow runs a Node script but doesn’t set up/pin a Node version (unlike other workflows such as .github/workflows/ci.yml:25-30). To avoid runner-image drift breaking the sync (and to match repo conventions), add an explicit actions/setup-node step (and optionally cache/lock the version).

Suggested change
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

Copilot uses AI. Check for mistakes.
Comment on lines 70 to +76
if [[ -L "$dest" ]]; then
rm "$dest"
elif [[ -d "$dest" ]]; then
rm -rf "$dest"
elif [[ -f "$dest" ]]; then
rm "$dest"
fi

# Copy the item
if [[ -d "$src" ]]; then
cp -r "$src" "$dest"
echo " Copied directory: $item"
else
cp "$src" "$dest"
echo " Copied file: $item"
fi
cp "$src" "$dest"
echo " Copied file: $item"
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the file-copy branch, if $dest exists as a directory (e.g., from a previous run or template structure change), it won’t be removed and cp will fail because it can’t overwrite a directory. Consider handling the -d "$dest" case here (e.g., remove it recursively) before copying the file to make the sync script robust.

Copilot uses AI. Check for mistakes.
- Run gh auth setup-git after clone so git push works with GH_TOKEN
- Pin Node version in sync-templates workflow
- Handle dest-is-directory in file copy branch of sync-cloudflare-templates.sh
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 15 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3 to +23
on:
workflow_dispatch:
workflow_call:

jobs:
sync:
name: Sync templates to emdash-cms/templates
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Generate token
id: app-token
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
repositories: templates
owner: emdash-cms

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sync-templates.yml is used as a reusable workflow (workflow_call) from release.yml, but it doesn’t declare the secrets it expects. In reusable workflows, secrets.* are only available if they’re declared under on.workflow_call.secrets, so secrets.APP_ID / secrets.APP_PRIVATE_KEY will be empty and token generation will fail. Declare these secrets (and mark required) under workflow_call.

Copilot uses AI. Check for mistakes.
Comment on lines +161 to +184
const args = process.argv.slice(2);
const dryRun = args.includes("--dry-run");
const localIdx = args.indexOf("--local");
const localPath = localIdx !== -1 ? args[localIdx + 1] : null;

const catalog = parseCatalog();
const workspace = collectWorkspaceVersions();

console.log("Workspace packages:");
for (const [name, version] of Object.entries(workspace)) {
console.log(` ${name} = ${String(version)}`);
}
console.log("");

let targetDir;
let tempDir;

if (localPath) {
targetDir = resolve(localPath);
if (!existsSync(join(targetDir, ".git"))) {
console.error(`Error: ${targetDir} is not a git repository`);
process.exit(1);
}
} else {
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--local parsing doesn’t validate that a path argument is actually provided. If someone runs node scripts/sync-templates-repo.mjs --local (or passes another flag next), localPath becomes undefined and the script falls back to cloning/pushing unexpectedly. Add an explicit check when --local is present to require a non-empty path (and exit with a helpful error).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 15 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


git(["checkout", "-B", branch], targetDir);
git(["add", "-A"], targetDir);
git(["commit", "-m", `chore: sync templates from emdash v${emdashVersion}`], targetDir);
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git push --force-with-lease will fail if the sync branch already exists on the remote (e.g., rerunning the workflow before the previous PR is merged), because the clone doesn’t have an up-to-date remote-tracking ref for that branch. Consider either fetching the remote branch first (so the lease can be evaluated), using a unique branch name per run, or explicitly handling the “branch already exists” case so reruns update the existing branch reliably.

Suggested change
git(["commit", "-m", `chore: sync templates from emdash v${emdashVersion}`], targetDir);
git(["commit", "-m", `chore: sync templates from emdash v${emdashVersion}`], targetDir);
let remoteBranchExists = false;
try {
git(["ls-remote", "--exit-code", "--heads", "origin", branch], targetDir);
remoteBranchExists = true;
} catch {
remoteBranchExists = false;
}
if (remoteBranchExists) {
git(
[
"fetch",
"origin",
`refs/heads/${branch}:refs/remotes/origin/${branch}`,
],
targetDir,
);
}

Copilot uses AI. Check for mistakes.
Comment on lines +276 to +291
const prUrl = execFileSync(
"gh",
[
"pr",
"create",
"--repo",
REPO,
"--title",
`chore: sync templates from emdash v${emdashVersion}`,
"--body",
prBody,
],
{ encoding: "utf8", stdio: "pipe", cwd: targetDir },
).trim();

console.log(`PR: ${prUrl}`);
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gh pr create will error if a PR already exists for this branch (common when the sync job is rerun). Consider detecting an existing PR for the head branch (e.g., gh pr view / gh pr list --head) and reusing its URL instead of failing the workflow.

Suggested change
const prUrl = execFileSync(
"gh",
[
"pr",
"create",
"--repo",
REPO,
"--title",
`chore: sync templates from emdash v${emdashVersion}`,
"--body",
prBody,
],
{ encoding: "utf8", stdio: "pipe", cwd: targetDir },
).trim();
console.log(`PR: ${prUrl}`);
const existingPrs = JSON.parse(
execFileSync(
"gh",
[
"pr",
"list",
"--repo",
REPO,
"--head",
branch,
"--state",
"open",
"--json",
"url",
],
{ encoding: "utf8", stdio: "pipe", cwd: targetDir },
),
);
const prUrl =
existingPrs[0]?.url ??
execFileSync(
"gh",
[
"pr",
"create",
"--repo",
REPO,
"--title",
`chore: sync templates from emdash v${emdashVersion}`,
"--body",
prBody,
],
{ encoding: "utf8", stdio: "pipe", cwd: targetDir },
).trim();
console.log(existingPrs[0] ? `PR already exists: ${prUrl}` : `PR: ${prUrl}`);

Copilot uses AI. Check for mistakes.
- Fetch remote branch before force-with-lease so the lease has a ref
- Check for existing open PR before creating a new one
@ascorbic ascorbic merged commit 1dc19b0 into main Apr 12, 2026
29 checks passed
@ascorbic ascorbic deleted the fix/cloudflare-template-worker-and-sync branch April 12, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants