Skip to content

Commit 24bb9de

Browse files
Merge branch 'dev' into fix/9578
2 parents f0f4096 + 1debbcb commit 24bb9de

419 files changed

Lines changed: 31986 additions & 877 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/code-standards/SKILL.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,31 @@ A loop that re-queues unresolved items will spin forever when the upstream sourc
303303

304304
If `X` does nothing useful without `Y`, and there is no second consumer of `X`, merge them. Splits must pay for themselves in polymorphism, reuse, or test isolation.
305305

306+
### 8. Accessing `Option<T>.Value` without checking `Has`
307+
308+
`Option<T>.Value` (`Utility/Types/Result.cs`) is `default` — null for reference types — when `Has` is false. A blind read silently propagates an invalid value far from its source.
309+
310+
```csharp
311+
// WRONG — Value is default/null when Has is false
312+
UserId userId = UserId.New(raw).Value;
313+
314+
// WRONG in production — Unwrap() hides the absence case instead of modeling it
315+
UserId userId = UserId.New(raw).Unwrap();
316+
317+
// RIGHT — branch on Has when the input may be invalid
318+
Option<UserId> userId = UserId.New(raw);
319+
if (!userId.Has) return;
320+
Use(userId.Value);
321+
322+
// RIGHT — a factory that is valid by construction needs no Option at all
323+
UserId userId = UserId.NewRandom();
324+
325+
// RIGHT in tests only — Unwrap() for known-valid constants; it throws loudly at the source
326+
UserId userId = UserId.New(KNOWN_CONSTANT).Unwrap();
327+
```
328+
329+
In production code, handle `None` explicitly (early return, propagation) or use a by-construction-valid factory. `Unwrap()` is a test-only affordance — and in tests, known-valid constants go through `Unwrap()`, never bare `.Value`.
330+
306331
## PR Standards
307332

308333
- **Branches:** Based on `dev` branch

