mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-24 20:05:39 -04:00
599 lines
19 KiB
YAML
599 lines
19 KiB
YAML
# Build workflow for BYOK fork of GDevelop
|
|
#
|
|
# Multi-job pipeline:
|
|
# 1. validate — lint, syntax checks, unit tests
|
|
# 2. gdevelop-js-build — compile GDevelop.js (C++ → WASM via Emscripten),
|
|
# upload libGD.js + libGD.wasm as CI artifacts
|
|
# 3. app-build — compile React frontend (react-app-rewired),
|
|
# build GDJS game engine runtime (esbuild),
|
|
# assemble Electron preview deps
|
|
# (@electron/remote → preview_node_modules),
|
|
# upload app-build artifact
|
|
# 4. platform-build — Electron platform installer builds (5-ary matrix)
|
|
# 5. release — create a GitHub release (pre-release from master
|
|
# push, draft release from v* tag, or from
|
|
# workflow_dispatch)
|
|
#
|
|
# Release modes:
|
|
# - Push to master → validate → gdevelop-js-build → app-build → platform-build → auto pre-release (with platform artifacts)
|
|
# - Push a v* tag → validate → gdevelop-js-build → app-build → platform-build → draft release (with platform artifacts)
|
|
# - workflow_dispatch → validate → gdevelop-js-build → app-build → platform-build → release for tag (with platform artifacts)
|
|
|
|
name: Build
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
tags:
|
|
- "v*"
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: "Tag to release (e.g. v1.0.0)"
|
|
required: false
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
NODE_VERSION: "18"
|
|
|
|
jobs:
|
|
validate:
|
|
name: Validate
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Cache newIDE node_modules
|
|
id: cache
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: newIDE/app/node_modules
|
|
key: newide-build-v1-${{ hashFiles('newIDE/app/package-lock.json') }}
|
|
|
|
- name: Install dependencies
|
|
if: steps.cache.outputs.cache-hit != 'true'
|
|
working-directory: newIDE/app
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Lint
|
|
working-directory: newIDE/app
|
|
run: npm run lint
|
|
|
|
- name: BYOK syntax check
|
|
run: |
|
|
for f in newIDE/electron-app/app/byok/*.js \
|
|
newIDE/electron-app/app/byok/tests/*.test.js; do
|
|
node -c "$f" && echo " ✓ $f" || exit 1
|
|
done
|
|
|
|
- name: BYOK unit tests
|
|
working-directory: newIDE/electron-app/app/byok
|
|
run: |
|
|
node --test \
|
|
tests/errors.test.js \
|
|
tests/buildSystemPrompt.test.js \
|
|
tests/requestStore.test.js \
|
|
tests/callLLM.test.js
|
|
|
|
gdevelop-js-build:
|
|
name: GDevelop.js Emscripten build
|
|
needs: validate
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Cache GDevelop.js node_modules
|
|
id: cache-gdjs
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: GDevelop.js/node_modules
|
|
key: gdjs-v1-${{ hashFiles('GDevelop.js/package-lock.json') }}
|
|
|
|
- name: Install Emscripten SDK
|
|
uses: mymindstorm/setup-emsdk@v1
|
|
|
|
- name: Install GDevelop.js dependencies
|
|
working-directory: GDevelop.js
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Build GDevelop.js (Emscripten → WASM)
|
|
working-directory: GDevelop.js
|
|
run: npm run build
|
|
|
|
- name: Verify build artifacts
|
|
run: |
|
|
echo "=== GDevelop.js build artifact verification ==="
|
|
test -f newIDE/app/public/libGD.js \
|
|
|| { echo "❌ libGD.js not found in newIDE/app/public/"; exit 1; }
|
|
test -f newIDE/app/public/libGD.wasm \
|
|
|| { echo "❌ libGD.wasm not found in newIDE/app/public/"; exit 1; }
|
|
|
|
JS_SIZE=$(stat -c%s newIDE/app/public/libGD.js 2>/dev/null || echo 0)
|
|
WASM_SIZE=$(stat -c%s newIDE/app/public/libGD.wasm 2>/dev/null || echo 0)
|
|
MAX_SIZE=2097152
|
|
|
|
echo "libGD.js: ${JS_SIZE} bytes"
|
|
echo "libGD.wasm: ${WASM_SIZE} bytes"
|
|
|
|
if [ "${JS_SIZE}" -gt "${MAX_SIZE}" ]; then
|
|
echo "❌ libGD.js exceeds 2 MiB limit (${JS_SIZE} > ${MAX_SIZE})"
|
|
exit 1
|
|
fi
|
|
echo "✅ libGD.js size check passed (under 2 MiB)"
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: gdjs-build
|
|
path: newIDE/app/public/
|
|
|
|
app-build:
|
|
name: App + GDJS Runtime Build
|
|
needs: [validate, gdevelop-js-build]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Cache newIDE/app node_modules
|
|
id: cache-app
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: newIDE/app/node_modules
|
|
key: newide-app-v1-${{ hashFiles('newIDE/app/package-lock.json') }}
|
|
|
|
- name: Cache GDJS node_modules
|
|
id: cache-gdjs-rt
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: GDJS/node_modules
|
|
key: gdjs-rt-v1-${{ hashFiles('GDJS/package-lock.json') }}
|
|
|
|
- name: Cache electron-app node_modules
|
|
id: cache-electron
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: newIDE/electron-app/node_modules
|
|
key: electron-app-v1-${{ hashFiles('newIDE/electron-app/package-lock.json') }}
|
|
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
name: gdjs-build
|
|
path: newIDE/app/public/
|
|
|
|
- name: Install app dependencies
|
|
working-directory: newIDE/app
|
|
run: npm ci
|
|
|
|
- name: Build React app
|
|
working-directory: newIDE/app
|
|
run: npm run build
|
|
|
|
- name: Install Electron dependencies
|
|
working-directory: newIDE/electron-app
|
|
run: npm ci
|
|
|
|
- name: Verify outputs
|
|
run: |
|
|
echo "=== App Build Verification ==="
|
|
MISSING=0
|
|
if [ -f newIDE/app/build/index.html ]; then
|
|
echo "✅ newIDE/app/build/index.html"
|
|
else
|
|
echo "❌ newIDE/app/build/index.html MISSING"
|
|
MISSING=1
|
|
fi
|
|
if [ -d newIDE/app/resources/GDJS/Runtime ]; then
|
|
echo "✅ newIDE/app/resources/GDJS/Runtime/"
|
|
else
|
|
echo "❌ newIDE/app/resources/GDJS/Runtime/ MISSING"
|
|
MISSING=1
|
|
fi
|
|
if [ -d newIDE/app/resources/preview_node_modules/@electron/remote ]; then
|
|
echo "✅ newIDE/app/resources/preview_node_modules/@electron/remote"
|
|
else
|
|
echo "❌ newIDE/app/resources/preview_node_modules/@electron/remote MISSING"
|
|
MISSING=1
|
|
fi
|
|
if [ "$MISSING" -eq 1 ]; then
|
|
echo "❌ Verification FAILED"
|
|
exit 1
|
|
fi
|
|
echo "✅ All outputs verified"
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: app-build
|
|
path: |
|
|
newIDE/app/build/
|
|
newIDE/app/resources/GDJS/
|
|
newIDE/app/resources/preview_node_modules/
|
|
|
|
platform-build:
|
|
name: Build (${{ matrix.name }})
|
|
needs: [app-build]
|
|
runs-on: ${{ matrix.os }}
|
|
continue-on-error: true
|
|
timeout-minutes: 30
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- name: linux-x64
|
|
os: ubuntu-latest
|
|
builder-args: --linux --x64
|
|
- name: linux-arm64
|
|
os: ubuntu-latest
|
|
builder-args: --linux --arm64
|
|
- name: mac-universal
|
|
os: macos-latest
|
|
builder-args: --mac --universal
|
|
- name: win-x64
|
|
os: windows-latest
|
|
builder-args: --win --x64
|
|
- name: win-arm64
|
|
os: windows-11-arm64
|
|
builder-args: --win --arm64
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Cache electron-app node_modules
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: newIDE/electron-app/node_modules
|
|
key: electron-app-v1-${{ hashFiles('newIDE/electron-app/package-lock.json') }}
|
|
|
|
- name: Install libfuse2 (Linux only)
|
|
if: startsWith(matrix.os, 'ubuntu')
|
|
run: sudo apt-get install -y libfuse2
|
|
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
name: gdjs-build
|
|
path: newIDE/app/public/
|
|
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
name: app-build
|
|
|
|
- name: Install electron-app dependencies
|
|
working-directory: newIDE/electron-app
|
|
run: npm ci
|
|
|
|
- name: Copy React bundle to app/www
|
|
working-directory: newIDE/electron-app
|
|
run: node scripts/app-build.js --skip-app-build
|
|
|
|
- name: Build platform installer
|
|
working-directory: newIDE/electron-app
|
|
run: npx electron-builder --config=electron-builder-config.js ${{ matrix.builder-args }} --publish never
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: gdevelop-${{ matrix.name }}
|
|
path: newIDE/electron-app/dist/
|
|
|
|
gdevelop-js-build:
|
|
name: GDevelop.js Emscripten build
|
|
needs: validate
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Cache GDevelop.js node_modules
|
|
id: cache-gdjs
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: GDevelop.js/node_modules
|
|
key: gdjs-v1-${{ hashFiles('GDevelop.js/package-lock.json') }}
|
|
|
|
- name: Install Emscripten SDK
|
|
uses: mymindstorm/setup-emsdk@v1
|
|
|
|
- name: Install GDevelop.js dependencies
|
|
working-directory: GDevelop.js
|
|
run: npm ci --ignore-scripts
|
|
|
|
- name: Build GDevelop.js (Emscripten → WASM)
|
|
working-directory: GDevelop.js
|
|
run: npm run build
|
|
|
|
- name: Verify build artifacts
|
|
run: |
|
|
echo "=== GDevelop.js build artifact verification ==="
|
|
test -f newIDE/app/public/libGD.js \
|
|
|| { echo "❌ libGD.js not found in newIDE/app/public/"; exit 1; }
|
|
test -f newIDE/app/public/libGD.wasm \
|
|
|| { echo "❌ libGD.wasm not found in newIDE/app/public/"; exit 1; }
|
|
|
|
JS_SIZE=$(stat -c%s newIDE/app/public/libGD.js 2>/dev/null || echo 0)
|
|
WASM_SIZE=$(stat -c%s newIDE/app/public/libGD.wasm 2>/dev/null || echo 0)
|
|
MAX_SIZE=2097152
|
|
|
|
echo "libGD.js: ${JS_SIZE} bytes"
|
|
echo "libGD.wasm: ${WASM_SIZE} bytes"
|
|
|
|
if [ "${JS_SIZE}" -gt "${MAX_SIZE}" ]; then
|
|
echo "❌ libGD.js exceeds 2 MiB limit (${JS_SIZE} > ${MAX_SIZE})"
|
|
exit 1
|
|
fi
|
|
echo "✅ libGD.js size check passed (under 2 MiB)"
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: gdjs-build
|
|
path: newIDE/app/public/
|
|
|
|
app-build:
|
|
name: App + GDJS Runtime Build
|
|
needs: [validate, gdevelop-js-build]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Cache newIDE/app node_modules
|
|
id: cache-app
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: newIDE/app/node_modules
|
|
key: newide-app-v1-${{ hashFiles('newIDE/app/package-lock.json') }}
|
|
|
|
- name: Cache GDJS node_modules
|
|
id: cache-gdjs-rt
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: GDJS/node_modules
|
|
key: gdjs-rt-v1-${{ hashFiles('GDJS/package-lock.json') }}
|
|
|
|
- name: Cache electron-app node_modules
|
|
id: cache-electron
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: newIDE/electron-app/node_modules
|
|
key: electron-app-v1-${{ hashFiles('newIDE/electron-app/package-lock.json') }}
|
|
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
name: gdjs-build
|
|
path: newIDE/app/public/
|
|
|
|
- name: Install app dependencies
|
|
working-directory: newIDE/app
|
|
run: npm ci
|
|
|
|
- name: Build React app
|
|
working-directory: newIDE/app
|
|
run: npm run build
|
|
|
|
- name: Install Electron dependencies
|
|
working-directory: newIDE/electron-app
|
|
run: npm ci
|
|
|
|
- name: Verify outputs
|
|
run: |
|
|
echo "=== App Build Verification ==="
|
|
MISSING=0
|
|
if [ -f newIDE/app/build/index.html ]; then
|
|
echo "✅ newIDE/app/build/index.html"
|
|
else
|
|
echo "❌ newIDE/app/build/index.html MISSING"
|
|
MISSING=1
|
|
fi
|
|
if [ -d newIDE/app/resources/GDJS/Runtime ]; then
|
|
echo "✅ newIDE/app/resources/GDJS/Runtime/"
|
|
else
|
|
echo "❌ newIDE/app/resources/GDJS/Runtime/ MISSING"
|
|
MISSING=1
|
|
fi
|
|
if [ -d newIDE/app/resources/preview_node_modules/@electron/remote ]; then
|
|
echo "✅ newIDE/app/resources/preview_node_modules/@electron/remote"
|
|
else
|
|
echo "❌ newIDE/app/resources/preview_node_modules/@electron/remote MISSING"
|
|
MISSING=1
|
|
fi
|
|
if [ "$MISSING" -eq 1 ]; then
|
|
echo "❌ Verification FAILED"
|
|
exit 1
|
|
fi
|
|
echo "✅ All outputs verified"
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: app-build
|
|
path: |
|
|
newIDE/app/build/
|
|
newIDE/app/resources/GDJS/
|
|
newIDE/app/resources/preview_node_modules/
|
|
|
|
platform-build:
|
|
name: Build (${{ matrix.name }})
|
|
needs: [app-build]
|
|
runs-on: ${{ matrix.os }}
|
|
continue-on-error: true
|
|
timeout-minutes: 30
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- name: linux-x64
|
|
os: ubuntu-latest
|
|
builder-args: --linux --x64
|
|
- name: linux-arm64
|
|
os: ubuntu-latest
|
|
builder-args: --linux --arm64
|
|
- name: mac-universal
|
|
os: macos-latest
|
|
builder-args: --mac --universal
|
|
- name: win-x64
|
|
os: windows-latest
|
|
builder-args: --win --x64
|
|
- name: win-arm64
|
|
os: windows-11-arm64
|
|
builder-args: --win --arm64
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
|
|
- name: Cache electron-app node_modules
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: newIDE/electron-app/node_modules
|
|
key: electron-app-v1-${{ hashFiles('newIDE/electron-app/package-lock.json') }}
|
|
|
|
- name: Install libfuse2 (Linux only)
|
|
if: startsWith(matrix.os, 'ubuntu')
|
|
run: sudo apt-get install -y libfuse2
|
|
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
name: gdjs-build
|
|
path: newIDE/app/public/
|
|
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
name: app-build
|
|
|
|
- name: Install electron-app dependencies
|
|
working-directory: newIDE/electron-app
|
|
run: npm ci
|
|
|
|
- name: Copy React bundle to app/www
|
|
working-directory: newIDE/electron-app
|
|
run: node scripts/app-build.js --skip-app-build
|
|
|
|
- name: Build platform installer
|
|
working-directory: newIDE/electron-app
|
|
run: npx electron-builder --config=electron-builder-config.js ${{ matrix.builder-args }} --publish never
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: gdevelop-${{ matrix.name }}
|
|
path: newIDE/electron-app/dist/
|
|
|
|
release:
|
|
name: ${{ github.ref_type == 'tag' && 'Create release' || 'Create pre-release' }}
|
|
needs: [validate, gdevelop-js-build, app-build, platform-build]
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
outputs:
|
|
release_url: ${{ steps.create.outputs.url }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
# Full history + tags for changelog generation across the
|
|
# previous-to-current-tag range.
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Determine release tag and type
|
|
id: info
|
|
run: |
|
|
IS_PRERELEASE="false"
|
|
|
|
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
|
TAG="${{ inputs.tag }}"
|
|
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
|
|
TAG="${GITHUB_REF_NAME}"
|
|
else
|
|
# Push to master — auto-generate a unique pre-release tag.
|
|
APP_VERSION=$(node -e \
|
|
"console.log(require('./newIDE/electron-app/app/package.json').version)")
|
|
TS=$(date -u +%Y%m%d%H%M%S)
|
|
SHA="${GITHUB_SHA:0:7}"
|
|
TAG="v${APP_VERSION}-pre.${TS}.${SHA}"
|
|
IS_PRERELEASE="true"
|
|
fi
|
|
|
|
if [ -z "$TAG" ]; then
|
|
echo "::error::No tag specified. For workflow_dispatch, provide the 'tag' input."
|
|
exit 1
|
|
fi
|
|
|
|
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
echo "is_prerelease=${IS_PRERELEASE}" >> "$GITHUB_OUTPUT"
|
|
echo "Release tag: ${TAG} (prerelease: ${IS_PRERELEASE})"
|
|
|
|
- name: Generate release notes
|
|
id: notes
|
|
run: |
|
|
TAG="${{ steps.info.outputs.tag }}"
|
|
IS_PRERELEASE="${{ steps.info.outputs.is_prerelease }}"
|
|
PREV_TAG=$(git tag --sort=-creatordate | sed -n '2p')
|
|
|
|
if [ -n "$PREV_TAG" ]; then
|
|
RANGE="${PREV_TAG}..HEAD"
|
|
else
|
|
RANGE="HEAD"
|
|
fi
|
|
|
|
echo "Changelog range: ${RANGE}"
|
|
CHANGELOG=$(git log --oneline --no-merges "$RANGE" 2>/dev/null || \
|
|
git log --oneline --no-merges --max-count=30)
|
|
|
|
{
|
|
echo "## ${IS_PRERELEASE:+Pre-release }Changes"
|
|
echo
|
|
echo '```'
|
|
echo "$CHANGELOG"
|
|
echo '```'
|
|
} > /tmp/release-notes.md
|
|
echo "notes_path=/tmp/release-notes.md" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Download platform artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
pattern: gdevelop-*
|
|
merge-multiple: true
|
|
|
|
- name: Create GitHub Release
|
|
id: create
|
|
uses: softprops/action-gh-release@v1
|
|
with:
|
|
tag_name: ${{ steps.info.outputs.tag }}
|
|
name: ${{ steps.info.outputs.tag }}
|
|
body_path: ${{ steps.notes.outputs.notes_path }}
|
|
prerelease: ${{ steps.info.outputs.is_prerelease == 'true' }}
|
|
# Pre-releases are published immediately (not draft) so consumers
|
|
# can download them. Tagged releases are draft-only for review.
|
|
draft: ${{ steps.info.outputs.is_prerelease != 'true' }}
|
|
generate_release_notes: false
|
|
files: |
|
|
*.AppImage
|
|
*.deb
|
|
*.dmg
|
|
*.exe
|
|
*.zip
|