Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/steps/install_dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ runs:
if: runner.os == 'Linux' && inputs.job-platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-0
sudo apt-get install -y desktop-file-utils lintian libgtk-3-0
206 changes: 176 additions & 30 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -452,24 +452,12 @@ jobs:
path: ${{ github.workspace }}/Emerald-macOS-arm64-app.zip
retention-days: 14

# Snap packages are built natively on each architecture — Uno Platform does not
# support cross-compilation for snap targets as of the current SDK version.
publish-linux:
name: Linux Snap (${{ matrix.arch }})
name: Linux x64 Packages
needs: ci-filter
if: ${{ needs.ci-filter.outputs.run_linux == 'true' }}
runs-on: ${{ matrix.runner }}
runs-on: ubuntu-22.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-22.04
runtime: linux-x64
- arch: arm64
runner: ubuntu-22.04-arm
runtime: linux-arm64

steps:
- name: Checkout code
Expand All @@ -482,9 +470,108 @@ jobs:
with:
job-platform: linux

- name: Publish Linux x64 app and stage shared package files
shell: bash
env:
PACKAGE_VERSION: ${{ needs.ci-filter.outputs.package_version }}
PUBLIC_VERSION: ${{ needs.ci-filter.outputs.public_version }}
UPDATE_CHANNEL: ${{ needs.ci-filter.outputs.release_channel }}
RELEASE_TAG: ${{ needs.ci-filter.outputs.release_tag }}
COMMIT_SHA: ${{ github.sha }}
BUILD_TIMESTAMP_UTC: ${{ needs.ci-filter.outputs.build_timestamp_utc }}
run: scripts/linux/publish-linux-x64.sh

- name: Build Linux Debian package
shell: bash
env:
PACKAGE_VERSION: ${{ needs.ci-filter.outputs.package_version }}
run: scripts/linux/build-deb.sh

- name: Verify Linux AppDir staging
shell: bash
run: |
set -euo pipefail

test -x "$GITHUB_WORKSPACE/AppDir/usr/lib/emerald/Emerald"
test -x "$GITHUB_WORKSPACE/AppDir/usr/bin/emerald"
test -f "$GITHUB_WORKSPACE/AppDir/usr/share/applications/emerald.desktop"
test -f "$GITHUB_WORKSPACE/AppDir/usr/share/applications/com.riversidevalley.Emerald.desktop"
test -f "$GITHUB_WORKSPACE/AppDir/usr/share/icons/hicolor/256x256/apps/emerald.png"

- name: Build Linux AppImage
shell: bash
env:
EMERALD_PACKAGE_VERSION: ${{ needs.ci-filter.outputs.package_version }}
EMERALD_APPIMAGE_NAME: Emerald-linux-x86_64.AppImage
run: |
set -euo pipefail

docker run --rm \
-e "EMERALD_PACKAGE_VERSION=$EMERALD_PACKAGE_VERSION" \
-e "EMERALD_APPIMAGE_NAME=$EMERALD_APPIMAGE_NAME" \
-v "$GITHUB_WORKSPACE:/github/workspace" \
-w /github/workspace \
appimagecrafters/appimage-builder:1.1.0 \
bash -lc 'apt-get update && apt-get install -y squashfs-tools && appimage-builder --recipe=scripts/linux/AppImageBuilder.x64.yml --skip-test'

- name: Stage and validate Linux AppImage
shell: bash
run: |
set -euo pipefail

APPIMAGE_FILE="$(find "$GITHUB_WORKSPACE" -maxdepth 1 -name '*.AppImage' -type f -print -quit)"
if [ -z "$APPIMAGE_FILE" ]; then
echo "No AppImage file found after appimage-builder completed"
exit 1
fi

STAGED="$GITHUB_WORKSPACE/artifacts/linux/final/Emerald-linux-x86_64.AppImage"
cp "$APPIMAGE_FILE" "$STAGED"
chmod +x "$STAGED"
"$STAGED" --appimage-extract >/dev/null
rm -rf squashfs-root

- name: Prepare Linux Arch package recipe
shell: bash
env:
PACKAGE_VERSION: ${{ needs.ci-filter.outputs.package_version }}
run: scripts/linux/prepare-arch-package.sh

- name: Build Linux Arch package
shell: bash
run: |
set -euo pipefail

docker run --rm \
-v "$GITHUB_WORKSPACE:/workspace" \
-w /workspace/artifacts/linux/arch/pkgbuild \
archlinux:base-devel \
bash -lc '
set -euo pipefail
useradd -m builder
chown -R builder:builder /workspace/artifacts/linux/arch
su builder -c "cd /workspace/artifacts/linux/arch/pkgbuild && makepkg --printsrcinfo > .SRCINFO && makepkg --packagelist && makepkg --nodeps --cleanbuild --force"
'

- name: Stage Linux Arch artifacts
shell: bash
run: |
set -euo pipefail