.claude/skills/diagnostics-and-logging/SKILL.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ Drop a `.json` file in the build root folder, launch with `--use-log-matrix "fil
9797

9898
```json
9999
{
100-
"override": true,
100+
"isOverride": true,
101101
"debugLogMatrix": [
102102
{ "category": "VOICE_CHAT", "severity": "Warning" }
103103
],
@@ -107,8 +107,10 @@ Drop a `.json` file in the build root folder, launch with `--use-log-matrix "fil
107107
}
108108
```
109109

110-
- `"override": true` — Only use file values (replaces entire matrix)
111-
- `"override": false` — Merge with existing matrix values
110+
Keys must match `CategorySeverityMatrixDto` field names — `JsonUtility` ignores unknown ones. `{ "allOverride": true }` enables every category at every severity in the log file only, and takes precedence over `isOverride`/`debugLogMatrix`. A log captured under `allOverride` contains resolved media stream URLs with signed `sig`/`expire` query params — do not attach it to a public issue.
111+
112+
- `"isOverride": true` — Only use file values (replaces entire matrix)
113+
- `"isOverride": false` — Merge with existing matrix values
112114

113115
### Use Cases
114116

.gitattributes

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@ Explorer/Assets/StreamingAssets/AssetBundles/**/*.meta -filter=lfs -diff=lfs -me
1414
*.glb filter=lfs diff=lfs merge=lfs -text
1515
*.png filter=lfs diff=lfs merge=lfs -text
1616
*.dll filter=lfs diff=lfs merge=lfs -text
17+
*.dylib filter=lfs diff=lfs merge=lfs -text
18+
Explorer/Assets/Plugins/UUAV/Packages/UUAV/Runtime/Plugins/x86_64/uuav-helper.exe filter=lfs diff=lfs merge=lfs -text
19+
Explorer/Assets/Plugins/UUAV/Packages/UUAV/Runtime/Plugins/macOS/uuav-helper filter=lfs diff=lfs merge=lfs -text
20+
21+
##############################################################################
22+
# UUAV native - hashed bytes, so the line endings are part of the content
23+
#
24+
# scripts/uuav/uuav-binaries.lock.json digests these files as raw bytes, and
25+
# scripts/uuav/build-canonical.sh compiles them with LF forced
26+
# (-c core.autocrlf=false -c core.eol=lf). Without eol=lf a checkout on a host
27+
# with core.autocrlf=true holds CRLF copies, so `verify-binaries.py --update`
28+
# there records digests no other host can reproduce. The shell scripts are here
29+
# too: bash on the Windows runner does not accept CRLF.
30+
##############################################################################
31+
Explorer/Assets/Plugins/UUAV/native/**/*.rs text eol=lf
32+
Explorer/Assets/Plugins/UUAV/native/**/*.toml text eol=lf
33+
Explorer/Assets/Plugins/UUAV/native/**/*.lock text eol=lf
34+
Explorer/Assets/Plugins/UUAV/native/**/*.sb text eol=lf
35+
Explorer/Assets/Plugins/UUAV/**/*.sh text eol=lf
36+
scripts/uuav/*.sh text eol=lf
37+
# --update rewrites the lock, so its own newlines must not depend on the host
38+
scripts/uuav/uuav-binaries.lock.json text eol=lf
1739

1840

1941
##############################################################################

.github/workflows/build-unitycloud.yml

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ on:
9292
- both
9393
- windows-only
9494
- macos-only
95+
install_source:
96+
description: 'Install source baked into the build'
97+
required: true
98+
default: 'launcher'
99+
type: choice
100+
options:
101+
- launcher
102+
- epic
95103
workflow_call:
96104
inputs:
97105
profile:
@@ -626,6 +634,17 @@ jobs:
626634
echo "MAIN_EXE=$MAIN_EXE_ABS" >> "$GITHUB_ENV"
627635
echo "Located: $MAIN_EXE_ABS"
628636
637+
# the UUAV media helper (deployed by HelperBuildPostprocessor)
638+
# is a user-facing executable and must be signed like the game exe
639+
HELPER_EXE=$(find build -path '*/Plugins/x86_64/uuav-helper.exe' | head -n1)
640+
if [[ -z "$HELPER_EXE" ]]; then
641+
echo "::error::uuav-helper.exe not found in build/ (HelperBuildPostprocessor regression?)"
642+
exit 1
643+
fi
644+
HELPER_EXE_ABS=$(readlink -f "$HELPER_EXE")
645+
echo "HELPER_EXE=$HELPER_EXE_ABS" >> "$GITHUB_ENV"
646+
echo "Located: $HELPER_EXE_ABS"
647+
629648
- name: Sign Windows executable
630649
if: matrix.target == 'windows64' && (inputs.is_release_build == true || github.event.inputs.force_sign == 'true')
631650
continue-on-error: true
@@ -641,16 +660,33 @@ jobs:
641660
malware_block: 'false'
642661
environment_name: PROD
643662

663+
- name: Sign UUAV helper executable
664+
if: matrix.target == 'windows64' && (inputs.is_release_build == true || github.event.inputs.force_sign == 'true')
665+
continue-on-error: true
666+
uses: sslcom/esigner-codesign@b7f8ff36fc0de8690fbbab8e5b4421d29802f747 # develop @ 2025-06-23, pinned for supply-chain safety
667+
with:
668+
command: sign
669+
username: ${{ secrets.ES_USERNAME }}
670+
password: ${{ secrets.ES_PASSWORD }}
671+
credential_id: ${{ secrets.WINDOWS_CREDENTIAL_ID_SIGNER }}
672+
totp_secret: ${{ secrets.ES_TOTP_SECRET }}
673+
file_path: ${{ env.HELPER_EXE }}
674+
override: 'true'
675+
malware_block: 'false'
676+
environment_name: PROD
677+
644678
- name: Verify Windows signature
645679
if: matrix.target == 'windows64' && (inputs.is_release_build == true || github.event.inputs.force_sign == 'true')
646680
continue-on-error: true
647681
run: |
648682
set -euo pipefail
649683
sudo apt-get install -y -qq osslsigncode > /dev/null 2>&1
650684
651-
echo "Verifying signature on $MAIN_EXE ..."
652-
osslsigncode verify -in "$MAIN_EXE"
653-
echo "::notice::Signature verified for $MAIN_EXE"
685+
for exe in "$MAIN_EXE" "$HELPER_EXE"; do
686+
echo "Verifying signature on $exe ..."
687+
osslsigncode verify -in "$exe"
688+
echo "::notice::Signature verified for $exe"
689+
done
654690
655691
- name: 'Tar artifact to maintain original permissions'
656692
if: matrix.target == 'macos'

0 commit comments

Comments
 (0)