name: Release on: push: tags: ['v*'] workflow_dispatch: permissions: contents: read concurrency: group: release-${{ github.ref }} cancel-in-progress: false jobs: appimage: name: AppImage (AnyLinux) runs-on: ubuntu-24.04 timeout-minutes: 90 steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 submodules: recursive - name: Check release notes if: startsWith(github.ref, 'refs/tags/v') shell: bash run: ./scripts/release_notes.sh "$GITHUB_REF_NAME" >/dev/null - name: Build AppImage shell: bash env: GH_TOKEN: ${{ github.token }} run: | docker run --rm \ --volume "$GITHUB_WORKSPACE:/workspace" \ --workdir /workspace \ --env GH_TOKEN \ ghcr.io/archlinux/archlinux:base-devel@sha256:c3953446016873a756fb7814f10087cac1634c127f7302e80c81c512da796d05 bash -Eeuo pipefail -c ' pacman -Syu --noconfirm --needed \ cmake git ninja pkgconf lld sdl3 sdl3_ttf curl openssl \ nlohmann-json libyaml libelf minizip minizip-ng capstone gtk4 \ libadwaita webkitgtk-6.0 libutf8proc fontconfig libglvnd \ vulkan-headers zlib libplacebo bubblewrap xdg-dbus-proxy \ patchelf jq unzip file ca-certificates dbus zsync ./scripts/install_anylinux_dependencies.sh curl --fail --location --retry 3 \ --output /tmp/quick-sharun \ https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/2a025cef14483c5bc2a75b479071f4d5c58a906f/useful-tools/quick-sharun.sh echo "fa66d0189e1e87df781c049dfb23cbb1e753786056f693a4483d6d3af61e7ee1 /tmp/quick-sharun" | \ sha256sum --check --strict chmod 0755 /tmp/quick-sharun curl --fail --location --retry 3 \ --output /tmp/sharun \ https://github.com/pkgforge-dev/Anylinux-sharun/releases/download/2.2.6/sharun-x86_64 echo "a4d51752f9861b4870ca529fea04087310b28f8943cc55b99a95b777d4db92ec /tmp/sharun" | \ sha256sum --check --strict chmod 0755 /tmp/sharun curl --fail --location --retry 3 \ --output /tmp/anylinux.c \ https://raw.githubusercontent.com/pkgforge-dev/Anylinux-AppImages/2a025cef14483c5bc2a75b479071f4d5c58a906f/useful-tools/lib/anylinux.c echo "f50650ad96d177559bdd0737df509fa20bd4af08887631c738fc1f31bfac185f /tmp/anylinux.c" | \ sha256sum --check --strict curl --fail --location --retry 3 \ --output /tmp/appimagetool \ https://github.com/pkgforge-dev/appimagetool/releases/download/0.3.3/appimagetool-x86_64-linux echo "0d01a4e2628efc897be9663f0faeed6a171e1851270b4e1ce4c22434a36ecebd /tmp/appimagetool" | \ sha256sum --check --strict chmod 0755 /tmp/appimagetool curl --fail --location --retry 3 \ --output /tmp/uruntime \ https://github.com/VHSgunzo/uruntime/releases/download/v0.5.9/uruntime-appimage-dwarfs-lite-x86_64 echo "cef962c299f2fa19b2b3cdf2fa1565ee8541796cc89b9a97a591f94041e8b083 /tmp/uruntime" | \ sha256sum --check --strict chmod 0755 /tmp/uruntime curl --fail --location --retry 3 \ --output /tmp/mkdwarfs \ https://github.com/mhx/dwarfs/releases/download/v0.15.6/dwarfs-universal-0.15.6-Linux-x86_64 echo "50891c38ba359db8271819a6cbf6aaa8068681523f0c4f2b8242007a45edaa28 /tmp/mkdwarfs" | \ sha256sum --check --strict chmod 0755 /tmp/mkdwarfs git config --global --add safe.directory /workspace git config --global --add safe.directory /workspace/third_party/Vulkan-Headers git config --global --add safe.directory /workspace/third_party/libjnivm export MOCKTAIL_ANYLINUX_SYSTEM_INSTALL=1 export MOCKTAIL_ANYLINUX_SHARUN=/tmp/sharun export MOCKTAIL_ANYLINUX_C_SOURCE=/tmp/anylinux.c export RUNTIME=/tmp/uruntime export DWARFS_CMD=/tmp/mkdwarfs make appimage BUILD_DIR=build-appimage JOBS=4 \ APPIMAGE=dist/Mocktail-x86_64.AppImage \ PORTABLE_MODE=standalone APPIMAGE_FORMAT=anylinux \ ANYLINUX_PACKAGER=/tmp/quick-sharun \ ANYLINUX_APPIMAGETOOL=/tmp/appimagetool test -x dist/Mocktail-x86_64.AppImage ' - name: Smoke-test AppImage without FUSE shell: bash run: | smoke_dir="$(mktemp -d)" trap 'rm -rf -- "$smoke_dir"' EXIT export XDG_DATA_HOME="$smoke_dir/data" export XDG_CONFIG_HOME="$smoke_dir/config" export XDG_CACHE_HOME="$smoke_dir/cache" export XDG_STATE_HOME="$smoke_dir/state" mkdir -p "$XDG_DATA_HOME" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME" "$XDG_STATE_HOME" timeout 60s dist/Mocktail-x86_64.AppImage --appimage-extract-and-run --help timeout 60s dist/Mocktail-x86_64.AppImage --appimage-extract-and-run mocktail_updater status - name: Upload AppImage uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: Mocktail-AppImage path: dist/Mocktail-x86_64.AppImage if-no-files-found: error retention-days: 14 deb: name: DEB (Ubuntu 26.04) runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 submodules: recursive - name: Build DEB shell: bash run: | set -Eeuo pipefail docker run --rm \ --volume "$GITHUB_WORKSPACE:/workspace" \ --workdir /workspace \ --env MOCKTAIL_PACKAGE_VERSION="$(./scripts/package_version.sh)" \ ubuntu:26.04 bash -Eeuo pipefail -c ' export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install --yes --no-install-recommends \ build-essential cmake git ninja-build pkg-config lld fakeroot \ dpkg-dev file libsdl3-dev libsdl3-ttf-dev \ libcurl4-openssl-dev libssl-dev nlohmann-json3-dev \ libyaml-dev libelf-dev libminizip-dev libcapstone-dev \ libgtk-4-dev libadwaita-1-dev libwebkitgtk-6.0-dev \ libutf8proc-dev libfontconfig1-dev libegl-dev \ libvulkan-dev libplacebo-dev zlib1g-dev libpng-dev cmake -S . -B build-deb -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ -DMOCKTAIL_PACKAGE_NAME=nightcap \ -DMOCKTAIL_PACKAGE_VERSION="$MOCKTAIL_PACKAGE_VERSION" \ -DBUILD_TESTING=OFF cmake --build build-deb --parallel 4 cpack --config build-deb/CPackConfig.cmake \ -G DEB -B dist/deb dpkg-deb --info dist/deb/*.deb >/dev/null ' - name: Upload DEB uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: Nightcap-DEB path: dist/deb/*.deb if-no-files-found: error retention-days: 14 rpm: name: RPM (Fedora 44) runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 submodules: recursive - name: Build RPM shell: bash run: | set -Eeuo pipefail docker run --rm \ --volume "$GITHUB_WORKSPACE:/workspace" \ --workdir /workspace \ --env MOCKTAIL_PACKAGE_VERSION="$(./scripts/package_version.sh)" \ fedora:44 bash -Eeuo pipefail -c ' dnf install --assumeyes \ gcc-c++ cmake git ninja-build pkgconf-pkg-config lld rpm-build \ SDL3-devel SDL3_ttf-devel libcurl-devel openssl-devel \ nlohmann-json-devel libyaml-devel elfutils-libelf-devel \ minizip-ng-compat-devel capstone-devel gtk4-devel libadwaita-devel \ webkitgtk6.0-devel utf8proc-devel fontconfig-devel \ libglvnd-devel vulkan-headers vulkan-loader-devel \ libplacebo-devel zlib-ng-compat-devel libpng-devel cmake -S . -B build-rpm -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_LIBDIR=lib \ -DMOCKTAIL_PACKAGE_NAME=nightcap \ -DMOCKTAIL_PACKAGE_VERSION="$MOCKTAIL_PACKAGE_VERSION" \ -DBUILD_TESTING=OFF cmake --build build-rpm --parallel 4 cpack --config build-rpm/CPackConfig.cmake \ -G RPM -B dist/rpm rpm --query --package --info dist/rpm/*.rpm >/dev/null ' - name: Upload RPM uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: Nightcap-RPM path: dist/rpm/*.rpm if-no-files-found: error retention-days: 14 arch: name: Pacman package (Arch Linux) runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 submodules: recursive - name: Build pacman package shell: bash run: | set -Eeuo pipefail version="$(./scripts/package_version.sh)" sed -i "s/^pkgver=.*/pkgver=${version}/" packaging/arch/PKGBUILD docker run --rm \ --volume "$GITHUB_WORKSPACE:/workspace" \ --workdir /workspace \ ghcr.io/archlinux/archlinux:base-devel@sha256:c3953446016873a756fb7814f10087cac1634c127f7302e80c81c512da796d05 bash -Eeuo pipefail -c ' pacman -Syu --needed --noconfirm \ cmake git ninja pkgconf lld sdl3 sdl3_ttf curl openssl \ nlohmann-json libyaml libelf minizip capstone gtk4 \ libadwaita webkitgtk-6.0 libutf8proc fontconfig libpng \ libplacebo vulkan-headers vulkan-icd-loader libglvnd zlib useradd --create-home builder chown -R builder:builder /workspace runuser -u builder -- env MOCKTAIL_SOURCE_DIR=/workspace \ makepkg --dir /workspace/packaging/arch \ --noconfirm --cleanbuild --force install -d dist/arch cp packaging/arch/*.pkg.tar.zst dist/arch/ pacman -Qp dist/arch/*.pkg.tar.zst >/dev/null ' - name: Upload pacman package uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: Nightcap-Arch path: dist/arch/*.pkg.tar.zst if-no-files-found: error retention-days: 14 publish: name: Publish GitHub release if: startsWith(github.ref, 'refs/tags/v') needs: [appimage, deb, rpm, arch] runs-on: ubuntu-24.04 timeout-minutes: 15 permissions: contents: write steps: - name: Check out source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download packages uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: 'Nightcap-*' merge-multiple: true path: release - name: Download AppImage uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: Mocktail-AppImage path: release - name: Create release shell: bash env: GH_TOKEN: ${{ github.token }} run: | set -Eeuo pipefail tag="${GITHUB_REF_NAME}" mv release/Mocktail-x86_64.AppImage release/Nightcap-x86_64.AppImage # An unmatched glob would otherwise reach sha256sum and gh as its own # literal text, so every package pattern has to match before upload. shopt -s nullglob assets=(Nightcap-x86_64.AppImage) for glob in '*.deb' '*.rpm' '*.pkg.tar.zst'; do matched=(release/$glob) if [[ ${#matched[@]} -eq 0 ]]; then echo "::error::no ${glob} package among the release artifacts" exit 1 fi assets+=("${matched[@]#release/}") done uploads=() for asset in "${assets[@]}"; do uploads+=("release/$asset" "release/$asset.sha256") done ( cd release for asset in "${assets[@]}"; do sha256sum "$asset" > "$asset.sha256" done ) ./scripts/release_notes.sh "$tag" > release/notes.md # The Flatpak workflow creates the same release; whichever job # arrives second sees "already exists" and continues. if ! gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then gh release create "$tag" --repo "$GITHUB_REPOSITORY" \ --title "Nightcap $tag" --notes-file release/notes.md || gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null fi gh release edit "$tag" --repo "$GITHUB_REPOSITORY" \ --title "Nightcap $tag" --notes-file release/notes.md gh release upload "$tag" --repo "$GITHUB_REPOSITORY" --clobber \ "${uploads[@]}" # nightcap-bin downloads the pacman package from the release page, so this # waits for the upload. aur: name: Publish AUR packages if: startsWith(github.ref, 'refs/tags/v') needs: publish uses: ./.github/workflows/aur-publish.yml with: tag: ${{ github.ref_name }} secrets: AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}