From 86eb30f498c8907020701bffb06f0694d825a6ed Mon Sep 17 00:00:00 2001 From: foxyz Date: Sun, 11 Oct 2026 16:21:05 +0300 Subject: [PATCH] Dev publish: new archive before deleting the old, manifest last (a failed upload no longer empties the dev release) Co-Authored-By: Claude Opus 5.5 --- tool/release_publish.dart | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tool/release_publish.dart b/tool/release_publish.dart index 2624961..3b3a6f8 100644 --- a/tool/release_publish.dart +++ b/tool/release_publish.dart @@ -110,8 +110,8 @@ String _apiBase(String root) { return '$server/api/v1/repos/$repo'; } -// The `dev` prerelease (created at main's head on first use): every old -// asset deleted, then [files] uploaded. Its manifest's URL is fixed, so +// The `dev` prerelease (created at main's head on first use): [files] +// uploaded (the manifest last), the previous ones deleted. Its manifest's URL is fixed, so // test builds find each new one. Future _publishDev(String root, List files) async { final token = _token(); @@ -130,17 +130,23 @@ Future _publishDev(String root, List files) async { }) ?? _die('could not create or find release dev'); final id = rel['id']; - for (final a in (rel['assets'] as List? ?? const [])) { - if (a is Map) await c.delete('$api/releases/$id/assets/${a['id']}'); - } - for (final f in files) { + final old = [for (final a in (rel['assets'] as List? ?? const [])) if (a is Map) a]; + Future upload(File f) { final name = f.uri.pathSegments.last; stdout.writeln('uploading $name ...'); - await c.upload( - '$api/releases/$id/assets?name=${Uri.encodeQueryComponent(name)}', - f, - name); + return c.upload('$api/releases/$id/assets?name=${Uri.encodeQueryComponent(name)}', f, name); } + + // The archive first, the old assets after, the manifest last: a failed + // upload leaves the previous build in place, never an empty release. + final manifest = files.last; + for (final f in files.take(files.length - 1)) { + await upload(f); + } + for (final a in old) { + await c.delete('$api/releases/$id/assets/${a['id']}'); + } + await upload(manifest); stdout.writeln('published to dev.'); } finally { http.close();