PKGBUILD_DIR="$GITHUB_WORKSPACE/artifacts/linux/arch/pkgbuild"
FINAL_DIR="$GITHUB_WORKSPACE/artifacts/linux/final"
PKG_FILE="$(find "$PKGBUILD_DIR" -maxdepth 1 -name '*.pkg.tar.zst' -type f | head -n 1)"
if [ -z "$PKG_FILE" ]; then
echo "No Arch package file found after makepkg completed"
exit 1
fi

cp "$PKG_FILE" "$FINAL_DIR/emerald-${{ needs.ci-filter.outputs.package_version }}-1-x86_64.pkg.tar.zst"
tar -czf "$FINAL_DIR/emerald-aur-recipe.tar.gz" -C "$PKGBUILD_DIR" PKGBUILD .SRCINFO

# Snapcraft is installed after the base dependencies so that the snap daemon
# is ready before we invoke dotnet publish with PackageFormat=snap.
# core22 matches the Ubuntu 22.04 runner base used by both matrix legs.
# core22 matches the Ubuntu 22.04 runner base.
# --destructive-mode is required in CI because LXD/Multipass are unavailable
# on single-use GitHub-hosted runners; it is safe here because the environment
# is ephemeral and discarded after the job completes.
Expand All @@ -497,16 +584,16 @@ jobs:
sudo snap install snapcraft --classic
sudo snap install multipass

- name: Publish Linux Snap (${{ matrix.arch }})
- name: Publish Linux Snap
shell: bash
env:
# Modern Snapcraft equivalent to --destructive-mode
SNAPCRAFT_BUILD_ENVIRONMENT: host
SNAPCRAFT_BUILD_ENVIRONMENT: host
run: |
dotnet publish ./Emerald/Emerald.csproj \
-c Release \
-f net10.0-desktop \
-r "${{ matrix.runtime }}" \
-r linux-x64 \
-p:SelfContained=true \
-p:PackageFormat=snap \
-p:UnoSnapBuildProvider=none \
Expand All @@ -530,31 +617,66 @@ jobs:
run: |
# Uno places the .snap in the publish output folder; find it regardless
# of the exact versioned filename that snapcraft generates.
SNAP_FILE="$(find . -name '*.snap' -not -path '*/.git/*' -type f | head -n 1)"
SNAP_FILE="$(find "$GITHUB_WORKSPACE" \
\( -path "$GITHUB_WORKSPACE/.git" \
-o -path "$GITHUB_WORKSPACE/AppDir" \
-o -path "$GITHUB_WORKSPACE/appimage-build" \) -prune \
-o -name '*.snap' -type f -print -quit)"
if [ -z "$SNAP_FILE" ]; then
echo "No .snap file found after publish"
exit 1
fi
echo "Found snap: $SNAP_FILE"

STAGED="$GITHUB_WORKSPACE/Emerald-linux-${{ matrix.arch }}.snap"
STAGED="$GITHUB_WORKSPACE/artifacts/linux/final/Emerald-linux-x64.snap"
cp "$SNAP_FILE" "$STAGED"
echo "snap_path=$STAGED" >> "$GITHUB_OUTPUT"

- name: Upload CI Linux Snap artifact (${{ matrix.arch }})
- name: Upload CI Linux Snap artifact
uses: actions/upload-artifact@v4
with:
name: Emerald-linux-${{ matrix.arch }}-snap
name: Emerald-linux-x64-snap
path: ${{ steps.locate.outputs.snap_path }}
if-no-files-found: error
retention-days: 14

- name: Upload release Linux Snap transfer artifact (${{ matrix.arch }})
if: ${{ needs.ci-filter.outputs.is_release_flow == 'true' }}
- name: Upload CI Linux tar artifact
uses: actions/upload-artifact@v4
with:
name: Emerald-linux-${{ matrix.arch }}-ReleaseDraft-Snap
path: ${{ steps.locate.outputs.snap_path }}
name: Emerald-linux-x64-tar
path: ${{ github.workspace }}/artifacts/linux/final/Emerald-linux-x64.tar.gz
if-no-files-found: error
retention-days: 14

- name: Upload CI Linux AppImage artifact
uses: actions/upload-artifact@v4
with:
name: Emerald-linux-x64-appimage
path: ${{ github.workspace }}/artifacts/linux/final/Emerald-linux-x86_64.AppImage
if-no-files-found: error
retention-days: 14

- name: Upload CI Linux Debian artifact
uses: actions/upload-artifact@v4
with:
name: Emerald-linux-x64-deb
path: ${{ github.workspace }}/artifacts/linux/final/emerald_${{ needs.ci-filter.outputs.package_version }}_amd64.deb
if-no-files-found: error
retention-days: 14

- name: Upload CI Linux Arch artifact
uses: actions/upload-artifact@v4
with:
name: Emerald-linux-x64-arch
path: ${{ github.workspace }}/artifacts/linux/final/emerald-${{ needs.ci-filter.outputs.package_version }}-1-x86_64.pkg.tar.zst
if-no-files-found: error
retention-days: 14

- name: Upload CI Linux AUR recipe artifact
uses: actions/upload-artifact@v4
with:
name: Emerald-linux-x64-aur-recipe
path: ${{ github.workspace }}/artifacts/linux/final/emerald-aur-recipe.tar.gz
if-no-files-found: error
retention-days: 14

