fix(release): replace version-independent channel files on 409
latest.yml and release-notes.md change every release, but the atomic publish no longer wipes the channel up front, so their PUTs now hit the previous release's stored file. Swap them in place (delete + put, one small file); version-named payloads keep the same-size keep rule.
This commit is contained in:
1 parent
eccc1f52e7
commit
258e5fac0c
1 file changed
+26
-12
+26
-12
@@ -200,21 +200,35 @@ async function giteaChannel() {
|
|||||||
for (const [f, name] of ordered) {
|
for (const [f, name] of ordered) {
|
||||||
const stat = fs.statSync(f)
|
const stat = fs.statSync(f)
|
||||||
const url = `${base}/${encodeURIComponent(name)}`
|
const url = `${base}/${encodeURIComponent(name)}`
|
||||||
const resp = await fetch(url, {
|
const put = async () =>
|
||||||
method: 'PUT',
|
fetch(url, {
|
||||||
headers: { Authorization: `token ${env.GIT_TOKEN}`, 'Content-Type': 'application/octet-stream', 'Content-Length': String(stat.size) },
|
method: 'PUT',
|
||||||
body: fs.createReadStream(f),
|
headers: { Authorization: `token ${env.GIT_TOKEN}`, 'Content-Type': 'application/octet-stream', 'Content-Length': String(stat.size) },
|
||||||
duplex: 'half'
|
body: fs.createReadStream(f),
|
||||||
})
|
duplex: 'half'
|
||||||
|
})
|
||||||
|
let resp = await put()
|
||||||
console.log(` put ${name}: HTTP ${resp.status}`)
|
console.log(` put ${name}: HTTP ${resp.status}`)
|
||||||
|
if (!resp.ok && (resp.status === 409 || resp.status === 422)) {
|
||||||
|
if (/\d+\.\d+\.\d+/.test(name)) {
|
||||||
|
// Version-named payloads are immutable per release: accept a stored
|
||||||
|
// copy only when it has exactly the same size.
|
||||||
|
if ((await channelFileSize(url)) === stat.size) {
|
||||||
|
console.log(` ${name} is already published with the same size, kept`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// latest.yml / release-notes.md change every release and the atomic
|
||||||
|
// flow no longer wipes the channel up front, so replace them in place.
|
||||||
|
// The swap window is one small file (sub-second), not the whole channel.
|
||||||
|
const del = await fetch(url, { method: 'DELETE', headers: { Authorization: `token ${env.GIT_TOKEN}` } })
|
||||||
|
console.log(` delete old ${name}: HTTP ${del.status}`)
|
||||||
|
resp = await put()
|
||||||
|
console.log(` put ${name}: HTTP ${resp.status}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!resp.ok) {
|
if (!resp.ok) {
|
||||||
const detail = (await resp.text()).slice(0, 200)
|
const detail = (await resp.text()).slice(0, 200)
|
||||||
// Re-publishing the same version can hit an already-stored file; accept it
|
|
||||||
// only when the stored copy has exactly the same size.
|
|
||||||
if ((resp.status === 409 || resp.status === 422) && (await channelFileSize(url)) === stat.size) {
|
|
||||||
console.log(` ${name} is already published with the same size, kept`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
throw new Error(`channel put failed (${resp.status}) for ${name}: ${detail}`)
|
throw new Error(`channel put failed (${resp.status}) for ${name}: ${detail}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user