From cdedacadfcbbddf78529c8db1bc013d1411b3379 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Fri, 4 Apr 2025 18:31:15 -0400 Subject: [PATCH 1/7] Convert to Azahar from Citra (RIP) --- .github/workflows/ci.yml | 6 +++--- README.md | 2 +- run-tests/Dockerfile | 18 +++++++++--------- run-tests/action.yml | 2 +- run-tests/docker/download_citra.sh | 12 ------------ run-tests/docker/download_emulator.sh | 12 ++++++++++++ run-tests/docker/entrypoint.sh | 18 +++++++++--------- 7 files changed, 35 insertions(+), 35 deletions(-) delete mode 100755 run-tests/docker/download_citra.sh create mode 100755 run-tests/docker/download_emulator.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92a318d..88fec72 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: # Still run doc tests even if lib/integration tests fail: if: ${{ !cancelled() }} env: - # This ensures the citra logs and video output get persisted to a + # This ensures the emulator logs and video output get persisted to a # directory where the artifact upload can find them. RUSTDOCFLAGS: " --persist-doctests target/armv6k-nintendo-3ds/debug/doctests" uses: ./run-tests @@ -76,12 +76,12 @@ jobs: working-directory: ctru-rs args: --doc --package test-runner -v - - name: Upload citra logs and capture videos + - name: Upload emulator logs and capture videos uses: actions/upload-artifact@v3 # We always want to upload artifacts regardless of previous success/failure if: ${{ !cancelled() }} with: - name: citra-logs-${{ matrix.toolchain }}-${{ matrix.ctru-rs-ref }} + name: emu-logs-${{ matrix.toolchain }}-${{ matrix.ctru-rs-ref }} path: | ctru-rs/target/armv6k-nintendo-3ds/debug/**/*.txt ctru-rs/target/armv6k-nintendo-3ds/debug/**/*.webm diff --git a/README.md b/README.md index 780a2db..44b6fe1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ when working with these actions, in order to get useful test output on failures. ## Components * `setup`: action for setting up the Rust 3DS toolchain in workflows -* `run-tests`: action for running test executables with Citra in workflows +* `run-tests`: action for running test executables with [Azahar](https://github.com/azahar-emu/azahar) in workflows ## Usage diff --git a/run-tests/Dockerfile b/run-tests/Dockerfile index 8b60653..a256397 100644 --- a/run-tests/Dockerfile +++ b/run-tests/Dockerfile @@ -1,15 +1,15 @@ FROM buildpack-deps:latest as builder WORKDIR /tmp -COPY ./docker/download_citra.sh /usr/local/bin/download_citra +COPY ./docker/download_emulator.sh /usr/local/bin/download_emulator RUN apt-get update -y && apt-get install -y jq -ARG TAG=r0c2f076 -RUN download_citra ${TAG} +ARG EMU_TAG=2120.2 +RUN download_emulator ${EMU_TAG} FROM devkitpro/devkitarm:latest as devkitarm -# For some reason, citra isn't always happy when you try to run it for the first time, +# For some reason, the emulator isn't always happy when you try to run it for the first time, # so we build a simple dummy program to force it to create its directory structure RUN cd /opt/devkitpro/examples/3ds/graphics/printing/hello-world && \ echo 'int main(int, char**) {}' > source/main.c && \ @@ -38,16 +38,16 @@ ENV DEVKITPRO=/opt/devkitpro ENV DEVKITARM=${DEVKITPRO}/devkitARM ENV PATH=${DEVKITARM}/bin:${PATH} -COPY --from=builder /tmp/citra.AppImage /usr/local/bin/citra +COPY --from=builder /tmp/azahar.AppImage /usr/local/bin/azahar COPY --from=devkitarm /tmp/hello-world.3dsx /tmp/ -# We run citra once before copying our config file, so it should create its +# We run azahar once before copying our config file, so it should create its # necessary directory structure and run once with defaults -RUN xvfb-run citra --appimage-extract-and-run /tmp/hello-world.3dsx; \ +RUN xvfb-run azahar --appimage-extract-and-run /tmp/hello-world.3dsx; \ rm -f /tmp/hello-world.3dsx # Initial run seems to miss this one directory so just make it manually -RUN mkdir -p /root/.local/share/citra-emu/log +RUN mkdir -p /root/.local/share/azahar-emu/log -COPY ./docker/sdl2-config.ini /root/.config/citra-emu/ +COPY ./docker/sdl2-config.ini /root/.config/azahar-emu/ COPY ./docker/test-runner.gdb /app/ COPY ./docker/entrypoint.sh /app/ diff --git a/run-tests/action.yml b/run-tests/action.yml index d61b6e7..6d0d168 100644 --- a/run-tests/action.yml +++ b/run-tests/action.yml @@ -1,6 +1,6 @@ name: Cargo 3DS Test description: > - Run `cargo 3ds test` executables using Citra. Note that to use this action, + Run `cargo 3ds test` executables using an emulator. Note that to use this action, you must use a container image of `devkitpro/devkitarm` and mount `/var/run/docker.sock:/var/run/docker.sock` into the container so that the runner image can be built by the action. diff --git a/run-tests/docker/download_citra.sh b/run-tests/docker/download_citra.sh deleted file mode 100755 index f16ec11..0000000 --- a/run-tests/docker/download_citra.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -euxo pipefail - -TAG=$1 - -curl "https://api.github.com/repos/PabloMK7/citra/releases/tags/${TAG}" | - jq --raw-output '.assets[].browser_download_url' | - grep -E 'citra-linux-.*[.]tar.gz' | - xargs wget -O citra-linux.tar.gz - -tar --strip-components 1 -xvf citra-linux.tar.gz diff --git a/run-tests/docker/download_emulator.sh b/run-tests/docker/download_emulator.sh new file mode 100755 index 0000000..05540ae --- /dev/null +++ b/run-tests/docker/download_emulator.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -euxo pipefail + +TAG=$1 + +curl "https://api.github.com/repos/azahar-emu/azahar/releases/tags/${TAG}" | + jq --raw-output '.assets[].browser_download_url' | + grep -E 'azahar-.*-linux-appimage[.]tar.gz' | + xargs wget -O azahar-linux-appimage.tar.gz + +tar --strip-components 1 -xvf azahar-linux-appimage.tar.gz diff --git a/run-tests/docker/entrypoint.sh b/run-tests/docker/entrypoint.sh index 72e1860..c0c32c0 100755 --- a/run-tests/docker/entrypoint.sh +++ b/run-tests/docker/entrypoint.sh @@ -34,29 +34,29 @@ fi VIDEO_OUT="${EXE_NOEXT}_capture.webm" -CITRA_LOG_DIR=~/.local/share/citra-emu/log -CITRA_OUT="$CITRA_LOG_DIR/citra_output.txt" +EMULATOR_LOG_DIR=~/.local/share/azahar-emu/log +EMULATOR_OUT="$EMULATOR_LOG_DIR/emulator_output.txt" xvfb-run --auto-servernum \ - citra \ + azahar \ --appimage-extract-and-run \ --dump-video="$VIDEO_OUT" \ "$EXE_TO_RUN" \ - &>"$CITRA_OUT" & -CITRA_PID=$! + &>"$EMULATOR_OUT" & +EMULATOR_PID=$! -# Citra takes a little while to start up, so wait a little before we try to connect +# Azahar takes a little while to start up, so wait a little before we try to connect sleep 5 arm-none-eabi-gdb --silent --batch-silent --command /app/test-runner.gdb "$EXE_ELF" STATUS=$? -kill $CITRA_PID +kill $EMULATOR_PID cleanup_jobs -CITRA_LOG="$CITRA_LOG_DIR/citra_log.txt" +EMULATOR_LOG="$EMULATOR_LOG_DIR/azahar_log.txt" -for f in "$CITRA_LOG" "$CITRA_OUT"; do +for f in "$EMULATOR_LOG" "$EMULATOR_OUT"; do OUT="${EXE_NOEXT}_$(basename "$f")" if test -f "$f"; then cp "$f" "$OUT" From 7b5f672d4a9df3d83a97a2fc24cc015be1713ef0 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Fri, 4 Apr 2025 18:36:00 -0400 Subject: [PATCH 2/7] Upgrade to v4 of upload-artifact https://github.com/orgs/community/discussions/142581 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88fec72..fe178a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,7 @@ jobs: args: --doc --package test-runner -v - name: Upload emulator logs and capture videos - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 # We always want to upload artifacts regardless of previous success/failure if: ${{ !cancelled() }} with: From cdbd47087002163f2289e0d493d46817f0f8f580 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Fri, 4 Apr 2025 18:45:24 -0400 Subject: [PATCH 3/7] Build from debian, remove deps we no longer need xvfb is the important package for the entrypoint to work, everything else was for the pre-appimage version of Citra --- run-tests/Dockerfile | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/run-tests/Dockerfile b/run-tests/Dockerfile index a256397..c1e410d 100644 --- a/run-tests/Dockerfile +++ b/run-tests/Dockerfile @@ -1,4 +1,4 @@ -FROM buildpack-deps:latest as builder +FROM buildpack-deps:latest AS builder WORKDIR /tmp COPY ./docker/download_emulator.sh /usr/local/bin/download_emulator @@ -7,7 +7,7 @@ RUN apt-get update -y && apt-get install -y jq ARG EMU_TAG=2120.2 RUN download_emulator ${EMU_TAG} -FROM devkitpro/devkitarm:latest as devkitarm +FROM devkitpro/devkitarm:latest AS devkitarm # For some reason, the emulator isn't always happy when you try to run it for the first time, # so we build a simple dummy program to force it to create its directory structure @@ -16,18 +16,12 @@ RUN cd /opt/devkitpro/examples/3ds/graphics/printing/hello-world && \ make && \ mv hello-world.3dsx /tmp/ -FROM ubuntu:mantic +FROM debian:latest RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ apt-get update -y && \ apt-get install -y \ - libavfilter9 \ - libavformat60 \ - libavutil58 \ - libsdl2-2.0-0 \ - libswscale7 \ - mesa-vulkan-drivers \ - vulkan-tools \ + libncursesw6 \ xvfb COPY --from=devkitarm /opt/devkitpro /opt/devkitpro From feacae8a344ab3ea3eb86e54f6318fc4124d5b27 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Fri, 4 Apr 2025 18:47:52 -0400 Subject: [PATCH 4/7] Skip caching during setup for now Move setup *after* checkout of cargo project --- .github/workflows/ci.yml | 8 ++++---- setup/action.yml | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe178a7..3809d67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,10 +33,6 @@ jobs: - name: Checkout branch uses: actions/checkout@v4 - - uses: ./setup - with: - toolchain: ${{ matrix.toolchain }} - - name: Resolve inputs.ref to full SHA # https://github.com/actions/checkout/issues/265#issuecomment-1936792528 id: resolve-ref @@ -58,6 +54,10 @@ jobs: path: 'ctru-rs' ref: ${{ steps.resolve-ref.outputs.sha }} + - uses: ./setup + with: + toolchain: ${{ matrix.toolchain }} + - name: Build and run tests (unit + integration) uses: ./run-tests with: diff --git a/setup/action.yml b/setup/action.yml index 60167b7..8b509d5 100644 --- a/setup/action.yml +++ b/setup/action.yml @@ -20,10 +20,12 @@ runs: cache: false # We set up our own cache manually in the next step rustflags: "" - - name: Set up Rust cache - uses: Swatinem/rust-cache@v2 - with: - cache-on-failure: true + # TODO: accept a workspace directory arg to pass to this action + # + # - name: Set up Rust cache + # uses: Swatinem/rust-cache@v2 + # with: + # cache-on-failure: true - name: Install build tools for host shell: bash From 6bb3e95851f1768828b19e28ab2566f687a473fe Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Fri, 4 Apr 2025 18:54:47 -0400 Subject: [PATCH 5/7] Upgrade toolchain to 2024-09-01 We might actually want a more recent toolchain to support https://github.com/rust3ds/ctru-rs/pull/214 but I'm just testing things for now --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3809d67..73ed972 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,11 +15,11 @@ jobs: matrix: toolchain: # Oldest supported nightly - - nightly-2024-02-18 + - nightly-2024-09-01 - nightly ctru-rs-ref: # "known good" version of `test-runner` crate - - 3247af67d + - 786af2bdb43b2f178afc59f4f9d07c410235556f - master continue-on-error: ${{ matrix.toolchain == 'nightly' || matrix.ctru-rs-ref == 'master' }} From 554f31288e71d734a081b0378936ff293d6d7579 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Fri, 4 Apr 2025 19:12:59 -0400 Subject: [PATCH 6/7] Use long hash instead of short-hash hacks --- .github/workflows/ci.yml | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73ed972..d2c0925 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,26 +33,11 @@ jobs: - name: Checkout branch uses: actions/checkout@v4 - - name: Resolve inputs.ref to full SHA - # https://github.com/actions/checkout/issues/265#issuecomment-1936792528 - id: resolve-ref - run: | - apt-get update -y && apt-get install -y jq - - ref=${{ matrix.ctru-rs-ref }} - sha=$(curl -L "https://api.github.com/repos/rust3ds/ctru-rs/commits/$ref" | jq -r .sha) - if [ -z "$sha" ]; then - echo "Failed to resolve ref $ref (possibly missing GH_TOKEN env var?)" >&2 - exit 1 - fi - - echo "sha=$sha" >> $GITHUB_OUTPUT - - uses: actions/checkout@v4 with: repository: 'rust3ds/ctru-rs' path: 'ctru-rs' - ref: ${{ steps.resolve-ref.outputs.sha }} + ref: ${{ matrix.ctru-rs-ref }} - uses: ./setup with: From 1e2a4a8b7c9fa0b388b7534de6bdf7f6bcaee336 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Sat, 12 Apr 2025 22:47:27 -0400 Subject: [PATCH 7/7] Use nix to run azahar This way we get all the dependencies for "free", although it does slow the container build down a bit due to fetching nixpkgs. Switch to software rendering (seems to work better inside containers). --- run-tests/Dockerfile | 35 +++++++++++++++++++------------- run-tests/docker/entrypoint.sh | 2 +- run-tests/docker/sdl2-config.ini | 9 ++------ 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/run-tests/Dockerfile b/run-tests/Dockerfile index c1e410d..4e71c8c 100644 --- a/run-tests/Dockerfile +++ b/run-tests/Dockerfile @@ -4,9 +4,6 @@ WORKDIR /tmp COPY ./docker/download_emulator.sh /usr/local/bin/download_emulator RUN apt-get update -y && apt-get install -y jq -ARG EMU_TAG=2120.2 -RUN download_emulator ${EMU_TAG} - FROM devkitpro/devkitarm:latest AS devkitarm # For some reason, the emulator isn't always happy when you try to run it for the first time, @@ -16,13 +13,24 @@ RUN cd /opt/devkitpro/examples/3ds/graphics/printing/hello-world && \ make && \ mv hello-world.3dsx /tmp/ -FROM debian:latest +FROM ubuntu:noble AS with-nix + +# https://git.lix.systems/lix-project/lix-installer#in-a-container +RUN apt-get update -y && apt-get install -y curl + +RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install linux \ + --extra-conf "sandbox = false" \ + --extra-conf "experimental-features = flakes nix-command" \ + --init none \ + --no-confirm -RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ - apt-get update -y && \ - apt-get install -y \ - libncursesw6 \ - xvfb +ENV PATH="$PATH:/nix/var/nix/profiles/default/bin" + +# Azahar version2120.2 +ARG NIXPKGS_COMMIT=6a39c6e495eefabc935d8ddf66aa45d85b85fa3f +ARG FLAKE=github:NixOS/nixpkgs/${NIXPKGS_COMMIT} +RUN nix flake prefetch "${FLAKE}" +RUN bash -c 'nix profile install "${FLAKE}"#{azahar,xdg-utils,xvfb-run}' COPY --from=devkitarm /opt/devkitpro /opt/devkitpro # There's no way to copy ENV values from other stages properly: @@ -32,16 +40,15 @@ ENV DEVKITPRO=/opt/devkitpro ENV DEVKITARM=${DEVKITPRO}/devkitARM ENV PATH=${DEVKITARM}/bin:${PATH} -COPY --from=builder /tmp/azahar.AppImage /usr/local/bin/azahar +COPY ./docker/sdl2-config.ini /root/.config/azahar-emu/sdl2-config.ini COPY --from=devkitarm /tmp/hello-world.3dsx /tmp/ -# We run azahar once before copying our config file, so it should create its -# necessary directory structure and run once with defaults -RUN xvfb-run azahar --appimage-extract-and-run /tmp/hello-world.3dsx; \ + +RUN export XDG_RUNTIME_DIR="/run/user/0"; \ + xvfb-run azahar -n /tmp/hello-world.3dsx && \ rm -f /tmp/hello-world.3dsx # Initial run seems to miss this one directory so just make it manually RUN mkdir -p /root/.local/share/azahar-emu/log -COPY ./docker/sdl2-config.ini /root/.config/azahar-emu/ COPY ./docker/test-runner.gdb /app/ COPY ./docker/entrypoint.sh /app/ diff --git a/run-tests/docker/entrypoint.sh b/run-tests/docker/entrypoint.sh index c0c32c0..54aad28 100755 --- a/run-tests/docker/entrypoint.sh +++ b/run-tests/docker/entrypoint.sh @@ -39,7 +39,7 @@ EMULATOR_OUT="$EMULATOR_LOG_DIR/emulator_output.txt" xvfb-run --auto-servernum \ azahar \ - --appimage-extract-and-run \ + --gdbport 4000 \ --dump-video="$VIDEO_OUT" \ "$EXE_TO_RUN" \ &>"$EMULATOR_OUT" & diff --git a/run-tests/docker/sdl2-config.ini b/run-tests/docker/sdl2-config.ini index cd0f08c..3361263 100644 --- a/run-tests/docker/sdl2-config.ini +++ b/run-tests/docker/sdl2-config.ini @@ -1,15 +1,10 @@ -# OpenGL renderer seems to crash so we force using vulkan: -# https://github.com/rust3ds/test-runner/issues/16 [Renderer] -graphics_api = 2 +# Software rendering is slow, but works better than OpenGL or Vulkan inside docker +graphics_api = 0 [Miscellaneous] log_filter = *:Info Debug.Emulated:Debug -[Debugging] -use_gdbstub=true -gdbstub_port=4000 - [WebService] enable_telemetry = 0