Expand Down Expand Up @@ -588,13 +710,37 @@ jobs:
- name: Download Linux x64 Snap artifact
uses: actions/download-artifact@v4
with:
name: Emerald-linux-x64-ReleaseDraft-Snap
name: Emerald-linux-x64-snap
path: release-assets/linux

- name: Download Linux x64 tar artifact
uses: actions/download-artifact@v4
with:
name: Emerald-linux-x64-tar
path: release-assets/linux

- name: Download Linux x64 AppImage artifact
uses: actions/download-artifact@v4
with:
name: Emerald-linux-x64-appimage
path: release-assets/linux

- name: Download Linux x64 Debian artifact
uses: actions/download-artifact@v4
with:
name: Emerald-linux-x64-deb
path: release-assets/linux

- name: Download Linux x64 Arch artifact
uses: actions/download-artifact@v4
with:
name: Emerald-linux-x64-arch
path: release-assets/linux

- name: Download Linux arm64 Snap artifact
- name: Download Linux x64 AUR recipe artifact
uses: actions/download-artifact@v4
with:
name: Emerald-linux-arm64-ReleaseDraft-Snap
name: Emerald-linux-x64-aur-recipe
path: release-assets/linux

- name: Build release metadata files
Expand Down Expand Up @@ -655,4 +801,4 @@ jobs:
generate_release_notes: true
files: ${{ steps.files.outputs.files }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53 changes: 53 additions & 0 deletions scripts/linux/AppImageBuilder.x64.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
version: 1

AppDir:
path: ./AppDir
app_info:
id: com.riversidevalley.Emerald
name: Emerald
icon: emerald
version: !ENV ${EMERALD_PACKAGE_VERSION}
exec: usr/lib/emerald/Emerald
exec_args: $@
runtime:
env:
APPDIR_LIBRARY_PATH: '$APPDIR/usr/lib/emerald:$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu'
GTK_THEME: Default
apt:
arch: amd64
sources:
- sourceline: deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C'
- sourceline: deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse
- sourceline: deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
include:
- libgtk-3-0
- libgtk-3-bin
- libgtk-3-common
- libx11-6
- libfontconfig1
- libfreetype6
- libgcc-s1
- libstdc++6
- libcanberra-gtk3-module
exclude:
- hicolor-icon-theme
- humanity-icon-theme
files:
exclude:
- usr/share/man
- usr/share/doc/*/README.*
- usr/share/doc/*/changelog.*
- usr/share/doc/*/NEWS.*
- usr/share/doc/*/TODO.*
- usr/bin/kernel-install
- usr/lib/kernel
- usr/share/bug
- lib/systemd
- etc/init.d

AppImage:
arch: x86_64
file_name: !ENV ${EMERALD_APPIMAGE_NAME}
update-information: None
sign-key: None
43 changes: 43 additions & 0 deletions scripts/linux/build-deb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail

OUTPUT_ROOT="${OUTPUT_ROOT:-$PWD/artifacts/linux}"
PACKAGE_VERSION="${PACKAGE_VERSION:?PACKAGE_VERSION is required}"
INSTALL_ROOT="$OUTPUT_ROOT/install-root"
DEB_ROOT="$OUTPUT_ROOT/deb/root"
FINAL_DIR="$OUTPUT_ROOT/final"
DEB_PATH="$FINAL_DIR/emerald_${PACKAGE_VERSION}_amd64.deb"

if [ ! -d "$INSTALL_ROOT/opt/emerald" ]; then
echo "Install root was not found. Run scripts/linux/publish-linux-x64.sh first."
exit 1
fi

rm -rf "$DEB_ROOT"
mkdir -p "$DEB_ROOT/DEBIAN" "$FINAL_DIR"
cp -a "$INSTALL_ROOT/." "$DEB_ROOT/"

INSTALLED_SIZE="$(du -sk "$DEB_ROOT/opt/emerald" "$DEB_ROOT/usr" | awk '{total += $1} END {print total}')"

cat > "$DEB_ROOT/DEBIAN/control" <<EOF
Package: emerald
Version: $PACKAGE_VERSION
Section: games
Priority: optional
Architecture: amd64
Maintainer: Riverside Valley <support@riversidevalley.dev>
Installed-Size: $INSTALLED_SIZE
Depends: libgtk-3-0, libx11-6, libfontconfig1, libfreetype6, libgcc-s1, libstdc++6, libc6
Homepage: https://github.com/RiversideValley/Emerald
Description: Open-source cross-platform Minecraft launcher
Emerald is an open-source cross-platform Minecraft launcher made with .NET.
EOF

find "$DEB_ROOT" -type d -exec chmod 755 {} +
chmod 644 "$DEB_ROOT/DEBIAN/control"
dpkg-deb --build --root-owner-group "$DEB_ROOT" "$DEB_PATH"
dpkg-deb --info "$DEB_PATH"

if command -v lintian >/dev/null 2>&1; then
lintian "$DEB_PATH" || true
fi
Loading
Loading