diff --git a/.github/workflows/hyprcosmic.yml b/.github/workflows/hyprcosmic.yml new file mode 100644 index 0000000..4492697 --- /dev/null +++ b/.github/workflows/hyprcosmic.yml @@ -0,0 +1,152 @@ +# Build the compositor on the three distributions HyprCosmic targets. +# +# WHY THIS IS A SECOND FILE +# ------------------------- +# ci.yml beside it is upstream's, and it stays untouched. It asks a different +# question -- rustfmt, clippy, and whether the feature flags still compile -- on +# a single Ubuntu runner, and none of that stops being worth asking because the +# repository was forked. Replacing it would also mean carrying a conflict into +# every rebase against pop-os/cosmic-comp, for no gain. This file is additive, +# which is the same rule the rest of the fork follows. +# +# WHY CONTAINERS RATHER THAN ONE RUNNER +# ------------------------------------- +# The interesting failure is never "does Rust compile this" -- it is "does this +# distribution have a package called libseat-dev". That question cannot be asked +# from a single Ubuntu runner, so each distribution builds in its own image with +# its own package manager and its own names. A job failing here means a real +# user of that distribution could not have built it either. +# +# WHY RUSTUP AND NOT THE DISTRIBUTION'S RUST +# ------------------------------------------ +# Cargo.toml asks for edition 2024 and rust-version 1.93, and rust-toolchain.toml +# pins channel 1.93 with rust-src. Debian bookworm ships rustc 1.63, so on one of +# the three targets the packaged toolchain cannot build this at all. rustup is +# what makes the three jobs comparable -- and because it reads +# rust-toolchain.toml, all three get the pinned compiler rather than whatever +# each distribution happened to freeze. +name: HyprCosmic + +on: + push: + branches: [master] + pull_request: + workflow_dispatch: + +# A full matrix here is tens of minutes per distribution. Superseding a run that +# is already obsolete costs nothing and keeps a queue from forming behind it. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 + +jobs: + build: + name: ${{ matrix.distro }} + runs-on: ubuntu-latest + container: ${{ matrix.image }} + strategy: + # One distribution failing on a package name is worth seeing on its own. + # Cancelling its siblings would hide whether the break is universal or + # local to that distribution's naming, which is the whole point of the + # matrix. + fail-fast: false + matrix: + include: + - distro: fedora + image: fedora:latest + - distro: debian + image: debian:bookworm + - distro: arch + image: archlinux:latest + + steps: + # Before checkout, deliberately: actions/checkout needs git in the image, + # and these containers are bare. + # + # The library list is upstream's own, from debian/control, translated per + # distribution rather than trimmed. Four of them -- wayland, EGL, + # fontconfig and xcb -- proved unnecessary to build on a Fedora workstation + # with none of them installed, but that is a fact about one machine's + # feature flags, not a licence to drop what upstream says it needs. + - name: Install build dependencies (fedora) + if: matrix.distro == 'fedora' + run: | + dnf -y install --setopt=install_weak_deps=False \ + git curl gcc gcc-c++ cmake pkgconf-pkg-config \ + wayland-devel libxkbcommon-devel libinput-devel libseat-devel \ + systemd-devel mesa-libgbm-devel mesa-libEGL-devel pixman-devel \ + libdisplay-info-devel fontconfig-devel libxcb-devel + + - name: Install build dependencies (debian) + if: matrix.distro == 'debian' + run: | + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + git curl ca-certificates build-essential cmake pkg-config \ + libwayland-dev libxkbcommon-dev libinput-dev libseat-dev \ + libsystemd-dev libudev-dev libgbm-dev libegl1-mesa-dev \ + libpixman-1-dev libdisplay-info-dev libfontconfig-dev libxcb1-dev + + # Arch keeps headers in the main packages rather than split -devel ones, + # so this list is shorter by construction, not by omission. + - name: Install build dependencies (arch) + if: matrix.distro == 'arch' + run: | + pacman -Syu --noconfirm --needed \ + git curl base-devel cmake pkgconf \ + wayland libxkbcommon libinput seatd systemd-libs mesa pixman \ + libdisplay-info fontconfig libxcb + + - uses: actions/checkout@v4 + + # --default-toolchain none, then let rust-toolchain.toml choose. Naming a + # version here would create a second place to update and a silent way for + # CI to test a compiler the project does not use. + - name: Install Rust + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ + | sh -s -- -y --default-toolchain none --profile minimal + echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" + + - name: Show toolchain + run: | + rustup show + cargo --version + + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.distro }} + + - name: Build + run: cargo build --release --locked + + - name: Test + run: cargo test --release --locked + + # Staged into DESTDIR so the assertions below can inspect the result + # without needing root or a live system. + - name: Install into a staging root + run: make install DESTDIR="$PWD/stage" prefix=/usr + + # These two assertions are Patch D as an executable statement. HyprCosmic + # installs beside COSMIC rather than over it, which is what keeps the stock + # session available to log into when this compositor will not start. If a + # future edit sends the binary back to $(bindir)/cosmic-comp, that stops + # being true silently -- unless something fails here. + - name: Assert it installs beside COSMIC, not over it + run: | + set -eux + test -x stage/usr/libexec/hyprcosmic/cosmic-comp + test ! -e stage/usr/bin/cosmic-comp + test ! -e stage/usr/share/cosmic/com.system76.CosmicSettings.Shortcuts/v1/defaults + find stage -type f -printf '%M %10s %P\n' + + - uses: actions/upload-artifact@v4 + with: + name: cosmic-comp-${{ matrix.distro }} + path: stage/ + retention-days: 14