# peardata rolling release — Linux Bare servers + Electron clients (all 64-bit hosts). # # Secrets: # RELEASE_TOKEN — Gitea PAT with repo release write (required) # GITEA_URL — optional forge base URL # # Server hosts: linux-x64, linux-arm64 only # Client hosts: linux-x64, linux-arm64, darwin-x64, darwin-arm64, win32-x64, win32-arm64 name: Release rolling on: push: branches: [main, master] workflow_dispatch: inputs: skip_client: description: 'Skip Electron client builds (server only)' required: false default: 'false' server_hosts: description: 'Comma-separated Linux server hosts' required: false default: 'linux-x64,linux-arm64' client_hosts: description: 'Comma-separated 64-bit client hosts' required: false default: 'linux-x64,linux-arm64,darwin-x64,darwin-arm64,win32-x64,win32-arm64' dry_run: description: 'Build artifacts without uploading' required: false default: 'false' concurrency: group: release-rolling cancel-in-progress: true env: NODE_OPTIONS: '--dns-result-order=ipv4first' jobs: release: runs-on: ubuntu-latest timeout-minutes: 180 steps: - uses: actions/checkout@v4 - name: Use Node.js 22 uses: actions/setup-node@v4 timeout-minutes: 5 with: node-version: '22' - name: Install system deps (electron + cross packaging) timeout-minutes: 8 env: DEBIAN_FRONTEND: noninteractive run: | set -euo pipefail APT_OPTS=( -o Acquire::ForceIPv4=true -o Acquire::Retries=3 -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 ) if [ -f /etc/apt/sources.list.d/microsoft-prod.list ]; then sudo mv /etc/apt/sources.list.d/microsoft-prod.list /etc/apt/sources.list.d/microsoft-prod.list.bak || true fi sudo apt-get update "${APT_OPTS[@]}" || true sudo apt-get install -y "${APT_OPTS[@]}" \ libnss3 \ libatk-bridge2.0-0 \ libgtk-3-0 \ libgbm1 \ libasound2t64 \ zip \ unzip \ ca-certificates - name: Install dependencies timeout-minutes: 15 env: NODE_OPTIONS: '--dns-result-order=ipv4first' GIT_TERMINAL_PROMPT: '0' ELECTRON_SKIP_BINARY_DOWNLOAD: '1' npm_config_fetch_retries: '3' npm_config_fetch_timeout: '120000' npm_config_fund: 'false' npm_config_audit: 'false' run: | set -euo pipefail git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" git config --global url."https://github.com/".insteadOf "git@github.com:" echo "==> npm ci (ignore lifecycle scripts — avoid electron hangs)" npm ci --ignore-scripts --no-audit --no-fund --loglevel=info echo "==> esbuild binary" node node_modules/esbuild/install.js node -e "console.log('node', process.version); console.log('esbuild', require('esbuild').version)" # QVAC: npm ci skips os/cpu-mismatched optional bare-runtime-* packages. # Force-install every client host binary so Linux CI can package darwin/win32. # https://github.com/tetherto/qvac/issues/1492 echo "==> ensure QVAC bare-runtime platform packages" node scripts/ensure-qvac-bare-runtimes.cjs --all - name: Unit tests timeout-minutes: 10 env: SKIP_INTEGRATION: '1' run: npm test - name: Install rcodesign (macOS codesign on Linux) timeout-minutes: 2 run: | set -euo pipefail ARCH="$(uname -m)" case "$ARCH" in x86_64|amd64) HOST=linux-x64 ;; aarch64|arm64) HOST=linux-arm64 ;; *) echo "unsupported arch $ARCH for rcodesign"; exit 1 ;; esac SRC="tools/rcodesign/${HOST}/rcodesign" if [ ! -f "$SRC" ]; then echo "ERROR: vendored rcodesign missing at $SRC" echo "See tools/rcodesign/README.md" exit 1 fi sudo install -m 0755 "$SRC" /usr/local/bin/rcodesign echo "Installed from $SRC ($(cat "tools/rcodesign/${HOST}/VERSION" 2>/dev/null || echo unknown))" rcodesign --version - name: Build all hosts + publish rolling release env: RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} GITEA_URL: ${{ secrets.GITEA_URL }} GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_SHA: ${{ github.sha }} GITEA_SHA: ${{ github.sha }} NODE_OPTIONS: '--dns-result-order=ipv4first' PEARDATA_SERVER_HOSTS: ${{ github.event.inputs.server_hosts || 'linux-x64,linux-arm64' }} PEARDATA_CLIENT_HOSTS: ${{ github.event.inputs.client_hosts || 'linux-x64,linux-arm64,darwin-x64,darwin-arm64,win32-x64,win32-arm64' }} PEARDATA_SKIP_CLIENT: ${{ github.event.inputs.skip_client == 'true' && '1' || '0' }} DRY_RUN: ${{ github.event.inputs.dry_run == 'true' && '1' || '0' }} RELEASE_TAG: rolling npm_config_build_from_source: 'false' PEARDATA_SKIP_REBUILD: '1' ELECTRON_CACHE: ${{ github.workspace }}/.cache/electron electron_config_cache: ${{ github.workspace }}/.cache/electron PEARDATA_ELECTRON_DOWNLOAD_TIMEOUT_MS: '180000' # QVAC bundleSdk + forge package is heavy; 8m was tight for multi-host matrix PEARDATA_CLIENT_TIMEOUT_MS: '1200000' ELECTRON_GET_USE_PROXY: '0' CI: 'true' run: | set -euo pipefail if [ "${DRY_RUN:-0}" != "1" ] && [ -z "${RELEASE_TOKEN:-}" ]; then echo "ERROR: secret RELEASE_TOKEN is not set" exit 1 fi if [ -n "${GITHUB_REPOSITORY:-}" ]; then export GITEA_OWNER="${GITHUB_REPOSITORY%%/*}" export GITEA_REPO="${GITHUB_REPOSITORY#*/}" fi if [ -z "${GITEA_URL:-}" ]; then export GITEA_URL="${GITHUB_SERVER_URL:-}" fi mkdir -p "${ELECTRON_CACHE:-$GITHUB_WORKSPACE/.cache/electron}" mkdir -p "$GITHUB_WORKSPACE/.cache/electron-zips" echo "Server hosts (Linux only): $PEARDATA_SERVER_HOSTS" echo "Client hosts: $PEARDATA_CLIENT_HOSTS" chmod +x scripts/gitea-rolling-release.sh scripts/bare-standalone.cjs scripts/make.cjs scripts/predownload-electron.cjs bash scripts/gitea-rolling-release.sh