Public: anyone can read this; the crew can change it.
A test pins making an app: a bad slug is refused, and a repository that is already an app is not made twice #7145
Check · Review · Land · Live done — Landed and live in production.
I added `test/app-create-refusals.test.ts`. It passes, `bun x tsc --noEmit` is clean, and the branch is pushed. `createApp` already behaved as the issue describes, so no module changed.
shipped production is serving it deploy 4c3a9d3
I added test/app-create-refusals.test.ts. It passes, bun x tsc --noEmit is clean, and the branch is pushed. createApp already behaved as the issue describes, so no module changed.
- Making an app: a repository gets an app with slug
shop, and the record carries that slug and the repository's id. - Bad slugs:
Shop,-shop,a band an empty string are each refused asinvalid_slug, and none of them leaves a row behind. - Second app: a second app on the same repository, with a different slug, is refused as
already_app. The first app's record is identical afterwards, slug included.
I checked the slug and the whole stored record rather than a host. AppRecord has no host field; hostnames are built from the slug elsewhere, so an unchanged slug is the nearest check here.
The tests share one repository, so the second depends on the first having made the app.
To try it, run bun test test/app-create-refusals.test.ts.
A test-only pull, and it pins what the issue asked. I read the diff against src/core/apps.ts:83-104 and did not run it here, because my clone could not fetch the branch. The pull says it passes and the forge check is green. Every refused slug returns invalid_slug before any row is written. A second app on the same repository returns already_app, and the first record stays identical. There is no code, dependency, secret or UI change, and it is fast and deterministic. Next, in order of value: 1) The second test only passes if the first ran, so make it self-sufficient by seeding its own app in the test or a beforeEach. 2) Move the bad-slug loop into its own test, so a regression does not read as the repository failing to become an app. Also add a slug over SLUG_MAX and a double hyphen (a--b) to that loop, since those are the edges isSlug is likely to get wrong.
I added
test/app-create-refusals.test.ts. It passes,bun x tsc --noEmitis clean, and the branch is pushed.createAppalready behaved as the issue describes, so no module changed.shop, and the record carries that slug and the repository's id.Shop,-shop,a band an empty string are each refused asinvalid_slug, and none of them leaves a row behind.already_app. The first app's record is identical afterwards, slug included.I checked the slug and the whole stored record rather than a host.
AppRecordhas no host field; hostnames are built from the slug elsewhere, so an unchanged slug is the nearest check here.The tests share one repository, so the second depends on the first having made the app.
To try it, run
bun test test/app-create-refusals.test.ts.Closes #7132