Skip to content

Commit c33fca7

Browse files
authored
Merge pull request #6940 from decentraland/release/2026-02-02
release: 2026-02-02
2 parents c66b846 + 1915669 commit c33fca7

276 files changed

Lines changed: 37260 additions & 7536 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.

.github/workflows/build-unitycloud.yml

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,23 +140,26 @@ jobs:
140140
name: Prebuild
141141
runs-on: ubuntu-latest
142142
timeout-minutes: 10
143+
# Skip when PR has 'perf_test' label (only performance tests should run)
143144
if: |
144-
(github.ref == 'refs/heads/dev') ||
145-
(github.ref == 'refs/heads/main') ||
146-
(github.event_name == 'workflow_dispatch') ||
147-
(
148-
github.event_name == 'pull_request' &&
145+
!contains(github.event.pull_request.labels.*.name, 'perf_test') && (
146+
(github.ref == 'refs/heads/dev') ||
147+
(github.ref == 'refs/heads/main') ||
148+
(github.event_name == 'workflow_dispatch') ||
149149
(
150+
github.event_name == 'pull_request' &&
150151
(
151-
(github.event.action == 'opened' ||
152-
github.event.action == 'reopened' ||
153-
github.event.action == 'synchronize') &&
154-
!github.event.pull_request.draft
155-
) ||
156-
github.event.action == 'ready_for_review' ||
157-
(
158-
github.event.action == 'labeled' &&
159-
(github.event.label.name == 'force-build' || github.event.label.name == 'clean-build')
152+
(
153+
(github.event.action == 'opened' ||
154+
github.event.action == 'reopened' ||
155+
github.event.action == 'synchronize') &&
156+
!github.event.pull_request.draft
157+
) ||
158+
github.event.action == 'ready_for_review' ||
159+
(
160+
github.event.action == 'labeled' &&
161+
(github.event.label.name == 'force-build' || github.event.label.name == 'clean-build')
162+
)
160163
)
161164
)
162165
)
@@ -351,7 +354,7 @@ jobs:
351354
PARAM_BUILD_VERSION: ${{ needs.prebuild.outputs.version }}
352355
# solves https://github.com/decentraland/unity-explorer/issues/6789
353356
# use pre-defined sentry dsn, but in case it is not defined, use the development sentry project
354-
PARAM_SENTRY_DSN: ${{ inputs.is_release_build == 'true' && secrets.SENTRY_DSN || secrets.SENTRY_DSN_DEV }}
357+
PARAM_SENTRY_DSN: ${{ inputs.is_release_build && secrets.SENTRY_DSN || secrets.SENTRY_DSN_DEV }}
355358
PARAM_SENTRY_ENVIRONMENT: ${{ needs.prebuild.outputs.sentry_environment }}
356359
PARAM_SENTRY_ENABLED: ${{ needs.prebuild.outputs.sentry_enabled }}
357360
PARAM_SEGMENT_WRITE_KEY: ${{ secrets.SEGMENT_WRITE_KEY }}
@@ -570,7 +573,7 @@ jobs:
570573
env:
571574
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_CLI_AUTH_TOKEN }}
572575
SENTRY_ORG: ${{ vars.SENTRY_ORG }}
573-
SENTRY_PROJECT: ${{ inputs.is_release_build == 'true' && vars.SENTRY_PROJECT || vars.SENTRY_PROJECT_DEV }}
576+
SENTRY_PROJECT: ${{ inputs.is_release_build && vars.SENTRY_PROJECT || vars.SENTRY_PROJECT_DEV }}
574577
run: |
575578
npx --yes @sentry/cli debug-files upload \
576579
--org "$SENTRY_ORG" \
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Performance Test Merge Block
2+
3+
# This workflow creates a failing status check when 'perf_test' label is present,
4+
# preventing the PR from being merged. Remove the label to allow merging.
5+
6+
on:
7+
pull_request:
8+
types:
9+
- opened
10+
- reopened
11+
- synchronize
12+
- labeled
13+
- unlabeled
14+
15+
jobs:
16+
check-perf-test-label:
17+
name: Merge Eligibility
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Check for perf_test label
21+
run: |
22+
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }}" == "true" ]]; then
23+
echo "::error::PR has 'perf_test' label - merging is blocked while running performance tests."
24+
echo ""
25+
echo "The 'perf_test' label is used to run only performance tests and skip regular CI."
26+
echo "Remove the 'perf_test' label to restore normal CI and allow merging."
27+
exit 1
28+
else
29+
echo "No 'perf_test' label found - PR is eligible for merge."
30+
fi
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
name: Unity Performance Test
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
types:
7+
- opened
8+
- reopened
9+
- synchronize
10+
- labeled
11+
12+
permissions:
13+
contents: read
14+
packages: write
15+
actions: read
16+
17+
env:
18+
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
19+
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
20+
UNITY_LICENSE: ${{ secrets.UNITY_PERSONAL_LICENSE }}
21+
UNITY_IMAGE_FLAVOR: linux-il2cpp
22+
UNITY_IMAGE_VERSION: 3.2.0
23+
GHCR_IMAGE_NAME: unityci-editor
24+
25+
concurrency:
26+
group: ${{ github.workflow }}-${{ github.ref }}
27+
cancel-in-progress: true
28+
29+
jobs:
30+
performance-test:
31+
name: Performance Test (PlayMode)
32+
runs-on: ubuntu-latest
33+
# Run on manual dispatch OR when PR has 'perf_test' label (already present or just added)
34+
if: |
35+
github.event_name == 'workflow_dispatch' ||
36+
contains(github.event.pull_request.labels.*.name, 'perf_test')
37+
steps:
38+
39+
- name: Move Docker data-root to /mnt/docker
40+
run: |
41+
sudo systemctl stop docker
42+
sudo mkdir -p /mnt/docker
43+
echo '{"data-root":"/mnt/docker"}' | sudo tee /etc/docker/daemon.json
44+
sudo systemctl start docker
45+
docker info | sed -n '1,40p'
46+
df -h /mnt /mnt/docker
47+
48+
- name: Checkout code
49+
uses: actions/checkout@v4
50+
with:
51+
fetch-depth: 0
52+
lfs: true
53+
submodules: recursive
54+
55+
- name: Create LFS file list
56+
run: git lfs ls-files -l | awk '{print $1}' | sort > .lfs-assets-id
57+
58+
- name: Restore LFS cache
59+
uses: actions/cache@v4
60+
id: lfs-cache
61+
with:
62+
path: .git/lfs
63+
key: ${{ runner.os }}-lfs-${{ hashFiles('.lfs-assets-id') }}
64+
65+
- name: Git LFS Pull
66+
run: |
67+
git lfs pull
68+
git add .
69+
git reset --hard
70+
71+
- uses: webfactory/ssh-agent@v0.8.0
72+
with:
73+
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
74+
75+
- name: 'Add GitHub to the SSH known hosts file'
76+
run: |
77+
mkdir -p -m 0700 /home/runner/.ssh
78+
curl --silent https://api.github.com/meta | jq --raw-output '"github.com "+.ssh_keys[]' >> /home/runner/.ssh/known_hosts
79+
chmod 600 /home/runner/.ssh/known_hosts
80+
81+
- name: Restore Library cache
82+
uses: actions/cache@v4
83+
with:
84+
path: Explorer/Library
85+
key: Library-Explorer-Ubuntu
86+
87+
# --- Detect Unity version from the project ---
88+
- name: Read Unity version from ProjectVersion.txt
89+
id: unity-version
90+
run: |
91+
verFile="Explorer/ProjectSettings/ProjectVersion.txt"
92+
if [ ! -f "$verFile" ]; then
93+
echo "File not found: $verFile"
94+
exit 1
95+
fi
96+
ver=$(grep -o 'm_EditorVersion: [0-9a-f.]*' "$verFile" | cut -d' ' -f2)
97+
if [ -z "$ver" ]; then
98+
echo "Could not parse Unity version from $verFile"
99+
exit 1
100+
fi
101+
echo "version=$ver" >> $GITHUB_OUTPUT
102+
echo "Detected Unity version: $ver"
103+
104+
# --- Build image references (GHCR + upstream) ---
105+
- name: Set image names
106+
id: img
107+
run: |
108+
version="${{ steps.unity-version.outputs.version }}"
109+
flavor="${{ env.UNITY_IMAGE_FLAVOR }}"
110+
imgVer="${{ env.UNITY_IMAGE_VERSION }}"
111+
112+
# ubuntu-<unityVersion>-<flavor>-<gameciVersion>
113+
tag="ubuntu-$version-$flavor-$imgVer"
114+
owner=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
115+
upstream="unityci/editor:$tag"
116+
ghcr="ghcr.io/$owner/${{ env.GHCR_IMAGE_NAME }}:$tag"
117+
echo "tag=$tag" >> $GITHUB_OUTPUT
118+
echo "upstream=$upstream" >> $GITHUB_OUTPUT
119+
echo "ghcr=$ghcr" >> $GITHUB_OUTPUT
120+
echo "Upstream image: $upstream"
121+
echo "GHCR image: $ghcr"
122+
123+
# --- Log into GHCR ---
124+
- name: Log in to GitHub Container Registry
125+
uses: docker/login-action@v3
126+
with:
127+
registry: ghcr.io
128+
username: ${{ github.actor }}
129+
password: ${{ github.token }}
130+
131+
# --- Restore Unity image from GHCR (fast path) ---
132+
- name: Restore Unity image from GHCR
133+
id: restore-image
134+
continue-on-error: true
135+
run: |
136+
docker pull "${{ steps.img.outputs.ghcr }}"
137+
138+
# --- Seed GHCR from Docker Hub if missing (one-time per tag) ---
139+
- name: Download from Docker Hub and upload to GHCR (if missing)
140+
if: steps.restore-image.outcome == 'failure'
141+
run: |
142+
upstream="${{ steps.img.outputs.upstream }}"
143+
ghcr="${{ steps.img.outputs.ghcr }}"
144+
echo "GHCR miss. Pulling upstream: $upstream"
145+
docker pull $upstream
146+
docker tag $upstream $ghcr
147+
docker push $ghcr
148+
echo "Seeded GHCR: $ghcr"
149+
150+
# Configure test runner for Performance tests only
151+
- uses: game-ci/unity-test-runner@v4.3.1
152+
id: testRunner
153+
timeout-minutes: 180
154+
continue-on-error: true
155+
env:
156+
SHELL: /bin/bash
157+
with:
158+
projectPath: Explorer
159+
testMode: playmode
160+
sshAgent: ${{ env.SSH_AUTH_SOCK }}
161+
customImage: ${{ steps.img.outputs.ghcr }}
162+
customParameters: -buildTarget StandaloneLinux64 -testCategory "Performance" -perfTestResults ./PerformanceTestResults.json -DCLBenchmarkCIPKey ${{ secrets.DCL_BENCHMARK_CIP_KEY }}
163+
githubToken: ${{ env.GITHUB_TOKEN }}
164+
165+
# Generate PDF report
166+
- name: Set up Python
167+
if: always()
168+
uses: actions/setup-python@v5
169+
with:
170+
python-version: '3.11'
171+
172+
- name: Install report dependencies
173+
if: always()
174+
run: pip install -r scripts/requirements-perf-report.txt
175+
176+
- name: Generate performance report PDF
177+
if: always()
178+
run: |
179+
python scripts/generate_perf_report.py Explorer/PerformanceTestResults.json Explorer/PerformanceBenchmarkReport.pdf --github-summary Explorer/github_summary.md
180+
cat Explorer/github_summary.md >> $GITHUB_STEP_SUMMARY
181+
182+
# Upload performance test results JSON
183+
- name: Upload performance test results (JSON)
184+
uses: actions/upload-artifact@v4
185+
if: always()
186+
with:
187+
name: Performance test results (JSON)
188+
path: Explorer/PerformanceTestResults.json
189+
if-no-files-found: warn
190+
191+
# Upload performance report PDF
192+
- name: Upload performance report (PDF)
193+
uses: actions/upload-artifact@v4
194+
if: always()
195+
with:
196+
name: Performance benchmark report (PDF)
197+
path: Explorer/PerformanceBenchmarkReport.pdf
198+
if-no-files-found: warn

