import { test, before, after } from 'node:test'
import assert from 'node:assert/strict'
import { execFileSync } from 'node:child_process'
import fs from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path'
// 2026-09-30 (Kirschner Gebäudeservice): Projektänderung und Gitea-Webhook deployten dasselbe
// Repo gleichzeitig, beide git clone liefen ins selbe Arbeitsverzeichnis und brachen ab.
let tmp
let previewDeploy
const cwd = process.cwd()
before(async () => {
tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'preview-lock-'))
const repo = path.join(tmp, 'gitea', 'WEBklar', 'kunde.git')
const src = path.join(tmp, 'src')
await fs.mkdir(src, { recursive: true })
// Genug Inhalt, dass ein Klon Zeit braucht und sich zwei Klone überschneiden
for (let i = 0; i < 300; i += 1) await fs.writeFile(path.join(src, `seite-${i}.html`), `
${i}
`.repeat(200))
await fs.writeFile(path.join(src, 'index.html'), 'Kunde')
const git = (args, dir) => execFileSync('git', args, { cwd: dir, stdio: 'ignore' })
git(['init', '-q', '-b', 'main'], src)
git(['-c', 'user.name=t', '-c', 'user.email=t@t', 'add', '.'], src)
git(['-c', 'user.name=t', '-c', 'user.email=t@t', 'commit', '-q', '-m', 'init'], src)
git(['clone', '-q', '--bare', src, repo], tmp)
await fs.mkdir(path.join(tmp, 'work'))
process.chdir(path.join(tmp, 'work')) // previewWorkDir() liegt unter process.cwd()
Object.assign(process.env, {
APPWRITE_ENDPOINT: 'http://127.0.0.1:9/v1',
APPWRITE_API_KEY: 'test-key',
GITEA_BASE_URL: `file://${path.join(tmp, 'gitea')}`,
GITEA_API_TOKEN: '',
PREVIEW_DEPLOY_ROOT: path.join(tmp, 'previews'),
TRAEFIK_DYNAMIC_DIR: '',
})
previewDeploy = await import('../server/services/previewDeploy.js')
})
after(async () => {
process.chdir(cwd)
await fs.rm(tmp, { recursive: true, force: true })
})
test('gleichzeitige Deploys desselben Repos laufen nacheinander und gelingen beide', async () => {
const cfg = { subdomain: 'kunde', type: 'static' }
const results = await Promise.allSettled([
previewDeploy.runDeploy('WEBklar/kunde', 'main', cfg),
previewDeploy.runDeploy('WEBklar/kunde', 'main', cfg),
previewDeploy.runDeploy('WEBklar/kunde', 'main', cfg),
])
for (const r of results) assert.equal(r.status, 'fulfilled', r.reason?.message)
assert.match(await fs.readFile(path.join(tmp, 'previews', 'kunde', 'index.html'), 'utf8'), /Kunde/)
assert.equal((await fs.readdir(path.join(tmp, 'previews', 'kunde'))).filter((f) => f.startsWith('seite-')).length, 300)
})