build(ci): default Linux pipeline to AppImage artifacts#81
build(ci): default Linux pipeline to AppImage artifacts#81
Conversation
- build-linux.yml: add package_format input (appimage|gzip, default appimage) Replace monolithic deploy bundle step with two conditional steps: Package as AppImage (APPIMAGE_EXTRACT_AND_RUN=1 for CI) and Package as gzip bundle (legacy opt-in). Compute artifact path via Set artifact path step so Upload Deployment Bundle stays format-agnostic. - release.yml: pass package_format: appimage to both Linux build jobs. Normalize step now detects .AppImage first (direct copy) and falls back to legacy tar+zip path for older artifacts. Summary updated to new asset names. - INSTALL_INSTRUCTIONS.md: rewrite Linux install section for AppImage workflow, including chmod +x one-liner, default path auto-detection, CNC_GENERALS_ZH_PATH override, and a note that all runtime libs are bundled.
There was a problem hiding this comment.
Pull request overview
This PR updates the Linux CI/release packaging pipeline to produce AppImage artifacts by default (with the existing tar/gzip bundle retained as an opt-in fallback), and updates developer/user documentation and VS Code tasks to match the new distribution flow.
Changes:
- Add AppImage builder scripts for GeneralsXZH and GeneralsX, and expose them via VS Code tasks and scripts documentation.
- Update GitHub Actions Linux build workflow to support a
package_formatinput (defaultappimage) and upload a computed artifact path. - Update release workflow asset normalization and installation docs to prefer
.AppImageassets and document AppImage-first usage.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
scripts/README.md |
Documents the new AppImage builder scripts and usage examples. |
scripts/build/linux/build-linux-appimage-zh.sh |
New AppImage packaging script for Zero Hour (GeneralsXZH), including bundled runtime libs and generated AppRun. |
scripts/build/linux/build-linux-appimage-generals.sh |
New AppImage packaging script for base game (GeneralsX), including generated AppRun. |
docs/WORKDIR/support/APPIMAGE_POC_PLAN_2026-04.md |
Captures the AppImage PoC plan/scope and validation checklist. |
docs/WORKDIR/lessons/2026-04-LESSONS.md |
Records an AppImage-related lesson learned for April 2026. |
docs/DEV_BLOG/2026-04-DIARY.md |
Adds session notes describing AppImage hardening and validation outcomes. |
docs/BUILD/INSTALL_INSTRUCTIONS.md |
Updates Linux install instructions to AppImage-first flow and notes Vulkan driver dependency. |
.vscode/tasks.json |
Adds tasks to build AppImage artifacts for both GeneralsX and GeneralsXZH. |
.github/workflows/release.yml |
Makes the release pipeline prefer .AppImage assets, with tar/zip fallback. |
.github/workflows/build-linux.yml |
Adds package_format, conditionally packages AppImage vs legacy bundle, and uploads the selected artifact path. |
There was a problem hiding this comment.
Pull request overview
This PR updates the Linux CI/release packaging pipeline to produce AppImage artifacts by default (with a gzip/tar fallback), adds AppImage builder scripts for both Zero Hour and base Generals, and refreshes docs/tasks to reflect the AppImage-first install/run flow.
Changes:
- Default Linux CI packaging to AppImage via a new
package_formatinput (fallback: legacy gzip bundle). - Add new AppImage builder scripts for
GeneralsXZHandGeneralsX(including bundled FFmpeg runtime libs + AppRun launchers). - Update release asset normalization, VS Code tasks, and install/docs to reference
.AppImageartifacts.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/build-linux.yml |
Adds package_format, AppImage packaging step, and format-agnostic artifact upload. |
.github/workflows/release.yml |
Consumes AppImage artifacts by default and normalizes them into .AppImage release assets (fallback to legacy bundle zips). |
scripts/build/linux/build-linux-appimage-zh.sh |
New AppImage builder for Zero Hour, bundling runtime libs and generating AppRun/.desktop metadata. |
scripts/build/linux/build-linux-appimage-generals.sh |
New AppImage builder for base Generals, bundling runtime libs and generating AppRun/.desktop metadata. |
.vscode/tasks.json |
Adds tasks to build AppImages for both game variants. |
docs/BUILD/INSTALL_INSTRUCTIONS.md |
Updates Linux install/run instructions to AppImage-first with env overrides and troubleshooting notes. |
scripts/README.md |
Documents new AppImage packaging scripts and example usage. |
docs/WORKDIR/support/APPIMAGE_POC_PLAN_2026-04.md |
Adds AppImage PoC plan/reference for active work tracking. |
docs/WORKDIR/lessons/2026-04-LESSONS.md |
Records AppImage vs Flatpak takeaway as a lessons-learned entry. |
docs/DEV_BLOG/2026-04-DIARY.md |
Dev diary entries documenting AppImage work and validations. |
| cp "${BINARY_SRC}" "${APPDIR}/usr/bin/GeneralsXZH" | ||
| chmod +x "${APPDIR}/usr/bin/GeneralsXZH" | ||
| cp "${GAMESPY_LIB}" "${APPDIR}/usr/lib/" | ||
| copy_optional_libs "${DXVK_LIB_DIR}" "libdxvk_d3d8.so*" | ||
| copy_optional_libs "${DXVK_LIB_DIR}" "libdxvk_d3d9.so*" | ||
| copy_optional_libs "${SDL3_LIB_DIR}" "libSDL3.so*" | ||
| copy_optional_libs "${SDL3_IMAGE_LIB_DIR}" "libSDL3_image.so*" | ||
| copy_optional_libs "${OPENAL_LIB_DIR}" "libopenal.so*" | ||
|
|
| copy_ldd_deps() { | ||
| local root="$1" | ||
| [[ -e "${root}" ]] || return 0 | ||
|
|
||
| while IFS= read -r dep; do | ||
| case "${dep}" in | ||
| # GeneralsX @bugfix GitHubCopilot 10/04/2026 Exclude glibc loader/runtime files across common Linux layouts to preserve AppImage portability. | ||
| linux-vdso.so.1 | \ | ||
| /lib64/ld-linux* | /lib/*/ld-linux* | /usr/lib/*/ld-linux* | /usr/lib64/ld-linux* | \ | ||
| /lib/*/libc.so.* | /lib64/libc.so.* | /usr/lib/*/libc.so.* | /usr/lib64/libc.so.* | \ | ||
| /lib/*/libm.so.* | /lib64/libm.so.* | /usr/lib/*/libm.so.* | /usr/lib64/libm.so.* | \ | ||
| /lib/*/libpthread.so.* | /lib64/libpthread.so.* | /usr/lib/*/libpthread.so.* | /usr/lib64/libpthread.so.* | \ | ||
| /lib/*/librt.so.* | /lib64/librt.so.* | /usr/lib/*/librt.so.* | /usr/lib64/librt.so.* | \ | ||
| /lib/*/libdl.so.* | /lib64/libdl.so.* | /usr/lib/*/libdl.so.* | /usr/lib64/libdl.so.*) | ||
| continue | ||
| ;; | ||
| esac | ||
|
|
||
| cp -a "${dep}" "${APPDIR}/usr/lib/" 2>/dev/null || true | ||
| if [[ -L "${dep}" ]]; then | ||
| local resolved | ||
| resolved="$(readlink -f "${dep}")" | ||
| cp -a "${resolved}" "${APPDIR}/usr/lib/" 2>/dev/null || true | ||
| fi | ||
| done < <(ldd "${root}" | awk '{for (i = 1; i <= NF; ++i) { if ($i ~ /^\//) { print $i; break } }}' | sort -u) | ||
| } |
| SDL3_IMAGE_LIB_DIR="${BUILD_DIR}/_deps/sdl3_image-build" | ||
| OPENAL_LIB_DIR="${BUILD_DIR}/_deps/openal_soft-build" | ||
| FFMPEG_LIB_DIR="/usr/lib/x86_64-linux-gnu" | ||
| FFMPEG_DEP_LIB_DIR="/lib/x86_64-linux-gnu" | ||
| BINARY_SRC="${BUILD_DIR}/GeneralsMD/GeneralsXZH" |
| DXVK_LIB_DIR="${BUILD_DIR}/_deps/dxvk-src/lib" | ||
| SDL3_LIB_DIR="${BUILD_DIR}/_deps/sdl3-build" | ||
| SDL3_IMAGE_LIB_DIR="${BUILD_DIR}/_deps/sdl3_image-build" | ||
| OPENAL_LIB_DIR="${BUILD_DIR}/_deps/openal_soft-build" | ||
| FFMPEG_LIB_DIR="/usr/lib/x86_64-linux-gnu" | ||
| FFMPEG_DEP_LIB_DIR="/lib/x86_64-linux-gnu" |
| # GeneralsX @build GitHubCopilot 10/04/2026 Package as AppImage (self-contained, no FUSE needed for appimagetool in CI via APPIMAGE_EXTRACT_AND_RUN). | ||
| - name: Package as AppImage | ||
| if: success() && inputs.package_format == 'appimage' | ||
| env: | ||
| APPIMAGE_EXTRACT_AND_RUN: "1" | ||
| run: | | ||
| if [ "${{ inputs.game }}" = "GeneralsMD" ]; then | ||
| ./scripts/build/linux/build-linux-appimage-zh.sh ${{ inputs.preset }} | ||
| else | ||
| ./scripts/build/linux/build-linux-appimage-generals.sh ${{ inputs.preset }} | ||
| fi |
| copy_optional_libs "${SDL3_LIB_DIR}" "libSDL3.so*" | ||
| copy_optional_libs "${SDL3_IMAGE_LIB_DIR}" "libSDL3_image.so*" | ||
| copy_optional_libs "${OPENAL_LIB_DIR}" "libopenal.so*" | ||
|
|
Summary
This PR switches Linux packaging/release flow to AppImage by default and keeps gzip as an optional fallback.
What Changed
package_formatinput (appimagedefault,gzipfallback)scripts/build/linux/build-linux-appimage-zh.shandscripts/build/linux/build-linux-appimage-generals.shpackage_format: appimage.AppImageartifacts and falls back to legacy tar+zip if neededchmod +x, direct run, env overrides)Why
Validation
lddon AppDir binaries confirms runtime closure inside AppImage for non-glibc libsRelated