Add shared runner dependency setup for Linux and Windows
CI / Real Minecraft installs (manual) (push) Skipped
CI / Windows launcher (push) Failing after 13s
CI / Rust, web and container (push) Canceled after 0s
Server integrations / paper (push) Canceled after 0s
Server integrations / Fabric and Forge / 1.20.1 (push) Canceled after 0s
Server integrations / Fabric and Forge / 1.21.1 (push) Canceled after 0s
Server integrations / Fabric and Forge / 26.1.2 (push) Canceled after 0s
Server integrations / Fabric and Forge / 26.2 (push) Canceled after 0s
Server integrations / Fabric and Forge / 26.3 (push) Canceled after 0s

This commit is contained in:
SCOPEDD committed 2026-10-01 01:04:03 -04:00
1 parent 23ab34ab72
commit a378f9904c
7 files changed
+262 -83

No files matched your search

+25 -34
View File
@@ -19,17 +19,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Verify Linux runner
run: |
set -eu
test "$(uname -s)" = Linux
for tool in cargo rustc node npm docker; do command -v "$tool" >/dev/null || { echo "Missing $tool on ubuntu-latest runner"; exit 1; }; done
test "$(node -p 'process.versions.node.split(".")[0]')" -ge 22
rustup component list --installed | grep -q rustfmt
rustup component list --installed | grep -q clippy
pkg-config --exists webkit2gtk-4.1 ayatana-appindicator3-0.1 librsvg-2.0 || { echo 'Missing Tauri GTK/WebKit development packages'; exit 1; }
docker info >/dev/null || { echo 'Docker daemon unavailable'; exit 1; }
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v4
with:
node-version: '22'
@@ -37,6 +26,9 @@ jobs:
cache-dependency-path: |
panel/web/package-lock.json
launcher/package-lock.json
- name: Install Linux build dependencies
run: bash scripts/ci/install-linux.sh rust
- uses: Swatinem/rust-cache@v2
- name: Check Rust
run: |
mkdir -p launcher/dist
@@ -49,37 +41,35 @@ jobs:
for app in panel/web launcher; do
(cd "$app" && npm ci --no-audit --no-fund && npm run check && npm run build)
done
- id: docker
run: |
if command -v docker >/dev/null && docker info >/dev/null 2>&1; then
echo 'ready=true' >> "$GITEA_OUTPUT"
else
echo 'ready=false' >> "$GITEA_OUTPUT"
fi
- uses: docker/setup-docker-action@v5
if: steps.docker.outputs.ready != 'true'
- uses: docker/setup-buildx-action@v3
- name: Build panel container
run: docker build -t scopenet-panel:ci .
run: |
bash scripts/ci/install-linux.sh image
docker build -t scopenet-panel:ci .
launcher-windows:
name: Windows launcher
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- name: Find PowerShell 7 on Windows runner
shell: powershell
run: |
$pwsh = (Get-Command pwsh -ErrorAction SilentlyContinue | Select-Object -First 1).Source
if (-not $pwsh) { $pwsh = Join-Path $env:ProgramFiles 'PowerShell\7\pwsh.exe' }
if (-not (Test-Path $pwsh)) { throw "PowerShell 7 is not available to the runner at $pwsh" }
$version = & $pwsh -NoProfile -Command '$PSVersionTable.PSVersion.ToString()'
Write-Host "Using PowerShell $version at $pwsh"
Add-Content -Path $env:GITEA_PATH -Value (Split-Path $pwsh)
- name: Verify Windows runner
shell: pwsh
run: |
if (-not $IsWindows) { throw 'windows-latest must be a Windows host runner' }
foreach ($tool in @('cargo', 'rustc', 'node', 'npm')) {
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) { throw "Missing $tool" }
}
if ([int](node -p 'process.versions.node.split(".")[0]') -lt 22) { throw 'Node 22+ required' }
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
cache-dependency-path: launcher/package-lock.json
- name: Install Windows build dependencies
shell: powershell
run: .\scripts\ci\install-windows.ps1
- uses: Swatinem/rust-cache@v2
- run: npm ci --no-audit --no-fund
working-directory: launcher
- run: npm run build
@@ -94,9 +84,10 @@ jobs:
continue-on-error: true
steps:
- uses: actions/checkout@v5
- name: Verify runner
run: |
test "$(uname -s)" = Linux
command -v cargo
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Linux build dependencies
run: bash scripts/ci/install-linux.sh rust
- uses: Swatinem/rust-cache@v2
- run: cargo test -p scopenet-core --test online --locked -- --ignored --test-threads=2 --nocapture
+4 -12
View File
@@ -24,12 +24,8 @@ jobs:
with:
distribution: temurin
java-version: '21'
- name: Verify integration runner
run: |
set -eu
test "$(uname -s)" = Linux
command -v java
java -version 2>&1 | grep -q '21\.' || { echo 'Paper needs Java 21'; exit 1; }
- name: Check Linux and Java dependencies
run: bash scripts/ci/install-linux.sh java 21
- name: Build Paper with Gradle 8.10.2
run: |
sed -i 's/gradle-9.6.0-bin.zip/gradle-8.10.2-bin.zip/' integrations/gradle/wrapper/gradle-wrapper.properties
@@ -63,12 +59,8 @@ jobs:
with:
distribution: temurin
java-version: ${{ matrix.mc.java }}
- name: Verify integration runner
run: |
set -eu
test "$(uname -s)" = Linux
command -v java
java -version 2>&1 | grep -q '${{ matrix.mc.java }}\.' || { echo 'Wrong Java version for this matrix entry'; exit 1; }
- name: Check Linux and Java dependencies
run: bash scripts/ci/install-linux.sh java '${{ matrix.mc.java }}'
- name: Build both loaders
run: |
sed -i 's/gradle-9.6.0-bin.zip/gradle-${{ matrix.mc.gradle }}-bin.zip/' integrations/gradle/wrapper/gradle-wrapper.properties
+36 -36
View File
@@ -53,57 +53,54 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- name: Verify Windows runner
shell: pwsh
run: |
if (-not $IsWindows) { throw 'windows-latest must be a Windows host runner' }
foreach ($tool in @('cargo', 'node', 'npm')) {
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) { throw "Missing $tool" }
}
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: release
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: launcher/package-lock.json
- name: Install Windows build dependencies
shell: powershell
run: .\scripts\ci\install-windows.ps1
- uses: Swatinem/rust-cache@v2
with:
key: release
- name: Stamp version
shell: bash
shell: pwsh
env:
VERSION: ${{ needs.version.outputs.version }}
run: |
sed -i "0,/^version = \".*\"/s//version = \"$VERSION\"/" Cargo.toml
node -e "const f='launcher/src-tauri/tauri.conf.json';const c=require('./'+f);c.version=process.env.VERSION;require('fs').writeFileSync(f,JSON.stringify(c,null,2))"
node -e "const f='launcher/package.json';const c=require('./'+f);c.version=process.env.VERSION;require('fs').writeFileSync(f,JSON.stringify(c,null,2))"
$cargo = Get-Content Cargo.toml -Raw
$cargo = [regex]::new('(?m)^version = ".*"').Replace($cargo, 'version = "' + $env:VERSION + '"', 1)
[IO.File]::WriteAllText((Join-Path (Get-Location) 'Cargo.toml'), $cargo)
node -e "for(const f of ['launcher/src-tauri/tauri.conf.json','launcher/package.json']){const fs=require('fs');const c=JSON.parse(fs.readFileSync(f));c.version=process.env.VERSION;fs.writeFileSync(f,JSON.stringify(c,null,2))}"
- run: npm ci --no-audit --no-fund
working-directory: launcher
- name: Build installer
working-directory: launcher
shell: bash
shell: pwsh
env:
SCOPENET_PANEL_URL: ${{ vars.PANEL_URL }}
SCOPENET_LOCK_PANEL: ${{ vars.LOCK_PANEL }}
SCOPENET_REPO: ${{ gitea.server_url }}/${{ gitea.repository }}
LAUNCHER_NAME: ${{ vars.LAUNCHER_NAME }}
run: |
if [ -n "$LAUNCHER_NAME" ]; then
CONFIG=$(node -e "console.log(JSON.stringify({productName: process.env.LAUNCHER_NAME, app: {windows: [{...require('./src-tauri/tauri.conf.json').app.windows[0], title: process.env.LAUNCHER_NAME}]}}))")
npx tauri build --bundles nsis --config "$CONFIG"
else
if ($env:LAUNCHER_NAME) {
$config = node -e "console.log(JSON.stringify({productName: process.env.LAUNCHER_NAME, app: {windows: [{...require('./src-tauri/tauri.conf.json').app.windows[0], title: process.env.LAUNCHER_NAME}]}}))"
npx tauri build --bundles nsis --config $config
} else {
npx tauri build --bundles nsis
fi
}
if ($LASTEXITCODE -ne 0) { throw "Installer build failed with exit code $LASTEXITCODE" }
- name: Collect installer
shell: bash
shell: pwsh
run: |
mkdir -p out
cp target/release/bundle/nsis/*-setup.exe out/
ls -la out
New-Item -ItemType Directory -Force out | Out-Null
Copy-Item target/release/bundle/nsis/*-setup.exe out/
Get-ChildItem out
- uses: actions/upload-artifact@v4
with:
@@ -117,17 +114,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Verify container runner
run: |
test "$(uname -s)" = Linux
command -v docker
docker info >/dev/null
docker buildx version >/dev/null
- name: Image name
run: echo "IMAGE=${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY_OWNER,,}/scopenet-mc-panel" >> "$GITEA_ENV"
- name: Stamp version
run: sed -i "0,/^version = \".*\"/s//version = \"${{ needs.version.outputs.version }}\"/" Cargo.toml
- id: docker
run: |
if command -v docker >/dev/null && docker info >/dev/null 2>&1; then
echo 'ready=true' >> "$GITEA_OUTPUT"
else
echo 'ready=false' >> "$GITEA_OUTPUT"
fi
- uses: docker/setup-docker-action@v5
if: steps.docker.outputs.ready != 'true'
- uses: docker/setup-buildx-action@v3
- name: Check Linux container dependencies
run: bash scripts/ci/install-linux.sh image
- uses: docker/login-action@v3
with:
registry: gitea.jadonsandbox.com
@@ -162,11 +164,9 @@ jobs:
needs: [version, launcher, panel-image, server-integrations]
runs-on: ubuntu-latest
steps:
- name: Verify release runner
run: |
test "$(uname -s)" = Linux
command -v curl
command -v jq
- uses: actions/checkout@v5
- name: Install Linux release dependencies
run: bash scripts/ci/install-linux.sh release
- uses: actions/download-artifact@v4
with:
name: windows-installer
+48
View File
@@ -0,0 +1,48 @@
name: Runner setup
on:
workflow_dispatch:
jobs:
linux:
name: Linux image and JAR dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Rust and system packages
run: bash scripts/ci/install-linux.sh rust
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- run: bash scripts/ci/install-linux.sh java 21
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '25'
- run: bash scripts/ci/install-linux.sh java 25
- id: docker
run: |
if command -v docker >/dev/null && docker info >/dev/null 2>&1; then
echo 'ready=true' >> "$GITHUB_OUTPUT"
else
echo 'ready=false' >> "$GITHUB_OUTPUT"
fi
- uses: docker/setup-docker-action@v5
if: steps.docker.outputs.ready != 'true'
- uses: docker/setup-buildx-action@v3
- run: bash scripts/ci/install-linux.sh image
windows:
name: Windows installer dependencies
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install PowerShell, Rust and MSVC
shell: powershell
run: .\scripts\ci\install-windows.ps1
+3 -1
View File
@@ -82,7 +82,9 @@ The workflow builds the **Windows installer**, pushes the **panel image to Gitea
### Gitea runner setup
Register a Linux host runner with the `ubuntu-latest` label and a Windows host runner with `windows-latest`. The CI workflows check the host OS and required tools before building. The Linux host needs Rust with `rustfmt` and `clippy`, Node 22+, Java 21 and 25 for the integration matrix, Docker with Buildx, `pkg-config`, the Tauri WebKit/GTK development libraries, `curl`, and `jq`. The Windows host needs Rust, Node 22+, PowerShell and Git Bash. Enable Actions for the repository and allow its job token to write releases and packages. See [Gitea's runner labels](https://docs.gitea.com/runner/labels/) and [token permissions](https://docs.gitea.com/usage/actions/token-permissions/).
Register a Linux host runner with the `ubuntu-latest` label and a Windows host runner with `windows-latest`. Linux builds the panel Docker image and server JARs; Windows builds the NSIS installer. The workflows use [the Linux setup tool](scripts/ci/install-linux.sh) and [the Windows setup tool](scripts/ci/install-windows.ps1) to install or check job dependencies. Node 22 and Java 21/25 are downloaded by `setup-node` and `setup-java`; the Linux tool installs Rust, Tauri system packages, and release utilities, while the Windows tool installs Rust and downloads PowerShell 7.6.6 if the runner cannot find it. Docker and Buildx are set up by Docker's Actions. The Linux runner must allow a Docker daemon to start or provide one, and system package installation needs root or passwordless sudo. Enable Actions for the repository and allow its job token to write releases and packages. See [Gitea's runner labels](https://docs.gitea.com/runner/labels/) and [token permissions](https://docs.gitea.com/usage/actions/token-permissions/).
The setup tools also run directly on matching hosts: `bash scripts/ci/install-linux.sh rust` prepares Rust and Tauri builds, `bash scripts/ci/install-linux.sh image` checks Docker, `bash scripts/ci/install-linux.sh java 21` checks a Java integration runner, and `powershell -File scripts/ci/install-windows.ps1` prepares the Windows installer runner. Gitea uses them in CI and release jobs; GitHub provides a manual **Runner setup** workflow for both platforms. Run the Linux `rust` mode as root or with passwordless sudo; the Windows script may need administrator rights to install Microsoft C++ Build Tools.
## Repository layout
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Install job-local dependencies on Linux Actions runners.
set -euo pipefail
mode="${1:-}"
case "$mode" in
rust|image|java|release) ;;
*) echo "Usage: $0 {rust|image|java|release}" >&2; exit 2 ;;
esac
[[ "$(uname -s)" == Linux ]] || { echo 'This setup tool requires Linux.' >&2; exit 1; }
add_path() {
export PATH="$1:$PATH"
for path_file in "${GITHUB_PATH:-}" "${GITEA_PATH:-}"; do
[[ -z "$path_file" ]] || printf '%s\n' "$1" >> "$path_file"
done
}
install_packages() {
local apt=()
local missing=()
command -v apt-get >/dev/null || { echo 'Automatic system package installation requires apt-get (Ubuntu/Debian runner).' >&2; exit 1; }
for package in "$@"; do
dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -q 'install ok installed' || missing+=("$package")
done
[[ ${#missing[@]} -gt 0 ]] || return 0
if [[ "$(id -u)" != 0 ]]; then
command -v sudo >/dev/null || { echo 'System packages require root or passwordless sudo.' >&2; exit 1; }
sudo -n true || { echo 'Passwordless sudo is required for system packages.' >&2; exit 1; }
apt=(sudo -n)
fi
"${apt[@]}" apt-get update
DEBIAN_FRONTEND=noninteractive "${apt[@]}" apt-get install -y --no-install-recommends "${missing[@]}"
}
require() {
command -v "$1" >/dev/null || { echo "Missing $1 after dependency setup." >&2; exit 1; }
}
case "$mode" in
rust)
install_packages build-essential curl file libayatana-appindicator3-dev librsvg2-dev libssl-dev libwebkit2gtk-4.1-dev libxdo-dev pkg-config wget
if ! command -v rustup >/dev/null; then
installer="$(mktemp)"
trap 'rm -f "$installer"' EXIT
curl -fsSL https://sh.rustup.rs -o "$installer"
sh "$installer" -y --profile minimal --default-toolchain stable
fi
add_path "${CARGO_HOME:-$HOME/.cargo}/bin"
rustup toolchain install stable --profile minimal --component rustfmt --component clippy
rustup default stable
require cargo
require rustc
require node
require npm
[[ "$(node -p 'process.versions.node.split(".")[0]')" -ge 22 ]] || { echo 'Node 22+ is required.' >&2; exit 1; }
pkg-config --exists webkit2gtk-4.1 ayatana-appindicator3-0.1 librsvg-2.0
;;
image)
require docker
docker info >/dev/null || { echo 'Docker daemon is unavailable. Mount the host socket or run a Docker-capable host runner.' >&2; exit 1; }
docker buildx version >/dev/null || { echo 'Docker Buildx is missing. Install the Docker buildx plugin on the host runner.' >&2; exit 1; }
;;
java)
require java
[[ -n "${2:-}" ]] || { echo 'Java major version is required.' >&2; exit 2; }
java -version 2>&1 | grep -q "${2}\." || { echo "Java $2 is required for this integration build." >&2; exit 1; }
require bash
;;
release)
if ! command -v curl >/dev/null || ! command -v jq >/dev/null; then install_packages curl jq; fi
require curl
require jq
;;
esac
echo "Linux $mode dependencies are ready."
+70
View File
@@ -0,0 +1,70 @@
# Installs job-local PowerShell and Rust dependencies for the Windows launcher.
param([ValidateSet('Launcher')][string]$Mode = 'Launcher')
$ErrorActionPreference = 'Stop'
if (-not [Environment]::OSVersion.Platform.ToString().StartsWith('Win')) {
throw 'This setup tool requires Windows.'
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
if (-not $env:RUNNER_TEMP) { $env:RUNNER_TEMP = $env:TEMP }
function Add-RunnerPath([string]$Directory) {
$env:PATH = "$Directory;$env:PATH"
foreach ($pathFile in @($env:GITHUB_PATH, $env:GITEA_PATH)) {
if ($pathFile) { Add-Content -Path $pathFile -Value $Directory }
}
}
$pwsh = Get-Command pwsh.exe -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Source
if (-not $pwsh) {
$machinePwsh = Join-Path $env:ProgramFiles 'PowerShell\7\pwsh.exe'
if (Test-Path $machinePwsh) { $pwsh = $machinePwsh }
}
if (-not $pwsh) {
$version = '7.6.6'
$installDir = Join-Path $env:RUNNER_TEMP "scopenet-pwsh-$version"
$pwsh = Join-Path $installDir 'pwsh.exe'
if (-not (Test-Path $pwsh)) {
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
$archive = Join-Path $env:RUNNER_TEMP "PowerShell-$version-win-x64.zip"
Invoke-WebRequest -UseBasicParsing -Uri "https://github.com/PowerShell/PowerShell/releases/download/v$version/PowerShell-$version-win-x64.zip" -OutFile $archive
Expand-Archive -Path $archive -DestinationPath $installDir -Force
Remove-Item $archive
}
}
Add-RunnerPath (Split-Path $pwsh)
Write-Host "PowerShell $(& $pwsh -NoProfile -Command '$PSVersionTable.PSVersion.ToString()') is ready."
$cargoBin = Join-Path $env:USERPROFILE '.cargo\bin'
Add-RunnerPath $cargoBin
if (-not (Get-Command rustup.exe -ErrorAction SilentlyContinue)) {
$installer = Join-Path $env:RUNNER_TEMP 'scopenet-rustup-init.exe'
Invoke-WebRequest -UseBasicParsing -Uri 'https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe' -OutFile $installer
& $installer -y --profile minimal --default-toolchain stable
if ($LASTEXITCODE -ne 0) { throw "rustup installer failed with exit code $LASTEXITCODE" }
Remove-Item $installer
}
& rustup toolchain install stable-x86_64-pc-windows-msvc --profile minimal --component clippy --component rustfmt
if ($LASTEXITCODE -ne 0) { throw "Rust toolchain install failed with exit code $LASTEXITCODE" }
& rustup default stable-x86_64-pc-windows-msvc
if ($LASTEXITCODE -ne 0) { throw "Rust toolchain selection failed with exit code $LASTEXITCODE" }
$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
$vsPath = if (Test-Path $vswhere) { & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath }
if (-not $vsPath) {
$installer = Join-Path $env:RUNNER_TEMP 'scopenet-vs-buildtools.exe'
Invoke-WebRequest -UseBasicParsing -Uri 'https://aka.ms/vs/17/release/vs_buildtools.exe' -OutFile $installer
$arguments = @('--quiet', '--wait', '--norestart', '--add', 'Microsoft.VisualStudio.Workload.VCTools', '--includeRecommended')
$process = Start-Process -FilePath $installer -ArgumentList $arguments -Wait -PassThru
if ($process.ExitCode -eq 3010) { throw 'Microsoft C++ Build Tools installed, but Windows must be restarted before this runner can build.' }
if ($process.ExitCode -ne 0) { throw "Microsoft C++ Build Tools installation failed with exit code $($process.ExitCode). Run the runner with administrator rights." }
Remove-Item $installer
$vsPath = if (Test-Path $vswhere) { & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath }
if (-not $vsPath) { throw 'Microsoft C++ Build Tools installation did not provide the x64 MSVC compiler.' }
}
Write-Host "Microsoft C++ Build Tools are ready at $vsPath."
foreach ($tool in @('cargo.exe', 'rustc.exe', 'node.exe', 'npm.cmd')) {
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) { throw "Missing $tool after dependency setup." }
}
$nodeMajor = [int](& node -p 'process.versions.node.split(".")[0]')
if ($nodeMajor -lt 22) { throw 'Node 22+ is required.' }
Write-Host "Windows $Mode dependencies are ready."