.github/workflows/test.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@ concurrency:
3434

3535
jobs:
3636
test:
37-
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event.pull_request.draft == false) || (github.event.label.name == 'force-build') || (github.event.label.name == 'clean-build')
37+
# Skip when PR has 'perf_test' label (performance tests run in separate workflow)
38+
if: |
39+
!contains(github.event.pull_request.labels.*.name, 'perf_test') && (
40+
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
41+
(github.event.pull_request.draft == false) ||
42+
(github.event.label.name == 'force-build') ||
43+
(github.event.label.name == 'clean-build')
44+
)
3845
name: Test (${{ matrix.testMode }})
3946
runs-on: ubuntu-latest
4047
strategy:

Explorer/Assets/AddressableAssetsData/AddressableAssetSettings.asset

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ MonoBehaviour:
1515
m_DefaultGroup: 47f803e1e9c5079449bd106df98a0b7d
1616
m_currentHash:
1717
serializedVersion: 2
18-
Hash: 37b170adf0ea7bf77c14f9b4fb468f18
18+
Hash: 1d6c17a99ca380a8d4e9b992efd1b862
1919
m_OptimizeCatalogSize: 0
2020
m_BuildRemoteCatalog: 0
2121
m_CatalogRequestsTimeout: 0

Explorer/Assets/AddressableAssetsData/AssetGroups/UI.asset

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ MonoBehaviour:
305305
m_ReadOnly: 0
306306
m_SerializedLabels: []
307307
FlaggedDuringContentUpdateRestriction: 0
308+
- m_GUID: 4f3a6cf0dfd5cc94cbd5225c88c7aa8b
309+
m_Address: PlaceDetailPanel
310+
m_ReadOnly: 0
311+
m_SerializedLabels: []
312+
FlaggedDuringContentUpdateRestriction: 0
308313
- m_GUID: 4f900819503d2412194e6de3e5a95ba0
309314
m_Address: Assets/DCL/Communities/CommunitiesCard/Prefabs/CommunityCard.prefab
310315
m_ReadOnly: 0

