Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions apps/desk/scripts/production-config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ export function createProductionConfig(source, env) {
const queueName = required(env, 'ABLE_MEDIA_QUEUE_NAME', /^[a-z0-9][a-z0-9_-]{1,62}$/)
const config = structuredClone(source)

// A deployment may run on a Worker whose name predates this one, and the
// Worker name is not customer-visible when custom domains front it. Renaming
// a Worker in place is not possible, so allow the name to be supplied like
// every other deployment identifier rather than moving domains, Access
// policy and email routing to a differently named Worker. Optional: the
// committed name is the default.
const workerName = env.ABLE_WORKER_NAME?.trim()
if (workerName) {
// A Worker name becomes a DNS label, so it may not start or end with a
// hyphen, and is limited to 63 characters.
if (!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(workerName)) throw new Error('ABLE_WORKER_NAME is invalid')
config.name = workerName
}

const database = config.d1_databases?.find((binding) => binding.binding === 'DB')
const bucket = config.r2_buckets?.find((binding) => binding.binding === 'ATTACHMENTS')
const producer = config.queues?.producers?.find((binding) => binding.binding === 'MEDIA_QUEUE')
Expand Down
17 changes: 17 additions & 0 deletions apps/desk/test/production-config.node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
import { createProductionConfig } from '../scripts/production-config.mjs'

const source = {
name: 'able',
d1_databases: [{ binding: 'DB', database_name: 'able', migrations_dir: 'migrations' }],
r2_buckets: [{ binding: 'ATTACHMENTS' }],
queues: {
Expand Down Expand Up @@ -38,4 +39,20 @@ describe('production Wrangler configuration', () => {
expect(() => createProductionConfig(source, { ...variables, ABLE_R2_BUCKET_NAME: '../bucket' }))
.toThrow('ABLE_R2_BUCKET_NAME is missing or invalid')
})

it('keeps the committed Worker name unless a deployment supplies its own', () => {
// A Worker cannot be renamed in place, so a deployment already serving
// custom domains from an older Worker name must be able to keep it.
expect(createProductionConfig(source, variables).name).toBe('able')
expect(createProductionConfig(source, { ...variables, ABLE_WORKER_NAME: 'abledesk' }).name).toBe('abledesk')
expect(createProductionConfig(source, { ...variables, ABLE_WORKER_NAME: ' ' }).name).toBe('able')
expect(source.name).toBe('able')
})

it('rejects a Worker name Cloudflare would not accept', () => {
for (const name of ['Not Valid', 'trailing-', '-leading', 'has_underscore', 'a'.repeat(64)]) {
expect(() => createProductionConfig(source, { ...variables, ABLE_WORKER_NAME: name }))
.toThrow('ABLE_WORKER_NAME is invalid')
}
})
})
12 changes: 11 additions & 1 deletion apps/desk/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,20 @@
}
]
},
// Migration tags are an immutable contract: Cloudflare records which tags a
// Worker has applied, so an already-applied tag must keep its original
// contents. v1 therefore still names the class as it was first created, and
// the rename to Able is expressed as a new tag. A fresh install applies both
// in sequence and lands on AbleDeskAgent; a Worker that already applied v1
// applies only v2 and keeps its Durable Object state.
"migrations": [
{
"tag": "v1_voice_demo",
"new_sqlite_classes": ["AbleDeskAgent"]
"new_sqlite_classes": ["AbleDeskVoiceDemoAgent"]
},
{
"tag": "v2_rename_desk_agent",
"renamed_classes": [{ "from": "AbleDeskVoiceDemoAgent", "to": "AbleDeskAgent" }]
}
],
"d1_databases": [
Expand Down
3 changes: 2 additions & 1 deletion docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ Keep deployment-specific resource coordinates in private Workers Builds variable
- `ABLE_D1_DATABASE_ID`: the production D1 database UUID;
- `ABLE_D1_DATABASE_NAME`: the production D1 database name;
- `ABLE_R2_BUCKET_NAME`: the production attachment bucket;
- `ABLE_MEDIA_QUEUE_NAME`: the production attachment-analysis queue.
- `ABLE_MEDIA_QUEUE_NAME`: the production attachment-analysis queue;
- `ABLE_WORKER_NAME`: optional; the Worker to deploy onto when it is not the committed default. A Worker cannot be renamed in place, so a deployment whose Worker predates a rename can keep serving from it instead of moving its custom domains, Access application and email routing to a differently named Worker. The Worker name is not customer-visible when custom domains front it.

`npm run deploy:production` validates these values and creates an ignored, ephemeral Wrangler file for the build. It never writes the production coordinates into the public repository.

Expand Down
Loading