ci(linux): migrate Archlinux build to GitHub workflow (#4478)

This commit is contained in:
David Lane
2025-12-07 09:01:57 -05:00
committed by GitHub
parent 35f4b9ee51
commit 75809f13e3
8 changed files with 292 additions and 188 deletions

182
.github/workflows/ci-archlinux.yml vendored Normal file
View File

@ -0,0 +1,182 @@
---
name: CI-Archlinux
permissions:
contents: read
on:
workflow_call:
inputs:
release_commit:
required: true
type: string
release_version:
required: true
type: string
jobs:
build_archlinux:
name: Archlinux
env:
_use_cuda: true
_run_unit_tests: true
_support_headless_testing: true
BRANCH: ${{ github.head_ref || github.ref_name }}
BUILD_VERSION: ${{ inputs.release_version }}
CLONE_URL: ${{ github.event.repository.clone_url }}
COMMIT: ${{ inputs.release_commit }}
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:base-devel
options: --cpus 4 --memory 8g
steps:
- name: Update keyring
shell: bash
run: |
# Update keyring to avoid signature errors, and update system
pacman -Syy --disable-download-timeout --needed --noconfirm \
archlinux-keyring
pacman -Syu --disable-download-timeout --noconfirm
pacman -Scc --noconfirm
- name: Setup builder user
shell: bash
run: |
# arch prevents running makepkg as root
useradd -m builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
- name: Patch build flags
shell: bash
run: |
# shellcheck disable=SC2016
sed -i 's,#MAKEFLAGS="-j2",MAKEFLAGS="-j$(nproc)",g' /etc/makepkg.conf
- name: Install dependencies
shell: bash
run: |
pacman -Syu --disable-download-timeout --needed --noconfirm \
base-devel \
cmake \
cuda \
git \
namcap \
xorg-server-xvfb
pacman -Scc --noconfirm
- name: Checkout
uses: actions/checkout@v6
- name: Fix workspace permissions
shell: bash
run: |
# Give builder user ownership of the workspace
chown -R builder:builder "${GITHUB_WORKSPACE}"
- name: Configure PKGBUILD
shell: bash
run: |
# Calculate sub_version
sub_version=""
if [[ "${BRANCH}" != "master" ]]; then
sub_version=".r${COMMIT}"
fi
# Configure PKGBUILD file (as root)
mkdir -p build
cd build
cmake \
-DSUNSHINE_CONFIGURE_ONLY=ON \
-DSUNSHINE_CONFIGURE_PKGBUILD=ON \
-DSUNSHINE_SUB_VERSION="${sub_version}" \
..
# Make sure builder can read from build directory
chmod -R a+rX "${GITHUB_WORKSPACE}/build"
- name: Prepare PKGBUILD Package
shell: bash
run: |
# Create pkg directory and move files (as root)
mkdir -p pkg
mv build/PKGBUILD pkg/
mv build/sunshine.install pkg/
# Change ownership to builder
chown -R builder:builder pkg
# Run makepkg as builder user
cd pkg
sudo -u builder makepkg --printsrcinfo | tee .SRCINFO
# create a PKGBUILD archive
cd ..
tar -czf sunshine.pkg.tar.gz -C pkg .
- name: Build PKGBUILD
env:
DISPLAY: :1
id: build
shell: bash
working-directory: pkg
run: |
# Add problem matcher
echo "::add-matcher::.github/matchers/gcc.json"
source /etc/profile # ensure cuda is in the PATH
# Run Xvfb for headless testing
Xvfb "${DISPLAY}" -screen 0 1024x768x24 &
# Check PKGBUILD
sudo -u builder namcap -i PKGBUILD
# Export PKGBUILD options so they're available to makepkg
export _use_cuda="${_use_cuda}"
export _run_unit_tests="${_run_unit_tests}"
export _support_headless_testing="${_support_headless_testing}"
# Build the package as builder user (pass through environment variables)
sudo -u builder env \
_use_cuda="${_use_cuda}" \
_run_unit_tests="${_run_unit_tests}" \
_support_headless_testing="${_support_headless_testing}" \
makepkg -si --noconfirm
# Remove debug package
rm -f sunshine-debug*.pkg.tar.zst
# Remove problem matcher
echo "::remove-matcher owner=gcc::"
- name: Upload coverage artifact
if: >-
always() &&
(steps.build.outcome == 'success' || steps.build.outcome == 'failure')
uses: actions/upload-artifact@v5
with:
name: coverage-Archlinux
path: |
pkg/src/build/coverage.xml
pkg/src/build/tests/test_results.xml
if-no-files-found: error
- name: Copy Artifacts
shell: bash
run: |
# create artifacts directory
mkdir -p artifacts
# Copy built packages to artifacts
cp pkg/sunshine*.pkg.tar.zst artifacts/
cp sunshine.pkg.tar.gz artifacts/
# List artifacts
ls -la artifacts/
- name: Upload Artifacts
uses: actions/upload-artifact@v5
with:
name: build-Archlinux
path: artifacts/
if-no-files-found: error

View File

@ -156,8 +156,7 @@ jobs:
if: >-
always() &&
matrix.release != true &&
(steps.test.outcome == 'success' || steps.test.outcome == 'failure') &&
startsWith(github.repository, 'LizardByte/')
(steps.test.outcome == 'success' || steps.test.outcome == 'failure')
uses: actions/upload-artifact@v5
with:
name: coverage-Homebrew-${{ matrix.os_name }}-${{ matrix.os_version }}

View File

@ -191,7 +191,9 @@ jobs:
- name: Generate gcov report
id: test_report
# any except canceled or skipped
if: always() && (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
if: >-
always() &&
(steps.test.outcome == 'success' || steps.test.outcome == 'failure')
shell: msys2 {0}
working-directory: build
run: |

View File

@ -99,6 +99,14 @@ jobs:
release_commit: ${{ needs.release-setup.outputs.release_commit }}
release_version: ${{ needs.release-setup.outputs.release_version }}
build-archlinux:
name: Archlinux
needs: release-setup
uses: ./.github/workflows/ci-archlinux.yml
with:
release_commit: ${{ needs.release-setup.outputs.release_commit }}
release_version: ${{ needs.release-setup.outputs.release_version }}
build-linux-copr:
name: Linux Copr
if: github.event_name != 'push' # releases are handled directly in ci-copr.yml
@ -143,6 +151,7 @@ jobs:
needs:
- build-freebsd
- build-linux
- build-archlinux
- build-linux-flatpak
- build-homebrew
- build-windows
@ -160,6 +169,9 @@ jobs:
- name: Linux-AppImage
coverage: true
pr: true
- name: Archlinux
coverage: true
pr: true
- name: Homebrew-macos-14
coverage: false
pr: true
@ -227,11 +239,12 @@ jobs:
startsWith(github.repository, 'LizardByte/')
needs:
- release-setup
- build-archlinux
- build-docker
- build-freebsd
- build-homebrew
- build-linux
- build-linux-flatpak
- build-homebrew
- build-windows
runs-on: ubuntu-latest
steps:

View File

@ -24,7 +24,6 @@ ENTRYPOINT steam && sunshine
### SUNSHINE_OS
Sunshine images are available with the following tag suffixes, based on their respective base images.
- `archlinux`
- `debian-bookworm`
- `ubuntu-22.04`
- `ubuntu-24.04`
@ -153,7 +152,6 @@ The architectures supported by these images are shown in the table below.
| tag suffix | amd64/x86_64 | arm64/aarch64 |
|-----------------|--------------|---------------|
| archlinux | ✅ | ❌ |
| debian-bookworm | ✅ | ✅ |
| ubuntu-22.04 | ✅ | ✅ |
| ubuntu-24.04 | ✅ | ✅ |

View File

@ -1,173 +0,0 @@
# syntax=docker/dockerfile:1
# artifacts: true
# platforms: linux/amd64
# archlinux does not have an arm64 base image
# no-cache-filters: artifacts,sunshine
ARG BASE=archlinux/archlinux
ARG TAG=base-devel
FROM ${BASE}:${TAG} AS sunshine-base
# Update keyring to avoid signature errors, and update system
RUN <<_DEPS
#!/bin/bash
set -e
pacman -Syy --disable-download-timeout --needed --noconfirm \
archlinux-keyring
pacman -Syu --disable-download-timeout --noconfirm
pacman -Scc --noconfirm
_DEPS
FROM sunshine-base AS sunshine-deps
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install dependencies first - this layer will be cached
RUN <<_SETUP
#!/bin/bash
set -e
# Setup builder user, arch prevents running makepkg as root
useradd -m builder
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
# patch the build flags
# shellcheck disable=SC2016
sed -i 's,#MAKEFLAGS="-j2",MAKEFLAGS="-j$(nproc)",g' /etc/makepkg.conf
# install dependencies
pacman -Syu --disable-download-timeout --needed --noconfirm \
base-devel \
cmake \
cuda \
git \
namcap \
xorg-server-xvfb
pacman -Scc --noconfirm
_SETUP
FROM sunshine-deps AS sunshine-build
ARG BRANCH
ARG BUILD_VERSION
ARG COMMIT
ARG CLONE_URL
# note: BUILD_VERSION may be blank
ENV BRANCH=${BRANCH}
ENV BUILD_VERSION=${BUILD_VERSION}
ENV COMMIT=${COMMIT}
ENV CLONE_URL=${CLONE_URL}
# PKGBUILD options
ENV _use_cuda=true
ENV _run_unit_tests=true
ENV _support_headless_testing=true
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Setup builder user
USER builder
# copy repository
WORKDIR /build/sunshine/
COPY --link .. .
# setup build directory
WORKDIR /build/sunshine/build
# configure PKGBUILD file
RUN <<_MAKE
#!/bin/bash
set -e
sub_version=""
if [[ "${BRANCH}" != "master" ]]; then
sub_version=".r${COMMIT}"
fi
cmake \
-DSUNSHINE_CONFIGURE_ONLY=ON \
-DSUNSHINE_CONFIGURE_PKGBUILD=ON \
-DSUNSHINE_SUB_VERSION="${sub_version}" \
/build/sunshine
_MAKE
WORKDIR /build/sunshine/pkg
RUN <<_PACKAGE
mv /build/sunshine/build/PKGBUILD .
mv /build/sunshine/build/sunshine.install .
makepkg --printsrcinfo > .SRCINFO
_PACKAGE
# create a PKGBUILD archive
USER root
RUN <<_REPO
#!/bin/bash
set -e
tar -czf /build/sunshine/sunshine.pkg.tar.gz .
_REPO
# namcap and build PKGBUILD file
USER builder
RUN <<_PKGBUILD
#!/bin/bash
set -e
# shellcheck source=/dev/null
source /etc/profile # ensure cuda is in the PATH
export DISPLAY=:1
Xvfb ${DISPLAY} -screen 0 1024x768x24 &
namcap -i PKGBUILD
makepkg -si --noconfirm
rm -f /build/sunshine/pkg/sunshine-debug*.pkg.tar.zst
ls -a
_PKGBUILD
FROM sunshine-base AS sunshine
COPY --link --from=sunshine-build /build/sunshine/pkg/sunshine*.pkg.tar.zst /sunshine.pkg.tar.zst
# artifacts to be extracted in CI
COPY --link --from=sunshine-build /build/sunshine/pkg/sunshine*.pkg.tar.zst /artifacts/sunshine.pkg.tar.zst
COPY --link --from=sunshine-build /build/sunshine/sunshine.pkg.tar.gz /artifacts/sunshine.pkg.tar.gz
# install sunshine
RUN <<_INSTALL_SUNSHINE
#!/bin/bash
set -e
pacman -U --disable-download-timeout --needed --noconfirm \
/sunshine.pkg.tar.zst
pacman -Scc --noconfirm
_INSTALL_SUNSHINE
# network setup
EXPOSE 47984-47990/tcp
EXPOSE 48010
EXPOSE 47998-48000/udp
# setup user
ARG PGID=1000
ENV PGID=${PGID}
ARG PUID=1000
ENV PUID=${PUID}
ENV TZ="UTC"
ARG UNAME=lizard
ENV UNAME=${UNAME}
ENV HOME=/home/$UNAME
# setup user
RUN <<_SETUP_USER
#!/bin/bash
set -e
groupadd -f -g "${PGID}" "${UNAME}"
useradd -lm -d ${HOME} -s /bin/bash -g "${PGID}" -u "${PUID}" "${UNAME}"
mkdir -p ${HOME}/.config/sunshine
ln -s ${HOME}/.config/sunshine /config
chown -R ${UNAME} ${HOME}
_SETUP_USER
USER ${UNAME}
WORKDIR ${HOME}
# entrypoint
ENTRYPOINT ["/usr/bin/sunshine"]

View File

@ -2,7 +2,7 @@
# Reference: https://wiki.archlinux.org/title/PKGBUILD
## options
: "${_run_unit_tests:=false}" # if set to true; unit tests will be executed post build; useful in CI
: "${_run_unit_tests:=false}" # if set to true; unit tests will be executed post build; useful in CI
: "${_support_headless_testing:=false}"
: "${_use_cuda:=detect}" # nvenc
@ -55,6 +55,10 @@ makedepends=(
'npm'
)
checkdepends=(
'gcovr'
)
optdepends=(
'libva-mesa-driver: AMD GPU encoding support'
)
@ -160,16 +164,46 @@ build() {
}
check() {
cd "${srcdir}/build"
./sunshine --version
if [[ "${_run_unit_tests::1}" == "t" ]]; then
export CC="gcc-${_gcc_version}"
export CXX="g++-${_gcc_version}"
cd "${srcdir}/build/tests"
./test_sunshine --gtest_color=yes
./test_sunshine --gtest_color=yes --gtest_output=xml:test_results.xml
# Generate coverage report
# Run gcovr from the build directory (where all .gcda/.gcno files are)
# This matches the pattern used in ci-linux.yml
cd "${srcdir}/build"
# Dynamically find the gcov executable from gcc's library directory
# This ensures we use the same gcov version as the compiler
local gcov_path
gcov_path=$(find /usr/lib/gcc/x86_64-pc-linux-gnu/${_gcc_version}.*/ -name gcov -type f 2>/dev/null | head -n 1)
if [ -z "$gcov_path" ]; then
# Fallback to standard gcov if not found
gcov_path="gcov"
fi
echo "Using gcov at: $gcov_path"
# Use the actual relative path to the source directory
# From ${srcdir}/build, the source is at ../${pkgname}/src
gcovr --gcov-executable "$gcov_path" . -r "../${pkgname}/src" \
--exclude-noncode-lines \
--exclude-throw-branches \
--exclude-unreachable-branches \
--verbose \
--xml-pretty \
-o coverage.xml
# Post-process the coverage XML to strip the absolute path and show only 'src'
sed -i "s|${srcdir}/${pkgname}/src|src|g" coverage.xml
fi
cd "${srcdir}/build"
./sunshine --version
}
package() {

View File

@ -19,6 +19,45 @@ include_directories("${GTEST_SOURCE_DIR}/googletest/include" "${GTEST_SOURCE_DIR
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage -ggdb -O0")
set(CMAKE_C_FLAGS "-fprofile-arcs -ftest-coverage -ggdb -O0")
# Find the correct libgcov library path matching the gcc compiler version
# This ensures the test executable links against the same libgcov version used during compilation
if(UNIX AND NOT APPLE)
# Get the gcc compiler version
execute_process(
COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Extract major version
string(REGEX MATCH "^[0-9]+" GCC_MAJOR_VERSION "${GCC_VERSION}")
# Search for the gcc library directory matching this version
file(GLOB GCC_LIB_DIRS "/usr/lib/gcc/*/*${GCC_MAJOR_VERSION}.*")
if(GCC_LIB_DIRS)
list(GET GCC_LIB_DIRS 0 GCC_LIB_DIR)
message(STATUS "Found GCC library directory: ${GCC_LIB_DIR}")
# Look for libgcov.a in the gcc library directory
find_library(LIBGCOV_LIBRARY
NAMES gcov
PATHS ${GCC_LIB_DIR}
NO_DEFAULT_PATH
)
if(LIBGCOV_LIBRARY)
message(STATUS "Found libgcov: ${LIBGCOV_LIBRARY}")
# Store this to link against later
set(GCOV_LINK_LIBRARY ${LIBGCOV_LIBRARY})
else()
message(WARNING "Could not find libgcov in ${GCC_LIB_DIR}")
endif()
else()
message(WARNING "Could not find GCC library directory for version ${GCC_VERSION}")
endif()
endif()
# if windows
if (WIN32)
# For Windows: Prevent overriding the parent project's compiler/linker settings
@ -102,10 +141,20 @@ endforeach()
add_dependencies(${PROJECT_NAME} sync_locale_files)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 23)
target_link_libraries(${PROJECT_NAME}
${SUNSHINE_EXTERNAL_LIBRARIES}
gtest
${PLATFORM_LIBRARIES})
# Build the list of libraries to link
set(TEST_LINK_LIBRARIES
${SUNSHINE_EXTERNAL_LIBRARIES}
gtest
${PLATFORM_LIBRARIES}
)
# Add the specific libgcov library if found
if(GCOV_LINK_LIBRARY)
list(APPEND TEST_LINK_LIBRARIES ${GCOV_LINK_LIBRARY})
endif()
target_link_libraries(${PROJECT_NAME} ${TEST_LINK_LIBRARIES})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${SUNSHINE_DEFINITIONS} ${TEST_DEFINITIONS})
target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${SUNSHINE_COMPILE_OPTIONS}>;$<$<COMPILE_LANGUAGE:CUDA>:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) # cmake-lint: disable=C0301
target_link_options(${PROJECT_NAME} PRIVATE)