diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7650c2b..c11bf58 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1221,27 +1221,55 @@ jobs: fi curl -fsS -X DELETE -H "$auth" "$api/tags/$TAG" >/dev/null 2>&1 || true - # vpk rather than curl, unlike the android job above, and the difference is what is being - # uploaded. An APK is one file the client is told about by a manifest this repository writes; a - # Velopack release is a set of files plus an index whose format is Velopack's own. Writing that - # index by hand would be reimplementing the tool that is already here. + # curl, like the android job above, and no longer `vpk upload gitea`. vpk's Gitea client is a + # generated SDK that cannot read the forge's answer to "create a release" since its upgrade to + # 28.0.0: the release is created and the client gets null back, so both 1.2.0 and 1.2.161 threw a + # NullReferenceException before uploading anything, leaving an empty draft behind on every push. + # Nothing here writes Velopack's index by hand: `vpk pack` already wrote releases.win-nightly.json + # beside the packages, and with no earlier release downloaded into that directory it is exactly + # the index `vpk upload` would have generated from it. # - # --pre is load-bearing twice over. It keeps this out of the release channel, which refuses + # A draft first, published only once everything is on it, which is the order vpk used too: the + # client reads the index and then fetches what it names, and a published release missing a + # package is a few seconds in which every desktop is told to download something that is not + # there. The index goes up last for the same reason. + # + # prerelease is load-bearing twice over. It keeps this out of the release channel, which refuses # prereleases — and it keeps it out of `releases/latest`, which is what the *phone's* release # channel reads: a desktop nightly published as a stable release would become the newest release # in this repository and every phone on the release channel would start failing its update check # against a release carrying no android manifest. - dotnet vpk upload gitea \ - --skip-updates \ - --repoUrl "$FORGE/$REPO" \ - --token "$TOKEN" \ - --outputDir "$RUNNER_TEMP/nightly-releases" \ - --channel win-nightly \ - --tag "$TAG" \ - --releaseName "Nightly desktop $VERSION" \ - --targetCommitish "$GITHUB_SHA" \ - --pre \ - --publish + releases="$RUNNER_TEMP/nightly-releases" + + created="$(curl -fsS -X POST -H "$auth" -H 'Content-Type: application/json' \ + -d "$(printf '{"tag_name":"%s","target_commitish":"%s","name":"Nightly desktop %s","draft":true,"prerelease":true,"body":"Built from %s by CI. Installs beside the release build, never over it."}' \ + "$TAG" "$GITHUB_SHA" "$VERSION" "$GITHUB_SHA")" \ + "$api/releases")" + + draft="$(printf '%s' "$created" | release_id)" + if [ -z "$draft" ]; then + echo "Gitea accepted the release call and returned no id:" >&2 + printf '%s\n' "$created" >&2 + exit 1 + fi + + for file in "$releases"/*-full.nupkg "$releases"/*-Portable.zip "$releases"/*-Setup.exe \ + "$releases"/releases.win-nightly.json; do + if [ ! -f "$file" ]; then + echo "vpk pack did not leave $file behind:" >&2 + ls -la "$releases" >&2 + exit 1 + fi + name="$(basename "$file")" + echo "Uploading $name ($(wc -c < "$file") bytes)" + curl -fsS -X POST -H "$auth" \ + -F "attachment=@$file" \ + "$api/releases/$draft/assets?name=$name" >/dev/null + done + + curl -fsS -X PATCH -H "$auth" -H 'Content-Type: application/json' \ + -d '{"draft":false}' \ + "$api/releases/$draft" >/dev/null # Asked for back rather than assumed, and the android job's history is why: it once created a # release, uploaded nothing, and reported success for every upload it never made. A nightly @@ -1260,20 +1288,16 @@ jobs: fi done - # ◆ THE RPM GOES ONTO THE RELEASE vpk JUST MADE, RATHER THAN ONTO ONE OF ITS OWN. + # ◆ THE RPM GOES ONTO THE RELEASE JUST MADE, RATHER THAN ONTO ONE OF ITS OWN. # # One rolling release carrying both heads, because they are one nightly: the same commit, # the same version, and one page a person looks at to find out what is on main. A second tag # would double the delete-and-recreate dance this step already does, and would let the two # drift apart on a run where one of them failed. # - # It has to happen here, after `vpk upload`, and not in a step before it. vpk deletes and - # recreates this release, so an RPM uploaded first would be attached to something that no - # longer exists by the time the job ends — silently, because the delete succeeds. - # - # curl rather than vpk, unlike the assets above, for the reason the android job gives about - # its APK: this is one file the release simply carries. There is no index to write and no - # format that belongs to a tool. + # It has to happen here, after the Windows upload, and not in a step before it. This step + # deletes and recreates the release, so an RPM uploaded first would be attached to something + # that no longer exists by the time the job ends — silently, because the delete succeeds. release="$(printf '%s' "$published" | release_id)" if [ -z "$release" ]; then echo "The release was published and its id could not be read back:" >&2