Skip to content

Commit 06e8e3b

Browse files
SimHackermcarlson
andauthored
Don unity build (#58)
* now supports multiple simulators, controller navigation tab has simulator menu, qr code urls set simulator to correspond with each simulator, user can switch controller's simulator with menu, menu updates when new simulators attach and leave. (#53) (#55) Co-authored-by: Don Hopkins <[email protected]> * committing and pushing to main to work around new github actions bug * added build trigger script * tweaks * tweaks * tweaks * Stop tracking ProjectVersion.txt via LFS; commit real text * tweak * tweak * tweak * tweak * tweak * tweak * tweak * tweak * tweak * tweak * tweak * tweak * built * tweak * tweak * tweak * tweak * tweak * tweak * tweak * tweak * tweak --------- Co-authored-by: mcarlson <[email protected]>
1 parent 19c1fa2 commit 06e8e3b

File tree

20 files changed

+607
-74
lines changed

20 files changed

+607
-74
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@
4848
*.mp3 filter=lfs diff=lfs merge=lfs -text
4949
*.wav filter=lfs diff=lfs merge=lfs -text
5050
*.ogg filter=lfs diff=lfs merge=lfs -text
51+
Unity/**/ProjectSettings/ProjectVersion.txt text eol=lf -filter -diff -merge
Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
###################################################################################################
2+
# Build Unity SpaceCraft – GitHub Actions (Ubuntu runner)
3+
#
4+
# Overview
5+
# - Builds the Unity SpaceCraft project for WebGL on GitHub-hosted Linux runners.
6+
# - Auto-detects Unity version from ProjectVersion.txt (override via input).
7+
# - Supports Production/Development profiles or a fully custom build method.
8+
# - Caches the Unity Library folder for faster imports/compiles between runs.
9+
# - Downloads real LFS asset blobs for the checked-out commit (required for Unity).
10+
# - Uploads build artifacts for later download/deploy.
11+
#
12+
# Requirements (repo secrets)
13+
# - UNITY_LICENSE: Unity license file contents (game-ci format) or ULF text.
14+
# - UNITY_EMAIL: Unity account email (for legacy activation flows in builder).
15+
# - UNITY_PASSWORD: Unity account password (for legacy activation flows in builder).
16+
#
17+
# Inputs (workflow_dispatch)
18+
# - unityVersion: Unity Editor version (e.g., 2022.3.45f1). Use 'auto' to parse ProjectVersion.txt.
19+
# - projectPath: Path to the Unity project. Defaults to Unity/SpaceCraft.
20+
# - targetPlatform: Build target (WebGL). Extendable if needed.
21+
# - buildProfile: Convenience selector mapping to build methods (Production/Development).
22+
# - buildMethod: Explicit Unity C# method string, overrides buildProfile. Example:
23+
# SpaceCraft.Editor.Builds.BuildWebGLProduction
24+
#
25+
# Build method expectations (Unity side)
26+
# - The selected build method should be a static C# function callable by Unity with:
27+
# - No arguments (or signature supported by Unity batchmode).
28+
# - It should configure build options and write the WebGL build output into the project Build/ path
29+
# or another deterministic directory consumed by artifact upload below.
30+
# - Example namespace/class/method naming is provided here as a convention; implement accordingly.
31+
#
32+
# Caching strategy
33+
# - Caches the Library/ folder per (OS, Unity version, Packages/manifest.json hash) to reduce reimport.
34+
# - On cache hits, compilations and imports should be much faster.
35+
# - We intentionally do not cache Temp/ or final Build/ outputs; those are uploaded as artifacts.
36+
#
37+
# LFS and checkout
38+
# - actions/checkout is configured with lfs: true and fetch-depth: 1
39+
# - Ensures real LFS blobs for the current commit are available to the build.
40+
# - Uses shallow history for speed (no need for full Git history in CI).
41+
#
42+
# Artifacts
43+
# - Uploads the default game-ci build/ directory and the project Build/ directory.
44+
# - Adjust artifact paths if your build method writes to a different location.
45+
#
46+
# Invocation examples
47+
# - Production (auto-detect Unity, default project path):
48+
# unityVersion: auto
49+
# buildProfile: WebGLProductionBuild
50+
# - Development:
51+
# unityVersion: auto
52+
# buildProfile: WebGLDevelopmentBuild
53+
# - Explicit method (overrides profile mapping):
54+
# buildMethod: SpaceCraft.Editor.Builds.BuildWebGLProduction
55+
#
56+
# Notes
57+
# - This workflow focuses on GitHub-hosted runners (no self-hosted required).
58+
# - For further speed-ups, consider enabling editor caching in the action if appropriate and supported
59+
# by your environment, or splitting content generation into a separate, cacheable step.
60+
###################################################################################################
61+
name: Build Unity SpaceCraft
62+
63+
on:
64+
workflow_dispatch:
65+
inputs:
66+
unityVersion:
67+
description: "Unity Editor version (e.g. 2022.3.45f1). Use 'auto' to detect from ProjectVersion.txt"
68+
required: false
69+
default: "auto"
70+
type: string
71+
projectPath:
72+
description: "Unity project path"
73+
required: false
74+
default: "Unity/SpaceCraft"
75+
type: string
76+
targetPlatform:
77+
description: "Unity target platform"
78+
required: false
79+
default: "WebGL"
80+
type: choice
81+
options:
82+
- WebGL
83+
buildProfile:
84+
description: "Build profile token (maps to a Unity build method)"
85+
required: false
86+
default: "WebGLProductionBuild"
87+
type: choice
88+
options:
89+
- WebGLProductionBuild
90+
- WebGLDevelopmentBuild
91+
buildMethod:
92+
description: "Explicit Unity build method (overrides buildProfile). Example: SpaceCraft.Editor.Builds.BuildWebGLProduction"
93+
required: false
94+
default: ""
95+
type: string
96+
97+
jobs:
98+
build:
99+
name: Build ${{ inputs.targetPlatform }} (${{ inputs.buildProfile }})
100+
runs-on: ubuntu-latest
101+
timeout-minutes: 90
102+
103+
env:
104+
PROJECT_PATH: ${{ inputs.projectPath }}
105+
TARGET_PLATFORM: ${{ inputs.targetPlatform }}
106+
107+
steps:
108+
- name: Checkout
109+
uses: actions/checkout@v4
110+
with:
111+
lfs: true
112+
fetch-depth: 1
113+
114+
- name: Ensure LFS files are materialized (smudged)
115+
shell: bash
116+
run: |
117+
set -euo pipefail
118+
echo "[lfs] git lfs version:" && git lfs version || true
119+
echo "[lfs] Pulling LFS objects (broad)"
120+
git lfs pull --exclude="" --include="" || true
121+
echo "[lfs] Forcing checkout (smudge) of LFS pointers"
122+
git lfs checkout || true
123+
124+
- name: Detect Unity version and resolve project path
125+
id: detect
126+
shell: bash
127+
run: |
128+
set -euo pipefail
129+
echo "[detect] GITHUB_WORKSPACE=${{ github.workspace }}"
130+
echo "[detect] inputs.projectPath='${{ inputs.projectPath }}' inputs.unityVersion='${{ inputs.unityVersion }}'"
131+
echo "[detect] Workspace root listing:"
132+
ls -la "${{ github.workspace }}" || true
133+
134+
# If version provided, honor it and still resolve project path for later steps
135+
REQ_VER="${{ inputs.unityVersion }}"
136+
PROJ_PATH_IN="${{ inputs.projectPath }}"
137+
CANDIDATE_FILE="${{ github.workspace }}/${PROJ_PATH_IN}/ProjectSettings/ProjectVersion.txt"
138+
echo "[detect] Initial candidate file: $CANDIDATE_FILE"
139+
echo "[detect] Listing input project path: '${PROJ_PATH_IN}'"
140+
ls -la "${{ github.workspace }}/${PROJ_PATH_IN}" || true
141+
142+
if [[ ! -f "$CANDIDATE_FILE" ]]; then
143+
echo "[detect] Input projectPath not found: $CANDIDATE_FILE" >&2
144+
echo "[detect] Searching for ProjectVersion.txt under workspace..."
145+
MAPFILE -t FOUND < <(find "${{ github.workspace }}" -type f -path "*/ProjectSettings/ProjectVersion.txt" | sort)
146+
echo "[detect] Found ${#FOUND[@]} candidates"
147+
if [[ ${#FOUND[@]} -eq 0 ]]; then
148+
echo "[detect] No ProjectVersion.txt found in repository" >&2
149+
exit 1
150+
fi
151+
CANDIDATE_FILE="${FOUND[0]}"
152+
echo "[detect] Using detected ProjectVersion.txt: $CANDIDATE_FILE"
153+
echo "[detect] Candidates (up to 10):" && printf '%s\n' "${FOUND[@]:0:10}"
154+
fi
155+
156+
# Derive resolved project path (folder containing ProjectSettings)
157+
RESOLVED_PROJECT_PATH="$(cd "$(dirname "$CANDIDATE_FILE")/.." && pwd)"
158+
# Convert to path relative to workspace for downstream steps
159+
RESOLVED_PROJECT_PATH_REL="${RESOLVED_PROJECT_PATH#"${{ github.workspace }}/"}"
160+
echo "projectPath=$RESOLVED_PROJECT_PATH_REL" >> "$GITHUB_OUTPUT"
161+
echo "[detect] RESOLVED_PROJECT_PATH=$RESOLVED_PROJECT_PATH"
162+
echo "[detect] RESOLVED_PROJECT_PATH_REL=$RESOLVED_PROJECT_PATH_REL"
163+
echo "[detect] ProjectSettings listing:" && ls -la "$RESOLVED_PROJECT_PATH/ProjectSettings" || true
164+
echo "[detect] cat ProjectVersion.txt (pre-smudge):" && cat "$CANDIDATE_FILE" || true
165+
166+
# If file still looks like an LFS pointer, try to smudge just this file and re-check
167+
if head -n 1 "$CANDIDATE_FILE" | grep -q '^version https://git-lfs.github.com/spec/v1'; then
168+
echo "[detect] ProjectVersion.txt appears to be an LFS pointer; attempting smudge"
169+
git lfs checkout -- "$CANDIDATE_FILE" || true
170+
git lfs pull --include="$RESOLVED_PROJECT_PATH_REL/ProjectSettings/ProjectVersion.txt" --exclude="" || true
171+
echo "[detect] cat ProjectVersion.txt (post-smudge):" && cat "$CANDIDATE_FILE" || true
172+
fi
173+
174+
if [[ "$REQ_VER" != "auto" && -n "$REQ_VER" ]]; then
175+
echo "[detect] Using provided unityVersion: $REQ_VER"
176+
echo "version=$REQ_VER" >> "$GITHUB_OUTPUT"
177+
exit 0
178+
fi
179+
180+
VERSION=$(grep -E "^m_EditorVersion:\s*" "$CANDIDATE_FILE" | sed -E 's/^m_EditorVersion:\s*([^[:space:]]+).*/\1/')
181+
if [[ -z "$VERSION" ]]; then
182+
echo "[detect] Failed to parse Unity version from ProjectVersion.txt" >&2
183+
exit 1
184+
fi
185+
echo "[detect] Detected Unity version: $VERSION"
186+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
187+
188+
- name: Log build configuration
189+
shell: bash
190+
run: |
191+
echo "[config] projectPath='${{ steps.detect.outputs.projectPath }}'"
192+
echo "[config] unityVersion='${{ steps.detect.outputs.version }}'"
193+
echo "[config] targetPlatform='${{ inputs.targetPlatform }}'"
194+
echo "[config] buildProfile='${{ inputs.buildProfile }}'"
195+
196+
- name: Validate Unity activation secrets
197+
shell: bash
198+
run: |
199+
set -euo pipefail
200+
missing=0
201+
if [[ -z "${{ secrets.UNITY_LICENSE }}" ]]; then echo "[secrets] UNITY_LICENSE is missing" >&2; missing=1; fi
202+
if [[ -z "${{ secrets.UNITY_EMAIL }}" ]]; then echo "[secrets] UNITY_EMAIL is missing" >&2; missing=1; fi
203+
if [[ -z "${{ secrets.UNITY_PASSWORD }}" ]]; then echo "[secrets] UNITY_PASSWORD is missing" >&2; missing=1; fi
204+
if [[ "$missing" -ne 0 ]]; then
205+
echo "[secrets] One or more required secrets are missing. Per GameCI v4 Personal license activation, provide UNITY_LICENSE, UNITY_EMAIL, UNITY_PASSWORD." >&2
206+
exit 1
207+
fi
208+
209+
- name: Cache Unity Library (project import cache)
210+
uses: actions/cache@v4
211+
with:
212+
path: |
213+
${{ steps.detect.outputs.projectPath }}/Library
214+
key: ${{ runner.os }}-unity-library-${{ steps.detect.outputs.version }}-${{ hashFiles(format('{0}/Packages/manifest.json', steps.detect.outputs.projectPath)) }}
215+
restore-keys: |
216+
${{ runner.os }}-unity-library-${{ steps.detect.outputs.version }}-
217+
218+
- name: Compute build method
219+
id: compute
220+
shell: bash
221+
run: |
222+
set -euo pipefail
223+
if [[ -n "${{ inputs.buildMethod }}" ]]; then
224+
METHOD="${{ inputs.buildMethod }}"
225+
else
226+
case "${{ inputs.buildProfile }}" in
227+
WebGLProductionBuild)
228+
METHOD="Build.WebGL_Prod"
229+
;;
230+
WebGLDevelopmentBuild)
231+
METHOD="Build.WebGL_Dev"
232+
;;
233+
*)
234+
echo "Unknown buildProfile: ${{ inputs.buildProfile }}" >&2
235+
exit 1
236+
;;
237+
esac
238+
fi
239+
echo "buildMethod=$METHOD" >> "$GITHUB_OUTPUT"
240+
echo "[compute] Selected build method: $METHOD"
241+
242+
- name: Prepare logs directory
243+
shell: bash
244+
run: |
245+
mkdir -p Logs
246+
mkdir -p "${{ steps.detect.outputs.projectPath }}/Logs"
247+
248+
# Do not pre-create dist; Unity writes under project path, we stage after
249+
250+
- name: Unity - Builder
251+
uses: game-ci/unity-builder@v4
252+
env:
253+
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
254+
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
255+
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
256+
with:
257+
projectPath: ${{ steps.detect.outputs.projectPath }}
258+
targetPlatform: ${{ inputs.targetPlatform }}
259+
unityVersion: ${{ steps.detect.outputs.version }}
260+
buildMethod: ${{ steps.compute.outputs.buildMethod }}
261+
customParameters: -logFile Logs/Editor.log -stackTraceLogType Full
262+
runAsHostUser: true
263+
264+
265+
- name: Setup Node.js
266+
if: success()
267+
uses: actions/setup-node@v4
268+
with:
269+
node-version: '20'
270+
271+
- name: Install controller dependencies
272+
if: success()
273+
working-directory: WebSites/controller
274+
shell: bash
275+
run: |
276+
set -euo pipefail
277+
echo "[controller] PWD=$(pwd) contents:" && ls -la
278+
if [[ -f package-lock.json ]]; then
279+
echo "[controller] Using npm ci"
280+
npm ci
281+
else
282+
echo "[controller] package-lock.json not found; using npm install"
283+
npm install
284+
fi
285+
286+
- name: Install pnpm for build script
287+
if: success()
288+
working-directory: WebSites/controller
289+
shell: bash
290+
run: |
291+
echo "[controller] Ensuring pnpm is available in $(pwd)"
292+
npm i -g pnpm@8
293+
294+
- name: Build controller
295+
if: success()
296+
working-directory: WebSites/controller
297+
shell: bash
298+
run: |
299+
echo "[controller] Building in $(pwd)"
300+
npm run build
301+
302+
- name: Assemble flat artifact (no wrapper directory)
303+
if: success()
304+
shell: bash
305+
run: |
306+
set -euo pipefail
307+
STAGE="dist"
308+
SRC_BUILDS="${{ steps.detect.outputs.projectPath }}/Builds/SpaceCraft"
309+
echo "[assemble] Expecting Unity output at $SRC_BUILDS"
310+
test -d "$SRC_BUILDS" || { echo "[assemble] ERROR: Unity output missing at $SRC_BUILDS" >&2; exit 1; }
311+
rm -rf "$STAGE"
312+
mkdir -p "$STAGE/SpaceCraft" "$STAGE/controller"
313+
rsync -a "$SRC_BUILDS/" "$STAGE/SpaceCraft/"
314+
# Top-level site index
315+
if [[ -f WebSites/index.html ]]; then
316+
cp -f WebSites/index.html "$STAGE/index.html"
317+
fi
318+
# Controller site
319+
if [[ -f WebSites/controller/index.html ]]; then
320+
cp -f WebSites/controller/index.html "$STAGE/controller/index.html"
321+
fi
322+
if [[ -d WebSites/controller/lib ]]; then
323+
cp -R WebSites/controller/lib "$STAGE/controller/lib"
324+
fi
325+
if [[ -d WebSites/controller/build ]]; then
326+
cp -R WebSites/controller/build "$STAGE/controller/build"
327+
fi
328+
echo "[assemble] Final artifact layout:"
329+
(cd "$STAGE" && find . -maxdepth 2 -type f | sed 's#^./##')
330+
331+
- name: Package site.zip (flat contents)
332+
if: success()
333+
shell: bash
334+
run: |
335+
set -euo pipefail
336+
rm -f site.zip
337+
(cd dist && zip -r ../site.zip .)
338+
echo "[package] Created site.zip"
339+
340+
- name: Upload site.zip artifact
341+
if: success()
342+
uses: actions/upload-artifact@v4
343+
with:
344+
name: site
345+
path: site.zip

SvelteKit/BackSpace/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
"unity:logs": "tsx scripts/unity-automation.js check-logs",
6161
"unity:start": "tsx scripts/unity-automation.js launch",
6262
"unity:openproject": "tsx scripts/unity-automation.js run openproject",
63-
"unity:prebuild": "tsx scripts/unity-automation.js prebuild-webgl"
63+
"unity:prebuild": "tsx scripts/unity-automation.js prebuild-webgl",
64+
"trigger-build-unity-spacecraft": "tsx scripts/gh-trigger-build.ts"
6465
},
6566
"dependencies": {
6667
"async-retry": "^1.3.3",

0 commit comments

Comments
 (0)