Skip to content

Commit df630a0

Browse files
authored
Merge pull request #474 from OpenHub-Store/upload-workflow
2 parents 750563f + 401f5a7 commit df630a0

1 file changed

Lines changed: 171 additions & 0 deletions

File tree

.github/workflows/build-desktop-platforms.yml

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,174 @@ jobs:
411411
if-no-files-found: error
412412
retention-days: 30
413413
compression-level: 0
414+
415+
release:
416+
name: Draft release with all installers
417+
needs: [build-windows, build-macos, build-linux]
418+
runs-on: ubuntu-latest
419+
permissions:
420+
contents: write
421+
422+
steps:
423+
- name: Checkout code
424+
uses: actions/checkout@v4
425+
426+
- name: Read project version
427+
id: version
428+
run: |
429+
set -euo pipefail
430+
VERSION=$(grep 'projectVersionName' gradle/libs.versions.toml | head -1 | sed 's/.*= *"\(.*\)"/\1/')
431+
if [ -z "$VERSION" ]; then
432+
echo "ERROR: could not read projectVersionName from gradle/libs.versions.toml"
433+
exit 1
434+
fi
435+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
436+
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
437+
echo "Resolved release tag: v$VERSION"
438+
shell: bash
439+
440+
- name: Download all build artifacts
441+
uses: actions/download-artifact@v4
442+
with:
443+
path: artifacts
444+
445+
- name: Stage release files (rename arch / compat collisions)
446+
run: |
447+
set -euo pipefail
448+
mkdir -p release-files
449+
450+
# stage() returns 0 on a successful copy, 1 if the source is missing.
451+
# Callers use the exit status to increment per-group counters so the
452+
# completeness guard at the end can detect missing groups.
453+
stage() {
454+
local src="$1"
455+
local target_name="$2"
456+
if [ -f "$src" ]; then
457+
cp "$src" "release-files/$target_name"
458+
echo "Staged: $target_name"
459+
return 0
460+
fi
461+
return 1
462+
}
463+
464+
windows_count=0
465+
macos_x64_count=0
466+
macos_arm64_count=0
467+
linux_modern_count=0
468+
linux_debian12_count=0
469+
linux_appimage_count=0
470+
linux_arch_count=0
471+
472+
# Windows — names already unique (.exe, .msi)
473+
for f in artifacts/windows-installers/*.exe artifacts/windows-installers/*.msi; do
474+
[ -f "$f" ] || continue
475+
stage "$f" "$(basename "$f")" && windows_count=$((windows_count + 1)) || true
476+
done
477+
478+
# macOS — disambiguate x64 vs arm64 (Compose outputs identical filenames per arch)
479+
for f in artifacts/macos-installers-x64/*.dmg artifacts/macos-installers-x64/*.pkg; do
480+
[ -f "$f" ] || continue
481+
base="$(basename "$f")"
482+
ext="${base##*.}"
483+
stem="${base%.*}"
484+
stage "$f" "${stem}-x64.${ext}" && macos_x64_count=$((macos_x64_count + 1)) || true
485+
done
486+
for f in artifacts/macos-installers-arm64/*.dmg artifacts/macos-installers-arm64/*.pkg; do
487+
[ -f "$f" ] || continue
488+
base="$(basename "$f")"
489+
ext="${base##*.}"
490+
stem="${base%.*}"
491+
stage "$f" "${stem}-arm64.${ext}" && macos_arm64_count=$((macos_arm64_count + 1)) || true
492+
done
493+
494+
# Linux modern — default Debian/RPM (unprefixed)
495+
for f in artifacts/linux-installers-modern/*.deb artifacts/linux-installers-modern/*.rpm; do
496+
[ -f "$f" ] || continue
497+
stage "$f" "$(basename "$f")" && linux_modern_count=$((linux_modern_count + 1)) || true
498+
done
499+
500+
# Linux debian12-compat — suffix to avoid collision with modern
501+
for f in artifacts/linux-installers-debian12-compat/*.deb artifacts/linux-installers-debian12-compat/*.rpm; do
502+
[ -f "$f" ] || continue
503+
base="$(basename "$f")"
504+
ext="${base##*.}"
505+
stem="${base%.*}"
506+
stage "$f" "${stem}-debian12.${ext}" && linux_debian12_count=$((linux_debian12_count + 1)) || true
507+
done
508+
509+
# Linux AppImage + zsync (filenames already include -x86_64)
510+
for f in artifacts/linux-appimage/*.AppImage artifacts/linux-appimage/*.AppImage.zsync; do
511+
[ -f "$f" ] || continue
512+
stage "$f" "$(basename "$f")" && linux_appimage_count=$((linux_appimage_count + 1)) || true
513+
done
514+
515+
# Linux Arch (.pkg.tar.zst already has version + arch in filename)
516+
for f in artifacts/linux-arch/*.pkg.tar.zst; do
517+
[ -f "$f" ] || continue
518+
stage "$f" "$(basename "$f")" && linux_arch_count=$((linux_arch_count + 1)) || true
519+
done
520+
521+
echo
522+
echo "Final staged files:"
523+
ls -la release-files/
524+
echo
525+
echo "Per-group counts: windows=$windows_count macos-x64=$macos_x64_count macos-arm64=$macos_arm64_count linux-modern=$linux_modern_count linux-debian12=$linux_debian12_count linux-appimage=$linux_appimage_count linux-arch=$linux_arch_count"
526+
527+
# Completeness guard: refuse to ship an incomplete release. Each
528+
# group must produce >= 1 staged file. Without this guard, a build
529+
# regression (e.g. AppImage step silently producing nothing) would
530+
# ship a draft release missing the affected group and we'd discover
531+
# it only when users complained.
532+
missing=()
533+
[ "$windows_count" -eq 0 ] && missing+=("Windows installers (.exe/.msi)")
534+
[ "$macos_x64_count" -eq 0 ] && missing+=("macOS x64 (.dmg/.pkg)")
535+
[ "$macos_arm64_count" -eq 0 ] && missing+=("macOS arm64 (.dmg/.pkg)")
536+
[ "$linux_modern_count" -eq 0 ] && missing+=("Linux modern (.deb/.rpm)")
537+
[ "$linux_debian12_count" -eq 0 ] && missing+=("Linux debian12-compat (.deb/.rpm)")
538+
[ "$linux_appimage_count" -eq 0 ] && missing+=("Linux AppImage (.AppImage/.zsync)")
539+
[ "$linux_arch_count" -eq 0 ] && missing+=("Linux Arch (.pkg.tar.zst)")
540+
541+
if [ ${#missing[@]} -gt 0 ]; then
542+
echo
543+
echo "ERROR: missing artifacts for the following groups:"
544+
printf " - %s\n" "${missing[@]}"
545+
echo
546+
echo "Refusing to publish an incomplete release."
547+
exit 1
548+
fi
549+
shell: bash
550+
551+
- name: Create or update draft release
552+
env:
553+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
554+
TAG: ${{ steps.version.outputs.tag }}
555+
VERSION: ${{ steps.version.outputs.version }}
556+
run: |
557+
set -euo pipefail
558+
if gh release view "$TAG" >/dev/null 2>&1; then
559+
# Release with this tag exists. Only clobber assets if it's still
560+
# a DRAFT — we never silently overwrite assets on a published
561+
# release. Operator must bump projectVersionName in
562+
# gradle/libs.versions.toml to roll a new tag.
563+
is_draft=$(gh release view "$TAG" --json isDraft -q '.isDraft')
564+
if [ "$is_draft" = "true" ]; then
565+
echo "Draft release $TAG already exists — replacing assets via --clobber..."
566+
gh release upload "$TAG" release-files/* --clobber
567+
else
568+
echo "ERROR: release $TAG is already PUBLISHED."
569+
echo "Refusing to clobber published assets."
570+
echo
571+
echo "If you intended to ship a new version, bump"
572+
echo "projectVersionName in gradle/libs.versions.toml first,"
573+
echo "then re-push to generate-installers."
574+
exit 1
575+
fi
576+
else
577+
echo "Creating new draft release $TAG..."
578+
gh release create "$TAG" \
579+
--draft \
580+
--title "$VERSION" \
581+
--generate-notes \
582+
release-files/*
583+
fi
584+
shell: bash

0 commit comments

Comments
 (0)