Skip to content

chore(deploy): config-as-code railway.json + per-service watch path docs#53

Merged
vivek7405 merged 2 commits into
mainfrom
chore/railway-watch-all-services
May 21, 2026
Merged

chore(deploy): config-as-code railway.json + per-service watch path docs#53
vivek7405 merged 2 commits into
mainfrom
chore/railway-watch-all-services

Conversation

@vivek7405
Copy link
Copy Markdown
Collaborator

@vivek7405 vivek7405 commented May 21, 2026

Problem

The 4 Railway services in this repo each have a per-subdir watch path. Root-level changes (Dockerfile, root configs) only fire the service whose list happens to mention them. PR #51's Dockerfile fix reached ui-website but not website/docs/blog, which is why webjs.dev/changelog stayed broken even after the merge.

Mapped what each runtime actually depends on (imports, not prose mentions):

Service Imports from packages/
website core, cli
docs core, cli, server
blog (examples/) core, server
ui-website core, cli, ui

(ts-plugin is editor-only, no runtime use, so it's intentionally excluded. The docs site mentions @webjskit/ui in prose on the UI doc page but does not import it, so ui is not a runtime dep there.)

Plus everyone is built from the same Dockerfile and runs webjs start, so cli/core/server transitively land in every image.

Fix

Two parts.

1. railway.json at the repo root

Adds a shared, file-controlled record of the build (builder: DOCKERFILE, dockerfilePath: Dockerfile) and the deploy restart policy. watchPatterns is not in this file because a single value at the repo root would apply identically to all four services and the whole point is to make each service trigger on a different set.

2. Per-service watch paths (one-time dashboard cleanup)

For each service: open Settings → Source → Watch Paths, clear the existing list, paste the matching list below, and save.

@webjskit/website (webjs.dev)

/website/**
/changelog/**
/Dockerfile
/package.json
/package-lock.json
/railway.json
/packages/cli/**
/packages/core/**
/packages/server/**

@webjskit/docs (docs.webjs.dev)

/docs/**
/Dockerfile
/package.json
/package-lock.json
/railway.json
/packages/cli/**
/packages/core/**
/packages/server/**

@webjskit-examples/blog (example-blog.webjs.dev)

/examples/blog/**
/Dockerfile
/package.json
/package-lock.json
/railway.json
/packages/cli/**
/packages/core/**
/packages/server/**

@webjskit/ui-website (ui.webjs.dev)

/packages/ui/**
/Dockerfile
/package.json
/package-lock.json
/railway.json
/packages/cli/**
/packages/core/**
/packages/server/**

After the dashboard cleanup

  • A change to website/app/page.ts → only the website rebuilds.
  • A change to Dockerfile or root package.json → all four rebuild.
  • A change to packages/core/** or packages/server/** → all four rebuild (they all run on the framework).
  • A change to packages/ui/** → only ui-website rebuilds.
  • A change to changelog/<pkg>/<version>.md → only the website rebuilds (the page that reads it).

Test plan

  • After dashboard cleanup + this PR merges, push a website-only commit and confirm only the website service rebuilds.
  • Push a Dockerfile-only commit and confirm all four rebuild.
  • Confirm https://webjs.dev/changelog finally renders the per-package entries (the deferred fix from PR fix(deploy): copy changelog/ into the production image #51).

vivek7405 added 2 commits May 21, 2026 19:52
…tterns

Add a repo-root railway.json that captures the build (DOCKERFILE
builder, Dockerfile path) and a deploy restart policy. The
watchPatterns field is explicitly set to ["**/*"] so every commit
to main triggers a redeploy of every service.

Background: the 4 Railway services (@webjskit/website, /docs,
/ui-website, @webjskit-examples/blog) all build from the same
repo and the same Dockerfile, but each had its own dashboard-set
watch-path filter scoped to its own subdir. A root-level change
(e.g. Dockerfile, package.json, changelog/) did not trigger the
services whose subdir was untouched, which is how PR #51 (a
Dockerfile-only fix) reached only ui-website and left
webjs.dev/changelog broken until #52.

