diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92a318d..d2c0925 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' }} @@ -33,30 +33,15 @@ 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 - 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: + toolchain: ${{ matrix.toolchain }} - name: Build and run tests (unit + integration) uses: ./run-tests @@ -68,7 +53,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 +61,12 @@ jobs: working-directory: ctru-rs args: --doc --package test-runner -v - - name: Upload citra logs and capture videos - uses: actions/upload-artifact@v3 + - name: Upload emulator logs and capture videos + uses: actions/upload-artifact@v4 # 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..4e71c8c 100644 --- a/run-tests/Dockerfile +++ b/run-tests/Dockerfile @@ -1,34 +1,36 @@ -FROM buildpack-deps:latest as builder +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} +FROM devkitpro/devkitarm:latest AS devkitarm -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 && \ make && \ mv hello-world.3dsx /tmp/ -FROM ubuntu:mantic +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 \ - libavfilter9 \ - libavformat60 \ - libavutil58 \ - libsdl2-2.0-0 \ - libswscale7 \ - mesa-vulkan-drivers \ - vulkan-tools \ - 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: @@ -38,16 +40,15 @@ ENV DEVKITPRO=/opt/devkitpro ENV DEVKITARM=${DEVKITPRO}/devkitARM ENV PATH=${DEVKITARM}/bin:${PATH} -COPY --from=builder /tmp/citra.AppImage /usr/local/bin/citra +COPY ./docker/sdl2-config.ini /root/.config/azahar-emu/sdl2-config.ini COPY --from=devkitarm /tmp/hello-world.3dsx /tmp/ -# We run citra 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 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/citra-emu/log +RUN mkdir -p /root/.local/share/azahar-emu/log -COPY ./docker/sdl2-config.ini /root/.config/citra-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..54aad28 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 \ - --appimage-extract-and-run \ + azahar \ + --gdbport 4000 \ --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" 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 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