Skip to content

Rename server to API and enhance Alchemy integration#45

Merged
ahargunyllib merged 11 commits intomainfrom
feat/iac
Mar 31, 2026
Merged

Rename server to API and enhance Alchemy integration#45
ahargunyllib merged 11 commits intomainfrom
feat/iac

Conversation

@ahargunyllib
Copy link
Copy Markdown
Owner

@ahargunyllib ahargunyllib commented Mar 31, 2026

Description

Rename the apps/server directory to apps/api and migrate the API to use Alchemy. Update the Alchemy configuration and scripts for improved state management and environment configuration. Add a GitHub Actions workflow for API deployment, integrating necessary secrets for secure operations.

Summary by CodeRabbit

  • New Features

    • Preview deployments for pull requests with automated provisioning and teardown.
    • Added a /health endpoint returning status OK.
  • Chores

    • Added automated API deployment workflow.
    • Added example environment variables for the API.
    • Ignored local Alchemy artifacts (.alchemy).
    • Introduced an API package and removed legacy server package/config.
    • Updated linter scope and centralized dependency catalog.

@github-actions
Copy link
Copy Markdown

Preview Deployment

Commit: 8eb74f4931002d7fe993f5c0209a2d9d824449e0
Version ID: cc18c67b-170a-4782-81c6-cf4d0f932db0
Preview URL: https://cc18c67b-realm-www.ahargunyllib.workers.dev
Deployed at: 2026-03-31 01:02:53 UTC

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b8cb42a0-0c8b-422f-921a-49efb995ed44

📥 Commits

Reviewing files that changed from the base of the PR and between 1247f5d and da617c4.

📒 Files selected for processing (1)
  • apps/api/src/index.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/api/src/index.ts

📝 Walkthrough

Walkthrough

Adds a new Alchemy-backed API app with runtime and health endpoint, a GitHub Actions workflow to deploy/destroy per-PR preview stages, workspace/catalog updates to include Alchemy, moves lint override to apps/api, ignores *.alchemy files, and removes the prior apps/server Wrangler/package configuration.

Changes

Cohort / File(s) Summary
CI/CD Deployment Workflow
​.github/workflows/api-deployment.yaml
Adds a GitHub Actions workflow that deploys Alchemy preview environments on PR open/sync/reopen and destroys them on PR close; sets dynamic STAGE (pr-{PR_NUMBER} / prod), concurrency, Node 22/pnpm setup, pnpm cache, runs `pnpm dlx alchemy deploy
API App Package & Runtime
apps/api/alchemy.run.ts, apps/api/package.json, apps/api/.env.example, apps/api/src/env.ts, apps/api/src/index.ts
Introduces a new Alchemy app entrypoint exporting worker, CloudflareStateStore wiring in production, optional PR-commenting with preview URL, package metadata/scripts/deps, env placeholders (ALCHEMY_STATE_TOKEN, ALCHEMY_PASSWORD), exported Env type, and adds GET /health route.
Removed Server Config
apps/server/package.json, apps/server/wrangler.jsonc
Removes existing server package.json and Wrangler config previously used for Cloudflare/Wrangler deployment and related scripts.
Workspace, Linting & Ignore
.gitignore, biome.jsonc, package.json, pnpm-workspace.yaml
Adds *.alchemy to .gitignore, changes Biome override scope from apps/server/** to apps/api/**, introduces alchemy in pnpm catalog and updates root workspace/catalog entries (cataloged alchemy and typescript).

Sequence Diagram(s)

sequenceDiagram
    participant GH as GitHub Actions
    participant Repo as Repo (checkout & setup)
    participant PNPM as pnpm / Alchemy CLI
    participant Alchemy as Alchemy / Cloud service
    participant GH_API as GitHub API

    GH->>Repo: Trigger on PR event (opened/synchronize/reopened/closed)
    Repo->>Repo: Setup Node 22, pnpm 10.14.0, cache, install
    alt PR opened/synchronized/reopened
        Repo->>PNPM: Run `pnpm dlx alchemy deploy --stage pr-{PR_NUMBER}` (from `apps/api`)
        PNPM->>Alchemy: Create/Update preview worker (realm-api / api)
        Alchemy-->>PNPM: Return preview URL
        PNPM->>GH_API: Post/update PR comment with SHA & preview URL
        GH_API-->>GH: Comment published
    else PR closed
        Repo->>Repo: Safety check (fail if prod)
        Repo->>PNPM: Run `pnpm dlx alchemy destroy --stage pr-{PR_NUMBER}` (from `apps/api`)
        PNPM->>Alchemy: Destroy preview worker
        Alchemy-->>PNPM: Teardown confirmed
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through code to weave and pry,

Previews bloom beneath each PR sky,
Alchemy lights a transient gate,
Deploy, then tidy—preview’s fate.
A rabbit cheers the CI tie-up high.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description adequately covers the main objectives and changes. However, it lacks the related issues section, checklist completion, and additional context that the template requires. Complete the template by adding a 'Related Issues' section with issue number(s), checking off relevant checklist items, and providing additional notes about testing and validation performed.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main changes: renaming server to API and enhancing Alchemy integration, which aligns with the comprehensive refactoring shown in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/iac

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

Preview Deployment

Commit: a7d6de64969b4dc4aa82e254417470360c35ff77
Version ID: c529c704-106e-4089-8b46-c20b55022902
Preview URL: https://c529c704-realm-www.ahargunyllib.workers.dev
Deployed at: 2026-03-31 01:04:35 UTC

@github-actions
Copy link
Copy Markdown

Preview Deployment

Commit: 5264002c37c42ef7c0f9855f7599f4ad4141c3c7
Version ID: a48f070a-2ec3-4bca-8cd7-3e0b78a37652
Preview URL: https://a48f070a-realm-www.ahargunyllib.workers.dev
Deployed at: 2026-03-31 01:06:21 UTC

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (4)
apps/api/src/env.ts (1)

1-3: Empty bindings yields an empty Env type.

The worker is created with bindings: {} in alchemy.run.ts, so Env currently resolves to {}. This works as a scaffold for future bindings (KV, D1, secrets), but any code expecting actual bindings from Env will have no type information until bindings is populated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/env.ts` around lines 1 - 3, Env currently resolves to an empty
object because worker.bindings is `{}`; update the typing so consumers get
meaningful binding types by either (A) widening Env to a fallback type (e.g.,
make Env a union/extension of typeof worker.bindings with Record<string,
unknown> or Record<string, any>) or (B) declare an explicit interface for
expected bindings and intersect it with typeof worker.bindings; change the
export in apps/api/src/env.ts (the Env type) accordingly and/or add the proper
bindings object or declaration when creating `worker` in alchemy.run.ts so that
`worker.bindings` carries the intended keys for consumers to use.
apps/api/alchemy.run.ts (1)