Note: Railway dashboard-set values take precedence over
config-as-code. After this merges, clear "Watch Paths" in the
dashboard for each of the 4 services (Service → Settings →
Source → Watch Paths → clear the list, save), so railway.json
takes over. Once that is done, future cross-service infra
changes (Dockerfile, compose.yaml, root package.json, etc.)
trigger redeploys for all four services automatically.
Per-service watch paths cannot be expressed in a single repo-root
railway.json (the file applies to every service that points at it
and there is no per-service override in the JSON shape). Drop the
**/* pattern from the file and move the per-service tables into
the PR description for paste-into-dashboard use. The remaining
build + deploy fields stay because they really are shared by all
four services.
@vivek7405 vivek7405 changed the title chore(deploy): railway.json with cross-service watchPatterns chore(deploy): config-as-code railway.json + per-service watch path docs May 21, 2026
@vivek7405 vivek7405 merged commit 6ef0e1f into main May 21, 2026
@vivek7405 vivek7405 deleted the chore/railway-watch-all-services branch May 21, 2026 14:38
vivek7405 added a commit that referenced this pull request May 21, 2026
…ocs (#53)

* chore(deploy): config-as-code railway.json with cross-service watchPatterns

Add a repo-root railway.json that captures the build (DOCKERFILE
builder, Dockerfile path) and a deploy restart policy. The
watchPatterns field is explicitly set to ["**/*"] so every commit
to main triggers a redeploy of every service.

Background: the 4 Railway services (@webjskit/website, /docs,
/ui-website, @webjskit-examples/blog) all build from the same
repo and the same Dockerfile, but each had its own dashboard-set
watch-path filter scoped to its own subdir. A root-level change
(e.g. Dockerfile, package.json, changelog/) did not trigger the
services whose subdir was untouched, which is how PR #51 (a
Dockerfile-only fix) reached only ui-website and left
webjs.dev/changelog broken until #52.

Note: Railway dashboard-set values take precedence over
config-as-code. After this merges, clear "Watch Paths" in the
dashboard for each of the 4 services (Service → Settings →
Source → Watch Paths → clear the list, save), so railway.json
takes over. Once that is done, future cross-service infra
changes (Dockerfile, compose.yaml, root package.json, etc.)
trigger redeploys for all four services automatically.

* chore(deploy): drop the global watchPatterns from railway.json

Per-service watch paths cannot be expressed in a single repo-root
railway.json (the file applies to every service that points at it
and there is no per-service override in the JSON shape). Drop the
**/* pattern from the file and move the per-service tables into
the PR description for paste-into-dashboard use. The remaining
build + deploy fields stay because they really are shared by all
four services.
vivek7405 added a commit that referenced this pull request May 26, 2026
The static /public/* handler did `join(appDir, path)` without checking
that the resolved absolute path stays under `appDir/public/`. Node's
URL parser normalises raw `..` segments, but it does NOT decode
percent-encoded characters. webjs then runs `decodeURIComponent` on
the parsed pathname AFTER URL parsing. Combined, this lets a
`/public%2F..%2Fsecret%2Fsecret.svg` URL survive URL parsing as
`/public%2F..%2Fsecret%2Fsecret.svg`, decode to
`/public/../secret/secret.svg`, match the `/public/` branch, and
have `join` resolve to `appDir/secret/secret.svg` (outside public/).

Fix: after computing `abs = join(appDir, p)`, verify
`abs.startsWith(appDir + path.sep + 'public' + path.sep)`. Reject
with 404 if not.

Tests in /tmp covered raw `..`, `%2E%2E`, percent-encoded slash,
double-encoded forms. Only the `%2F..%2F` (encoded slash) variant
exploited the /public/ branch specifically; the others fall through
to URL-parser normalisation and hit the user-source branch, which is
a separate appDir-wide-exposure concern filed as task #53.
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