diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index b10c25d..ef4786c 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -1,39 +1,47 @@ -name: Native packages +name: Nightly AppImage on: - push: - branches: [main] - paths-ignore: - - '.github/workflows/ci.yml' - - '.gitignore' - - 'README.md' - - 'assets/screenshots/**' - - 'docs/**' - - 'packaging/aur/**' - - 'scripts/build_flatpak.sh' - - 'tests/**' - pull_request: - paths-ignore: - - '.github/workflows/ci.yml' - - '.gitignore' - - 'README.md' - - 'assets/screenshots/**' - - 'docs/**' - - 'packaging/aur/**' - - 'scripts/build_flatpak.sh' - - 'tests/**' + schedule: + # 05:00 UTC daily. A run whose commit already carries the continuous tag + # exits without rebuilding, so a quiet day costs one probe job. + - cron: '0 5 * * *' workflow_dispatch: permissions: contents: read concurrency: - group: packages-${{ github.ref }} - cancel-in-progress: true + group: nightly-appimage + cancel-in-progress: false jobs: + probe: + name: Check for new commits + runs-on: ubuntu-24.04 + timeout-minutes: 5 + outputs: + build: ${{ steps.decide.outputs.build }} + steps: + - name: Compare HEAD against the published continuous tag + id: decide + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + set -Eeuo pipefail + published="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/continuous" \ + --jq .object.sha 2>/dev/null || true)" + if [[ "$GITHUB_EVENT_NAME" == "schedule" && "$published" == "$GITHUB_SHA" ]]; then + echo 'build=false' >>"$GITHUB_OUTPUT" + echo "continuous already points at $GITHUB_SHA; nothing to build" + else + echo 'build=true' >>"$GITHUB_OUTPUT" + fi + appimage: name: AppImage (AnyLinux) + needs: probe + if: needs.probe.outputs.build == 'true' runs-on: ubuntu-24.04 timeout-minutes: 90 steps: @@ -138,155 +146,17 @@ jobs: - name: Upload AppImage uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: Mocktail-AppImage + name: Nightcap-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: | - nightly_suffix=".nightly.$(git show -s --format=%cd --date=format:%Y%m%d%H%M%S "$GITHUB_SHA").g${GITHUB_SHA:0:8}" - docker run --rm \ - --volume "$GITHUB_WORKSPACE:/workspace" \ - --workdir /workspace \ - --env MOCKTAIL_PACKAGE_VERSION_SUFFIX="$nightly_suffix" \ - 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 - cmake -S . -B build-deb -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DMOCKTAIL_PACKAGE_NAME=mocktail-nightly \ - -DMOCKTAIL_PACKAGE_VERSION_SUFFIX="$MOCKTAIL_PACKAGE_VERSION_SUFFIX" \ - -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: Mocktail-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: | - nightly_suffix=".nightly.$(git show -s --format=%cd --date=format:%Y%m%d%H%M%S "$GITHUB_SHA").g${GITHUB_SHA:0:8}" - docker run --rm \ - --volume "$GITHUB_WORKSPACE:/workspace" \ - --workdir /workspace \ - --env MOCKTAIL_PACKAGE_VERSION_SUFFIX="$nightly_suffix" \ - 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 - cmake -S . -B build-rpm -G Ninja \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_INSTALL_LIBDIR=lib \ - -DMOCKTAIL_PACKAGE_NAME=mocktail-nightly \ - -DMOCKTAIL_PACKAGE_VERSION_SUFFIX="$MOCKTAIL_PACKAGE_VERSION_SUFFIX" \ - -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: Mocktail-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: | - docker run --rm \ - --volume "$GITHUB_WORKSPACE:/workspace" \ - --workdir /workspace \ - archlinux:base-devel 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 \ - 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: Mocktail-Arch - path: dist/arch/*.pkg.tar.zst - if-no-files-found: error - retention-days: 14 - publish: - name: Publish continuous packages - if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - needs: [appimage, deb, rpm, arch] + name: Publish continuous release + needs: [probe, appimage] + # A manual run from another branch still builds and smoke-tests, but the + # continuous tag and release only ever follow main. + if: needs.probe.outputs.build == 'true' && github.ref == 'refs/heads/main' runs-on: ubuntu-24.04 timeout-minutes: 30 permissions: @@ -297,84 +167,49 @@ jobs: with: fetch-depth: 0 - - name: Download packages + - name: Download AppImage uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - pattern: Mocktail-* + name: Nightcap-AppImage path: release - merge-multiple: true - - name: Prepare continuous packages + - name: Name and checksum the nightly build shell: bash run: | set -Eeuo pipefail - mv -- release/*.AppImage release/mocktail-nightly.AppImage - mv -- release/*.deb release/mocktail-nightly.deb - mv -- release/*.rpm release/mocktail-nightly.rpm - mv -- release/*.pkg.tar.zst release/mocktail-nightly.pkg.tar.zst + # The Makefile builds under upstream's artifact name; the published + # asset carries this fork's. + mv -- release/Mocktail-x86_64.AppImage release/Nightcap-nightly-x86_64.AppImage + (cd release && sha256sum Nightcap-nightly-x86_64.AppImage \ + > Nightcap-nightly-x86_64.AppImage.sha256) find release -maxdepth 1 -type f -print - - name: Build package repositories - shell: bash - env: - GH_TOKEN: ${{ github.token }} - FLATPAK_GPG_PRIVATE_KEY: ${{ secrets.FLATPAK_GPG_PRIVATE_KEY }} - FLATPAK_GPG_KEY_ID: ${{ secrets.FLATPAK_GPG_KEY_ID }} - run: | - set -Eeuo pipefail - [[ -n "$FLATPAK_GPG_PRIVATE_KEY" && -n "$FLATPAK_GPG_KEY_ID" ]] - sudo apt-get update - sudo apt-get install --yes --no-install-recommends \ - apt-utils createrepo-c gnupg rpm - install -d stable/deb stable/rpm - stable_tag="$(gh api "repos/$GITHUB_REPOSITORY/releases/latest" --jq .tag_name)" - gh release download "$stable_tag" --pattern '*.deb' --dir stable/deb - gh release download "$stable_tag" --pattern '*.rpm' --dir stable/rpm - mapfile -t stable_debs < <(find stable/deb -maxdepth 1 -type f -name '*.deb' -print) - mapfile -t stable_rpms < <(find stable/rpm -maxdepth 1 -type f -name '*.rpm' -print) - [[ "${#stable_debs[@]}" -eq 1 && "${#stable_rpms[@]}" -eq 1 ]] - install -d -m 0700 "$RUNNER_TEMP/mocktail-native-gnupg" - printf '%s' "$FLATPAK_GPG_PRIVATE_KEY" | \ - gpg --batch --homedir "$RUNNER_TEMP/mocktail-native-gnupg" --import - gpg --batch --homedir "$RUNNER_TEMP/mocktail-native-gnupg" \ - --export "$FLATPAK_GPG_KEY_ID" >mocktail-packages.gpg - ./scripts/assemble_native_repositories.sh \ - "${stable_debs[0]}" release/mocktail-nightly.deb \ - "${stable_rpms[0]}" release/mocktail-nightly.rpm \ - mocktail-packages.gpg "$FLATPAK_GPG_KEY_ID" \ - "$RUNNER_TEMP/mocktail-native-gnupg" native-repositories - - name: Update continuous release shell: bash env: GH_TOKEN: ${{ github.token }} run: | set -Eeuo pipefail - git config user.name komaruworld - git config user.email rtysus228@gmail.com + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' git tag --force continuous "$GITHUB_SHA" git push origin refs/tags/continuous --force + notes="Automated build of main at ${GITHUB_SHA:0:8}. Untested and unreleased; use a tagged release for normal play." if ! gh release view continuous >/dev/null 2>&1; then gh release create continuous \ --prerelease \ - --title "Mocktail continuous" \ - --notes "Automated development packages from main." + --title "Nightcap continuous" \ + --notes "$notes" fi + gh release edit continuous --title "Nightcap continuous" --notes "$notes" gh release upload continuous release/* --clobber + # Drop assets left by earlier runs under other names. while IFS= read -r asset; do case "$asset" in - mocktail-nightly.AppImage|mocktail-nightly.deb|mocktail-nightly.rpm|mocktail-nightly.pkg.tar.zst) + Nightcap-nightly-x86_64.AppImage|Nightcap-nightly-x86_64.AppImage.sha256) ;; - Mocktail-*.AppImage|mocktail_*.deb|mocktail-*.deb|mocktail-*.rpm|mocktail-*.pkg.tar.zst) + *) gh release delete-asset continuous "$asset" --yes ;; esac done < <(gh release view continuous --json assets --jq '.assets[].name') - - - name: Upload package repositories - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: Mocktail-native-repositories - path: native-repositories - if-no-files-found: error - retention-days: 14 diff --git a/tests/native_packaging_test.sh b/tests/native_packaging_test.sh index acd8e71..bc9577c 100755 --- a/tests/native_packaging_test.sh +++ b/tests/native_packaging_test.sh @@ -86,34 +86,35 @@ grep -Fq 'mz_stream_tell(unzGetStream(archive))' "${ANDROID_STUB}" || Fail 'Android assets do not support the minizip-ng offset API' for expected in \ - 'ubuntu:26.04' \ - 'fedora:44' \ - 'archlinux:base-devel' \ - 'minizip-ng-compat-devel' \ - '-G DEB' \ - '-G RPM' \ - 'makepkg --dir' \ + 'cron:' \ 'APPIMAGE_FORMAT=anylinux' \ 'quick-sharun' \ './scripts/install_anylinux_dependencies.sh' \ + '--env GH_TOKEN' \ 'MOCKTAIL_ANYLINUX_SYSTEM_INSTALL=1' \ '--appimage-extract-and-run mocktail_updater status' \ 'Mocktail-x86_64.AppImage' \ + 'Nightcap-nightly-x86_64.AppImage' \ + 'github-actions[bot]' \ 'gh release upload continuous'; do grep -Fq -- "${expected}" "${WORKFLOW}" || - Fail "native package workflow is missing: ${expected}" + Fail "nightly AppImage workflow is missing: ${expected}" done -grep -Fq 'paths-ignore:' "${WORKFLOW}" || - Fail 'native package workflow has no path filters' -grep -Fq "'assets/screenshots/**'" "${WORKFLOW}" || - Fail 'native packages rebuild for screenshot-only changes' -if grep -Fq "'packaging/flatpak/**'" "${WORKFLOW}"; then - Fail 'native packages ignore Flatpak changes required by Pages publication' -fi -if grep -Fq "'site/**'" "${WORKFLOW}"; then - Fail 'native packages ignore website changes required by Pages publication' -fi +# The nightly runs on a schedule and on demand. Per-commit triggers would +# rebuild a full AppImage for every push and pull request. The DEB, RPM and +# pacman packages are built by the Makefile but are not published from here; +# upstream ships those for unmodified Mocktail. +for unexpected in \ + 'push:' \ + 'pull_request:' \ + '-G DEB' \ + '-G RPM' \ + 'makepkg --dir'; do + if grep -Fq -- "${unexpected}" "${WORKFLOW}"; then + Fail "nightly AppImage workflow should not contain: ${unexpected}" + fi +done grep -Fq 'Ubuntu 26.04+' "${README}" || Fail 'README has no Ubuntu source dependency guide'