Explorer/Assets/DCL/AvatarRendering/AvatarShape/Systems/AvatarLoaderSystem.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,19 @@ internal AvatarLoaderSystem(World world) : base(world) { }
3232

3333
protected override void Update(float t)
3434
{
35-
CreateAvatarShapeFromSDKComponentQuery(World);
3635
UpdateAvatarFromSDKComponentQuery(World);
37-
CreateMainPlayerAvatarShapeFromProfileQuery(World);
38-
CreateAvatarShapeFromProfileQuery(World);
3936
UpdateMainPlayerAvatarFromProfileQuery(World);
4037
UpdateAvatarFromProfileQuery(World);
38+
39+
CreateAvatarShapeFromSDKComponentQuery(World);
40+
CreateMainPlayerAvatarShapeFromProfileQuery(World);
41+
CreateAvatarShapeFromProfileQuery(World);
4142
}
4243

4344
[Query]
4445
[None(typeof(AvatarShapeComponent), typeof(Profile))]
4546
private void CreateAvatarShapeFromSDKComponent(in Entity entity, ref PBAvatarShape pbAvatarShape, ref PartitionComponent partition)
4647
{
47-
pbAvatarShape.IsDirty = false;
48-
4948
WearablePromise wearablePromise = CreateWearablePromise(pbAvatarShape, partition);
5049

5150
World.Add(entity, new AvatarShapeComponent(pbAvatarShape.Name, pbAvatarShape.Id, pbAvatarShape, wearablePromise,
@@ -98,7 +97,6 @@ private void UpdateAvatarFromSDKComponent(ref PBAvatarShape pbAvatarShape, ref A
9897
avatarShapeComponent.EyesColor = pbAvatarShape.GetEyeColor().ToUnityColor();
9998
avatarShapeComponent.IsDirty = true;
10099
avatarShapeComponent.ShowOnlyWearables = pbAvatarShape is { HasShowOnlyWearables: true, ShowOnlyWearables: true };
101-
pbAvatarShape.IsDirty = false;
102100
}
103101

104102
[Query]

Explorer/Assets/DCL/AvatarRendering/Emotes/Systems/Load/LoadEmotesByPointersSystem.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using DCL.AvatarRendering.Wearables.Helpers;
1111
using DCL.Diagnostics;
1212
using DCL.Ipfs;
13+
using DCL.PerformanceAndDiagnostics.Analytics;
1314
using DCL.SDKComponents.AudioSources;
1415
using DCL.Utility;
1516
using DCL.WebRequests;
@@ -47,9 +48,10 @@ public LoadEmotesByPointersSystem(
4748
IStreamableCache<EmotesDTOList, GetEmotesByPointersFromRealmIntention> cache,
4849
IEmoteStorage emoteStorage,
4950
IRealmData realmData,
50-
URLSubdirectory customStreamingSubdirectory
51+
URLSubdirectory customStreamingSubdirectory,
52+
EntitiesAnalytics entitiesAnalytics
5153
)
52-
: base(world, cache, webRequestController)
54+
: base(world, cache, webRequestController, entitiesAnalytics)
5355
{
5456
this.emoteStorage = emoteStorage;
5557
this.realmData = realmData;

0 commit comments

Comments
 (0)