generated from CubeCraft-Creations/Tracehound
Dev #26
@@ -16,6 +16,21 @@ const VERSION = SHA.slice(0, 8);
|
|||||||
const API = `${SERVER}/api/v1/repos/${REPO}`;
|
const API = `${SERVER}/api/v1/repos/${REPO}`;
|
||||||
const H = { Authorization: `token ${TOKEN}` };
|
const H = { Authorization: `token ${TOKEN}` };
|
||||||
|
|
||||||
|
// The runner's network to Gitea is flaky (ECONNRESET mid-publish leaves a
|
||||||
|
// half-created release). Retry transient fetch failures so the multi-step
|
||||||
|
// publish is atomic-enough in practice.
|
||||||
|
const rfetch = async (url, opts = {}, tries = 4) => {
|
||||||
|
for (let i = 1; ; i++) {
|
||||||
|
try {
|
||||||
|
return await fetch(url, opts);
|
||||||
|
} catch (e) {
|
||||||
|
if (i >= tries) throw e;
|
||||||
|
console.log(`fetch ${url} failed (${e.cause?.code || e.message}); retry ${i}/${tries - 1}`);
|
||||||
|
await new Promise((r) => setTimeout(r, 1000 * i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const ok = async (r) => {
|
const ok = async (r) => {
|
||||||
if (!r.ok) throw new Error(`${r.status} ${r.url}\n${await r.text()}`);
|
if (!r.ok) throw new Error(`${r.status} ${r.url}\n${await r.text()}`);
|
||||||
const t = await r.text();
|
const t = await r.text();
|
||||||
@@ -31,14 +46,14 @@ const files = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Roll the release forward to this commit: delete the old release + tag.
|
// Roll the release forward to this commit: delete the old release + tag.
|
||||||
const existing = await fetch(`${API}/releases/tags/${TAG}`, { headers: H });
|
const existing = await rfetch(`${API}/releases/tags/${TAG}`, { headers: H });
|
||||||
if (existing.ok) {
|
if (existing.ok) {
|
||||||
const rel = await existing.json();
|
const rel = await existing.json();
|
||||||
await fetch(`${API}/releases/${rel.id}`, { method: 'DELETE', headers: H });
|
await rfetch(`${API}/releases/${rel.id}`, { method: 'DELETE', headers: H });
|
||||||
}
|
}
|
||||||
await fetch(`${API}/tags/${TAG}`, { method: 'DELETE', headers: H }); // ignore if absent
|
await rfetch(`${API}/tags/${TAG}`, { method: 'DELETE', headers: H }); // ignore if absent
|
||||||
|
|
||||||
const rel = await ok(await fetch(`${API}/releases`, {
|
const rel = await ok(await rfetch(`${API}/releases`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { ...H, 'Content-Type': 'application/json' },
|
headers: { ...H, 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -53,7 +68,7 @@ const rel = await ok(await fetch(`${API}/releases`, {
|
|||||||
for (const [name, buf] of Object.entries(files)) {
|
for (const [name, buf] of Object.entries(files)) {
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('attachment', new Blob([buf]), name);
|
fd.append('attachment', new Blob([buf]), name);
|
||||||
await ok(await fetch(`${API}/releases/${rel.id}/assets?name=${encodeURIComponent(name)}`, {
|
await ok(await rfetch(`${API}/releases/${rel.id}/assets?name=${encodeURIComponent(name)}`, {
|
||||||
method: 'POST', headers: H, body: fd,
|
method: 'POST', headers: H, body: fd,
|
||||||
}));
|
}));
|
||||||
console.log(`uploaded ${name}`);
|
console.log(`uploaded ${name}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user