49-49: Add guard for invalid PULL_REQUEST value.

Number(process.env.PULL_REQUEST) returns NaN if the value is not a valid numeric string, which could cause unexpected behavior when passed as issueNumber.

🛡️ Defensive improvement
 if (process.env.PULL_REQUEST) {
+  const issueNumber = Number(process.env.PULL_REQUEST);
+  if (Number.isNaN(issueNumber)) {
+    throw new Error(`Invalid PULL_REQUEST number: ${process.env.PULL_REQUEST}`);
+  }
   await GitHubComment("preview-comment", {
     owner: "ahargunyllib",
-    repository: "ahargunyllib/realm",
-    issueNumber: Number(process.env.PULL_REQUEST),
+    repository: "realm",
+    issueNumber,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/alchemy.run.ts` at line 49, Guard against invalid PULL_REQUEST by
validating the conversion used for issueNumber: replace the direct
Number(process.env.PULL_REQUEST) call with logic that parses
process.env.PULL_REQUEST (e.g., parseInt base 10) and checks isNaN; if the
parsed value is NaN, set issueNumber to undefined (or a safe default) instead of
NaN so callers of issueNumber don't receive an invalid numeric value; update the
assignment where issueNumber is set to use this validated value.
.github/workflows/api-deployment.yaml (2)

21-21: Consider using explicit github.event.pull_request.number.

While github.event.number is valid in pull_request contexts, github.event.pull_request.number is more explicit and safer if the workflow is extended to support other event types in the future.

♻️ Suggested refinement
- STAGE: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || (github.ref == 'refs/heads/main' && 'prod' || github.ref_name) }}
+ STAGE: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || (github.ref == 'refs/heads/main' && 'prod' || github.ref_name) }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/api-deployment.yaml at line 21, Update the STAGE
expression to use the explicit pull request number field instead of the generic
event number: replace references to github.event.number with
github.event.pull_request.number in the STAGE assignment so the conditional that
builds the pr-{number} name uses the explicit github.event.pull_request.number
value; ensure the rest of the expression (the fallback checks for github.ref ==
'refs/heads/main' -> 'prod' and github.ref_name) remains unchanged.

76-98: Consider extracting duplicated setup steps into a composite action.

The setup steps (checkout, Node.js setup, pnpm setup, cache, install) are duplicated between the deploy and cleanup jobs. Extracting these into a reusable composite action would improve maintainability and reduce duplication.

This is a "nice-to-have" refactor and can be deferred to a future cleanup PR if the team prefers to keep the workflow explicit for now.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/api-deployment.yaml around lines 76 - 98, The workflow
duplicates the initial setup steps (actions/checkout@v6, actions/setup-node@v6
with node-version, pnpm/action-setup@v5, actions/cache@v5 for ~/.pnpm-store, and
the pnpm install --frozen-lockfile run) across jobs; extract these into a
reusable composite action and replace the duplicated blocks in both the deploy
and cleanup jobs with a single call to that composite. Create a composite action
that exposes inputs for node-version and pnpm version, includes the cache and
install steps, and then update the jobs to use uses: ./path/to/composite with
appropriate inputs (refer to the "Setup Node.js", "Setup pnpm", "Cache pnpm
store", and "Install dependencies" steps from the diff).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/api-deployment.yaml:
- Line 5: The pull_request event types list is missing "closed", so the cleanup
job (the cleanup job that checks github.event.action == 'closed') will never
run; update the pull_request types array to include "closed" alongside opened,
synchronize, and reopened so the cleanup job can trigger when PRs are closed and
remove preview environments. Locate the pull_request trigger definition and add
"closed" to the types: [opened, synchronize, reopened] list.
- Line 64: The workflow sets GITHUB_SHA but the runtime (alchemy.run.ts) reads
process.env.COMMIT_SHA, causing undefined; update the workflow env mapping so it
exports COMMIT_SHA: ${{ github.sha }} (or export both COMMIT_SHA and GITHUB_SHA)
where GITHUB_SHA is currently defined so process.env.COMMIT_SHA is populated for
alchemy.run.ts line that builds the PR comment body.
- Around line 55-66: Add the missing CLOUDFLARE_ACCOUNT_ID environment variable
to the Deploy step so the alchemy deploy run in the "Deploy" job
(working-directory: apps/api, run: pnpm dlx alchemy deploy --stage ${{ env.STAGE
}}) has the same Cloudflare account context as the cleanup job; add
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} under the env block
alongside CLOUDFLARE_API_TOKEN and CLOUDFLARE_EMAIL.
- Line 21: The STAGE interpolation in the workflow (the STAGE variable) contains
unreachable production logic because the workflow only triggers on pull_request;
either add a push trigger for main so github.event_name can be "push" (update
the workflow "on:" section to include push: branches: [main] and the same paths
filter as pull_request) to enable 'prod' evaluation, or remove the production
branch clause (github.ref == 'refs/heads/main && 'prod' ) from the STAGE
expression and keep only the PR-based staging logic; update the
.github/workflows/api-deployment.yaml STAGE assignment accordingly.
- Line 47: The workflow currently caches the wrong pnpm store entry ("path:
~/.pnpm-store"); update the cache step to point to pnpm's actual store by either
(a) using a dynamic command to get the store path (run `pnpm store path` and
feed that value into the cache path), or (b) replace the literal path with the
correct default store location for the runner version (use the store path
referenced in the review). Apply this change for both occurrences of the cache
step (the deploy and cleanup jobs) so the pnpm store is actually cached.

In `@apps/api/alchemy.run.ts`:
- Around line 46-55: The GitHubComment call is passing the full "owner/repo" in
the repository field; change it to just the repository name so owner and
repository are separate. Locate the GitHubComment invocation (identifier:
GitHubComment) and update the repository argument from "ahargunyllib/realm" to
"realm" while leaving owner as "ahargunyllib" and keeping other fields
(issueNumber, body) unchanged.

In `@package.json`:
- Around line 7-16: Remove the unsupported "catalog" object from the
package.json "workspaces" block and convert "workspaces" to the simple array
form (i.e., ensure "workspaces" only contains the packages array like
["apps/*","packages/*"]); move any catalog definitions into pnpm-workspace.yaml
using the top-level "catalog" or "catalogs" field instead of keeping "catalog"
inside package.json.

---

Nitpick comments:
In @.github/workflows/api-deployment.yaml:
- Line 21: Update the STAGE expression to use the explicit pull request number
field instead of the generic event number: replace references to
github.event.number with github.event.pull_request.number in the STAGE
assignment so the conditional that builds the pr-{number} name uses the explicit
github.event.pull_request.number value; ensure the rest of the expression (the
fallback checks for github.ref == 'refs/heads/main' -> 'prod' and
github.ref_name) remains unchanged.
- Around line 76-98: The workflow duplicates the initial setup steps
(actions/checkout@v6, actions/setup-node@v6 with node-version,
pnpm/action-setup@v5, actions/cache@v5 for ~/.pnpm-store, and the pnpm install
--frozen-lockfile run) across jobs; extract these into a reusable composite
action and replace the duplicated blocks in both the deploy and cleanup jobs
with a single call to that composite. Create a composite action that exposes
inputs for node-version and pnpm version, includes the cache and install steps,
and then update the jobs to use uses: ./path/to/composite with appropriate
inputs (refer to the "Setup Node.js", "Setup pnpm", "Cache pnpm store", and
"Install dependencies" steps from the diff).

In `@apps/api/alchemy.run.ts`:
- Line 49: Guard against invalid PULL_REQUEST by validating the conversion used
for issueNumber: replace the direct Number(process.env.PULL_REQUEST) call with
logic that parses process.env.PULL_REQUEST (e.g., parseInt base 10) and checks
isNaN; if the parsed value is NaN, set issueNumber to undefined (or a safe
default) instead of NaN so callers of issueNumber don't receive an invalid
numeric value; update the assignment where issueNumber is set to use this
validated value.

In `@apps/api/src/env.ts`:
- Around line 1-3: Env currently resolves to an empty object because
worker.bindings is `{}`; update the typing so consumers get meaningful binding
types by either (A) widening Env to a fallback type (e.g., make Env a
union/extension of typeof worker.bindings with Record<string, unknown> or
Record<string, any>) or (B) declare an explicit interface for expected bindings
and intersect it with typeof worker.bindings; change the export in
apps/api/src/env.ts (the Env type) accordingly and/or add the proper bindings
object or declaration when creating `worker` in alchemy.run.ts so that
`worker.bindings` carries the intended keys for consumers to use.
🪄 Autofix (Beta)

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

Run ID: ec8ffc3a-8414-41fe-8374-1b216bb286f7

📥 Commits

Reviewing files that changed from the base of the PR and between 80b6bcf and 7558fc7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .github/workflows/api-deployment.yaml
  • .gitignore
  • apps/api/.env.example
  • apps/api/alchemy.run.ts
  • apps/api/package.json
  • apps/api/src/env.ts
  • apps/api/src/index.ts
  • apps/api/tsconfig.json
  • apps/server/package.json
  • apps/server/worker-configuration.d.ts
  • apps/server/wrangler.jsonc
  • biome.jsonc
  • package.json
  • pnpm-workspace.yaml
💤 Files with no reviewable changes (2)
  • apps/server/wrangler.jsonc
  • apps/server/package.json

@github-actions
Copy link
Copy Markdown

Preview Deployment

Commit: 4d123c23bd75215d734a8407f447c2155366f2f8
Version ID: 572e9da5-0d96-438b-87c5-a814351c6d73
Preview URL: https://572e9da5-realm-www.ahargunyllib.workers.dev
Deployed at: 2026-03-31 01:21:55 UTC

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 31, 2026

Preview Deployment

Commit: 7f6fd4012ee5f2c56c3207ef4d27c3b9df4f58ac
Preview URL: https://realm-api.ahargunyllib.workers.dev
Deployed at: Tue, 31 Mar 2026 06:09:45 GMT

@github-actions
Copy link
Copy Markdown

Preview Deployment

Commit: e95904d1e52c58c3873801fac538df3d1a52309c
Version ID: 38bf9964-a2bc-41aa-8810-3af129e72f71
Preview URL: https://38bf9964-realm-www.ahargunyllib.workers.dev
Deployed at: 2026-03-31 01:25:18 UTC

@github-actions
Copy link
Copy Markdown

Preview Deployment

Commit: dc6c23fad9597c2e33fd0b346a4afd722372dd03
Version ID: eaa7721e-cf32-4828-9ca7-01f23da2ed44
Preview URL: https://eaa7721e-realm-www.ahargunyllib.workers.dev
Deployed at: 2026-03-31 06:05:26 UTC

@github-actions
Copy link
Copy Markdown

Preview Deployment

Commit: 7f6fd4012ee5f2c56c3207ef4d27c3b9df4f58ac
Version ID: 709b6a33-59ff-4c60-b33a-994ff7f49710
Preview URL: https://709b6a33-realm-www.ahargunyllib.workers.dev
Deployed at: 2026-03-31 06:10:32 UTC

@ahargunyllib ahargunyllib merged commit 3fa28cd into main Mar 31, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant