generated from CubeCraft-Creations/Tracehound
ci: retry transient network errors when publishing the release
The publish step died with "fetch failed: ECONNRESET" mid-run, leaving a half-created release (no version.txt asset → the Pi got 404s). Wrap the Gitea API calls in a small retry (rfetch) so a flaky connection doesn't leave the rolling release incomplete. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,21 @@ const VERSION = SHA.slice(0, 8);
|
||||
const API = `${SERVER}/api/v1/repos/${REPO}`;
|
||||
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) => {
|
||||
if (!r.ok) throw new Error(`${r.status} ${r.url}\n${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.
|
||||
const existing = await fetch(`${API}/releases/tags/${TAG}`, { headers: H });
|
||||
const existing = await rfetch(`${API}/releases/tags/${TAG}`, { headers: H });
|
||||
if (existing.ok) {
|
||||
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',
|
||||
headers: { ...H, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@@ -53,7 +68,7 @@ const rel = await ok(await fetch(`${API}/releases`, {
|
||||
for (const [name, buf] of Object.entries(files)) {
|
||||
const fd = new FormData();
|
||||
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,
|
||||
}));
|
||||
console.log(`uploaded ${name}`);
|
||||
|
||||
Reference in New Issue
Block a user