Preview: Runner-Verfolger verdraengt sauber, R15-Grenzen

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-09-30 21:54:01 +00:00
1 parent 4258b5b9f1
commit d788dba937
2 files changed
+126 -15

No files matched your search

+97
View File
@@ -256,3 +256,100 @@ test('Runner ausgelastet (503): failed mit Meldung, kein Wurf', async () => {
assert.equal(r.error, 'Server ausgelastet')
assert.equal(aw.get('websiteProjects', id).previewState, 'failed')
})
test('Modus off während ein Lauf läuft: Zustand bleibt off, kein TLS-Sync vom alten Verfolger', async () => {
const { id, repo, doc } = await project()
rs.script = () => ({ state: 'running', detected: null, sha: SHA, log: [], error: null, result: null })
const r1 = await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
const { updateDocument } = await import('../server/services/appwriteAdmin.js')
const off = await updateDocument('websiteProjects', id, { previewMode: 'off' })
await pd.runDeploy(repo, 'main', cfg(repo), { project: off, sha: SHA })
rs.runs.set(r1.runId, { state: 'done', detected: { kind: 'static', pm: 'npm' }, sha: SHA, log: ['alt'], error: null, result: 'static' })
await pd.waitForRunFollowers()
assert.equal(aw.get('websiteProjects', id).previewState, 'off')
assert.equal((await logs.listRunLogs(id)).length, 0)
})
test('gleichzeitige Aufrufe: der neueste gewinnt', async () => {
const { id, repo, doc } = await project()
rs.script = (job) => ({ state: 'done', detected: { kind: 'static', pm: 'npm' }, sha: job.sha, log: [job.sha], error: null, result: 'static' })
const sha2 = 'e'.repeat(40)
const [, r2] = await Promise.all([
pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA }),
pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: sha2 }),
])
await pd.waitForRunFollowers()
assert.ok(r2.queued)
assert.equal(aw.get('websiteProjects', id).previewBuiltSha, sha2)
})
test('fehlgeschlagener neuer Auftrag verdrängt den alten Verfolger', async () => {
const { id, repo, doc } = await project()
rs.script = () => ({ state: 'running', detected: null, sha: SHA, log: [], error: null, result: null })
const r1 = await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
rs.submitError = 503
await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
rs.runs.set(r1.runId, { state: 'done', detected: { kind: 'static' }, sha: SHA, log: [], error: null, result: 'static' })
await pd.waitForRunFollowers()
assert.equal(aw.get('websiteProjects', id).previewState, 'failed')
})
test('R15: folgt queued/running über die alte 16-Minuten-Grenze, Runner-Ausfall lange toleriert', async () => {
const { id, repo, doc } = await project()
let polls = 0
rs.script = () => ({ state: 'queued', detected: null, sha: SHA, log: [], error: null, result: null })
const r = await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
const orig = rs.runs.get(r.runId)
Object.defineProperty(orig, 'state', { get() { polls++; return polls < 15 ? 'queued' : 'done' }, enumerable: true })
await pd.waitForRunFollowers()
assert.ok(polls >= 15)
assert.equal(aw.get('websiteProjects', id).previewState, 'online')
})
test('R15: Gesamtzeit überschritten => failed mit "Status unbekannt"', async () => {
const { id, repo, doc } = await project()
rs.script = () => ({ state: 'running', detected: null, sha: SHA, log: [], error: null, result: null })
const saved = pd.runnerTiming.maxMs
pd.runnerTiming.maxMs = 60
try {
await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
await pd.waitForRunFollowers()
} finally { pd.runnerTiming.maxMs = saved }
const d = aw.get('websiteProjects', id)
assert.equal(d.previewState, 'failed')
assert.equal(d.previewError, 'Status unbekannt – bitte neu bauen')
})
test('R15: Runner dauerhaft unerreichbar (> unreachableMs) => failed', async () => {
const { id, repo, doc } = await project()
rs.script = () => ({ state: 'running', detected: null, sha: SHA, log: [], error: null, result: null })
const { config } = await import('../server/config.js')
const savedUrl = config.previewRunner.url
const saved = pd.runnerTiming.unreachableMs
pd.runnerTiming.unreachableMs = 50
try {
await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
config.previewRunner.url = 'http://127.0.0.1:1'
await pd.waitForRunFollowers()
} finally { config.previewRunner.url = savedUrl; pd.runnerTiming.unreachableMs = saved }
const d = aw.get('websiteProjects', id)
assert.equal(d.previewState, 'failed')
assert.match(d.previewError, /nicht erreichbar/)
})
test('Runner-Fehlertext wird maskiert', async () => {
rs.script = done({ state: 'failed', result: null, error: 'Fehler mit supergeheim99', log: [] })
const { id, repo, doc } = await project({ previewEnv: envLib.encryptEnv({ K: 'supergeheim99' }, key) })
await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
await pd.waitForRunFollowers()
assert.equal(aw.get('websiteProjects', id).previewError, 'Fehler mit •••')
})
test('dev-Ergebnis: PUT /dev/<sub> mit vollständigem Auftrag inkl. Variablen', async () => {
rs.script = done({ result: 'dev', detected: { kind: 'dev', pm: 'npm' } })
const { repo, doc } = await project({ previewEnv: envLib.encryptEnv({ A: 'wert1234' }, key), previewMode: 'dev' })
await pd.runDeploy(repo, 'main', cfg(repo), { project: doc, sha: SHA })
await pd.waitForRunFollowers()
const put = rs.calls.find((c) => c.method === 'PUT')
assert.deepEqual(put.body, { sub: repo.split('/')[1], repo, sha: SHA, branch: 'main', mode: 'dev', env: { A: 'wert1234' } })
})