From 1ecd93f8360cd36749e9df93b2a27031f8c80ed7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 4 Nov 2026 10:14:13 +0000 Subject: [PATCH 1/3] Check the rendering of a few games against expected screenshots A few games get a rendering test (a gameplay test named "Rendering: ..." taking PNG screenshots): the 3D island (ambient occlusion, depth of field, bloom, tone mapping, terrain, water), the 3D light playground (sun, point and spot lights, shadows), the expanded 3D house horror (models, fog, flashlight, text) and the platformer (2D). scripts/check-rendering-screenshots.js runs only these tests with the latest build of GDevelop and compares the screenshots with the images of rendering-screenshots/ (or writes them with --update). The new rendering-screenshots CI job runs it on main, every night and on the branches changing these games, their images or the scripts: an image that differs while the game did not change is an early warning that the rendering of GDevelop changed. The code running the tests of a game moves to scripts/lib/GameplayTestsRunner.js, to be shared by both scripts, and can now run only some of the tests. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GFZna1tBkWVDbpAbTNnXpr --- .circleci/config.yml | 120 ++++++-- .gitignore | 4 + README.md | 24 ++ .../3d-island-terrain/3d-island-terrain.json | 19 ++ .../3d-light-playground.json | 15 + .../starting-expanded-3d-house-horror.json | 13 + .../starting-platformer.json | 16 + package-lock.json | 35 +++ package.json | 2 + .../the-island-from-above.png | Bin 0 -> 575397 bytes .../the-view-of-the-player.png | Bin 0 -> 518936 bytes .../3d-light-playground/mixed-lights.png | Bin 0 -> 120950 bytes .../3d-light-playground/point-lights.png | Bin 0 -> 179357 bytes .../3d-light-playground/spot-lights.png | Bin 0 -> 70839 bytes .../3d-light-playground/sun-and-shadows.png | Bin 0 -> 76732 bytes .../the-view-of-the-player.png | Bin 0 -> 217401 bytes .../starting-platformer/the-level.png | Bin 0 -> 17912 bytes scripts/check-rendering-screenshots.js | 282 ++++++++++++++++++ scripts/lib/ChangedProjectFiles.js | 1 + scripts/lib/GameplayTestsRunner.js | 223 ++++++++++++++ scripts/lib/RenderingScreenshots.js | 125 ++++++++ .../__tests__/RenderingScreenshots.spec.js | 105 +++++++ scripts/run-gameplay-tests.js | 173 +---------- 23 files changed, 972 insertions(+), 185 deletions(-) create mode 100644 rendering-screenshots/3d-island-terrain/the-island-from-above.png create mode 100644 rendering-screenshots/3d-island-terrain/the-view-of-the-player.png create mode 100644 rendering-screenshots/3d-light-playground/mixed-lights.png create mode 100644 rendering-screenshots/3d-light-playground/point-lights.png create mode 100644 rendering-screenshots/3d-light-playground/spot-lights.png create mode 100644 rendering-screenshots/3d-light-playground/sun-and-shadows.png create mode 100644 rendering-screenshots/starting-expanded-3d-house-horror/the-view-of-the-player.png create mode 100644 rendering-screenshots/starting-platformer/the-level.png create mode 100644 scripts/check-rendering-screenshots.js create mode 100644 scripts/lib/GameplayTestsRunner.js create mode 100644 scripts/lib/RenderingScreenshots.js create mode 100644 scripts/lib/__tests__/RenderingScreenshots.spec.js diff --git a/.circleci/config.yml b/.circleci/config.yml index c66f88d0e..e82eedb63 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,26 @@ parameters: type: string default: master +commands: + install-gdevelop-runtime-dependencies: + steps: + - run: + name: Install the runtime dependencies of GDevelop + # Even in CLI mode, Electron needs these libraries and a display to + # start up on a headless machine. + command: | + sudo apt-get update + sudo apt-get install -y \ + libnss3 \ + libasound2t64 \ + libgbm1 \ + libgtk-3-0 \ + libxss1 \ + libatk-bridge2.0-0 \ + libdrm2 \ + libxkbcommon0 \ + xvfb + jobs: install: docker: @@ -165,22 +185,7 @@ jobs: steps: - checkout - - run: - name: Install the runtime dependencies of GDevelop - # Even in CLI mode, Electron needs these libraries and a display to - # start up on a headless machine. - command: | - sudo apt-get update - sudo apt-get install -y \ - libnss3 \ - libasound2t64 \ - libgbm1 \ - libgtk-3-0 \ - libxss1 \ - libatk-bridge2.0-0 \ - libdrm2 \ - libxkbcommon0 \ - xvfb + - install-gdevelop-runtime-dependencies - run: name: Install the dependencies of the scripts @@ -244,6 +249,64 @@ jobs: name: Report whether the gameplay tests passed command: exit "$(cat /tmp/gameplay-tests-exit-code)" + # Check that the games are still drawn the same: their rendering tests + # (gameplay tests named "Rendering: ...") take screenshots compared with the + # images of `rendering-screenshots/` (see scripts/check-rendering-screenshots.js). + # The latest build of GDevelop is used: an image that differs while the game + # did not change is an early warning of a change of the rendering of GDevelop. + rendering-screenshots: + parameters: + scope: + description: > + "all" checks every game with rendering tests. "changed" only checks + the games whose project or expected images changed compared to `main`. + type: enum + enum: ['all', 'changed'] + default: 'all' + resource_class: large + docker: + - image: cimg/node:24.13.0 + working_directory: ~/GDevelop-examples + + steps: + - checkout + - install-gdevelop-runtime-dependencies + + - run: + name: Install the dependencies of the scripts + command: npm ci --omit=dev + + - run: + name: Check the rendering of the games + no_output_timeout: 30m + # The failure is reported by the last step of the job, so that the + # screenshots and their differences are uploaded first. + command: | + set +e + SCOPE_ARGS="" + if [ "<< parameters.scope >>" = "changed" ]; then + SCOPE_ARGS="--only-changed --base-ref=origin/main" + fi + node scripts/check-rendering-screenshots.js $SCOPE_ARGS \ + --gdevelop-branch=<< pipeline.parameters.gdevelop-branch >> \ + --work-dir=/tmp/gdevelop-portable \ + --artifacts-dir=/tmp/rendering-screenshots-artifacts \ + --junit-path=/tmp/rendering-screenshots-results/results.xml + echo $? > /tmp/rendering-screenshots-exit-code + + - store_test_results: + path: /tmp/rendering-screenshots-results + # One folder per game, with its screenshots (in + # `gameplay-test-screenshots/`) and, for those that differ, an image of + # the differences next to them (`.diff.png`, differences in magenta). + - store_artifacts: + path: /tmp/rendering-screenshots-artifacts + destination: rendering-screenshots + + - run: + name: Report whether the games are drawn like their expected images + command: exit "$(cat /tmp/rendering-screenshots-exit-code)" + workflows: tests: jobs: @@ -271,9 +334,8 @@ workflows: # Every night (03:00 UTC): rebuild and redeploy `main`. The starters re-skinned # with each theme are generated by the build from the themes and assets the - # assets repository publishes, so this is how they catch up with it. Only this - # workflow runs on the schedule: the gameplay tests are not run again, as the - # games did not change. + # assets repository publishes, so this is how they catch up with it. The + # gameplay tests are not run again, as the games did not change. nightly-rebuild: triggers: - schedule: @@ -306,6 +368,9 @@ workflows: name: gameplay-tests-all scope: 'all' parallelism: << pipeline.parameters.all-gameplay-tests-parallelism >> + - rendering-screenshots: + name: rendering-screenshots-all + scope: 'all' # On a branch / Pull Request: only check the games it modifies. changed-gameplay-tests: @@ -319,3 +384,20 @@ workflows: name: gameplay-tests-changed scope: 'changed' parallelism: << pipeline.parameters.changed-gameplay-tests-parallelism >> + - rendering-screenshots: + name: rendering-screenshots-changed + scope: 'changed' + + # Every night (04:17 UTC): check the rendering of the games with the latest + # build of GDevelop, which changes every day without any change here. + nightly-rendering-screenshots: + triggers: + - schedule: + cron: '17 4 * * *' + filters: + branches: + only: main + jobs: + - rendering-screenshots: + name: rendering-screenshots-nightly + scope: 'all' diff --git a/.gitignore b/.gitignore index 60fca0582..11259dced 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ gameplay-test-results.json gameplay-test-screenshots/ /gameplay-tests-artifacts /gameplay-tests-results + +# Written by the rendering screenshots check. +/rendering-screenshots-artifacts +/rendering-screenshots-results diff --git a/README.md b/README.md index 0a9f8e357..f7de32fb9 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,30 @@ land on `main`, by triggering a CircleCI pipeline with the `run-all-gameplay-tests` parameter set to `true`. The number of parallel containers used is the `all-gameplay-tests-parallelism` pipeline parameter. +### Rendering screenshots + +A few games have a _rendering test_: a gameplay test named `Rendering: ...` +taking PNG screenshots (`harness.takeScreenshot(label, { width: 640, format: 'png' })`). +The `rendering-screenshots` CI job runs them with the latest build of GDevelop +and compares each screenshot with the expected image, +`rendering-screenshots//