Ian Chamberlain
1 year ago
committed by
GitHub
19 changed files with 283 additions and 143 deletions
@ -1,12 +0,0 @@ |
|||||||
name: 'Run 3DS Executable' |
|
||||||
description: 'Run a given 3DS executable with citra and GDB' |
|
||||||
inputs: |
|
||||||
executable: |
|
||||||
description: > |
|
||||||
The 3DS executable(s) to run. Globs and space separated lists allowed. |
|
||||||
required: true |
|
||||||
runs: |
|
||||||
using: docker |
|
||||||
image: ../../../Dockerfile |
|
||||||
args: |
|
||||||
- ${{ inputs.executable }} |
|
@ -1,34 +0,0 @@ |
|||||||
FROM buildpack-deps:latest as builder |
|
||||||
|
|
||||||
ARG CITRA_CHANNEL=nightly |
|
||||||
ARG CITRA_RELEASE=1962 |
|
||||||
|
|
||||||
WORKDIR /tmp |
|
||||||
COPY ./docker/download_citra.sh /usr/local/bin/download_citra |
|
||||||
RUN apt-get update -y && apt-get install -y jq |
|
||||||
RUN download_citra ${CITRA_CHANNEL} ${CITRA_RELEASE} |
|
||||||
|
|
||||||
FROM devkitpro/devkitarm:latest as devkitarm |
|
||||||
|
|
||||||
FROM ubuntu:latest |
|
||||||
|
|
||||||
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ |
|
||||||
apt-get update -y && \ |
|
||||||
apt-get install -y \ |
|
||||||
libswscale5 \ |
|
||||||
libsdl2-2.0-0 \ |
|
||||||
libavformat58 \ |
|
||||||
libavfilter7 \ |
|
||||||
xvfb |
|
||||||
|
|
||||||
COPY --from=devkitarm /opt/devkitpro /opt/devkitpro |
|
||||||
ENV PATH=/opt/devkitpro/devkitARM/bin:${PATH} |
|
||||||
|
|
||||||
COPY --from=builder /tmp/citra.AppImage /usr/local/bin/citra |
|
||||||
COPY ./docker/sdl2-config.ini /app/ |
|
||||||
COPY ./docker/test-runner.gdb /app/ |
|
||||||
COPY ./docker/entrypoint.sh /app/ |
|
||||||
|
|
||||||
WORKDIR /app |
|
||||||
|
|
||||||
ENTRYPOINT [ "/app/entrypoint.sh" ] |
|
@ -1,50 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
|
|
||||||
# Clean up child processes on exit: https://stackoverflow.com/a/2173421/14436105 |
|
||||||
trap "pkill -P $$" EXIT INT TERM |
|
||||||
|
|
||||||
mkdir -p ~/.config/citra-emu |
|
||||||
cp /app/sdl2-config.ini ~/.config/citra-emu |
|
||||||
# For some reason, log file is only written when this dir already exists, |
|
||||||
# but it is only created after the first run of citra (our only run, in the container) |
|
||||||
mkdir -p ~/.local/share/citra-emu/ |
|
||||||
|
|
||||||
ERRS=0 |
|
||||||
# shellcheck disable=SC2068 |
|
||||||
for EXE in $@; do |
|
||||||
VIDEO_OUT="$(dirname "$EXE")/$(basename "$EXE" .elf)_capture.webm" |
|
||||||
|
|
||||||
# colored logs would be nice, but we can always just grab the plaintext log file |
|
||||||
xvfb-run citra \ |
|
||||||
--appimage-extract-and-run \ |
|
||||||
--dump-video="$VIDEO_OUT" \ |
|
||||||
"$EXE" \ |
|
||||||
&>/dev/null & |
|
||||||
PID=$! |
|
||||||
|
|
||||||
# Citra takes a little while to start up, so wait a little before we try to connect |
|
||||||
sleep 3 |
|
||||||
|
|
||||||
arm-none-eabi-gdb --silent --batch-silent --command /app/test-runner.gdb "$EXE" |
|
||||||
STATUS=$? |
|
||||||
if [ $STATUS -ne 0 ]; then |
|
||||||
echo >&2 "FAILED (exit status $STATUS): $EXE" |
|
||||||
ERRS=$(( ERRS + 1 )) |
|
||||||
fi |
|
||||||
|
|
||||||
kill -INT $PID &>/dev/null |
|
||||||
sleep 1 |
|
||||||
if kill -0 $PID &>/dev/null; then |
|
||||||
kill -KILL $PID &>/dev/null |
|
||||||
fi |
|
||||||
|
|
||||||
CITRA_LOG=~/.local/share/citra-emu/log/citra_log.txt |
|
||||||
CITRA_LOG_OUT="$(dirname "$EXE")/$(basename "$EXE" .elf)_citra_log.txt" |
|
||||||
if test -f "$CITRA_LOG"; then |
|
||||||
cp "$CITRA_LOG" "$CITRA_LOG_OUT" |
|
||||||
else |
|
||||||
echo "WARNING: citra log not found" |
|
||||||
fi |
|
||||||
done |
|
||||||
|
|
||||||
exit $ERRS |
|
@ -0,0 +1,54 @@ |
|||||||
|
FROM buildpack-deps:latest as builder |
||||||
|
|
||||||
|
WORKDIR /tmp |
||||||
|
COPY ./docker/download_citra.sh /usr/local/bin/download_citra |
||||||
|
RUN apt-get update -y && apt-get install -y jq |
||||||
|
|
||||||
|
ARG CITRA_CHANNEL=nightly |
||||||
|
ARG CITRA_RELEASE=1995 |
||||||
|
RUN download_citra ${CITRA_CHANNEL} ${CITRA_RELEASE} |
||||||
|
|
||||||
|
FROM devkitpro/devkitarm:latest as devkitarm |
||||||
|
|
||||||
|
# For some reason, citra 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:latest |
||||||
|
|
||||||
|
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt \ |
||||||
|
apt-get update -y && \ |
||||||
|
apt-get install -y \ |
||||||
|
libswscale5 \ |
||||||
|
libsdl2-2.0-0 \ |
||||||
|
libavformat58 \ |
||||||
|
libavfilter7 \ |
||||||
|
xvfb |
||||||
|
|
||||||
|
COPY --from=devkitarm /opt/devkitpro /opt/devkitpro |
||||||
|
# There's no way to copy ENV values from other stages properly: |
||||||
|
# https://github.com/moby/moby/issues/37345 |
||||||
|
# Luckily in this case we know exactly what the values should be: |
||||||
|
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=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; \ |
||||||
|
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 |
||||||
|
|
||||||
|
COPY ./docker/sdl2-config.ini /root/.config/citra-emu/ |
||||||
|
COPY ./docker/test-runner.gdb /app/ |
||||||
|
COPY ./docker/entrypoint.sh /app/ |
||||||
|
|
||||||
|
WORKDIR /app |
||||||
|
|
||||||
|
ENTRYPOINT [ "/app/entrypoint.sh" ] |
@ -0,0 +1,61 @@ |
|||||||
|
name: Cargo 3DS Test |
||||||
|
description: > |
||||||
|
Run `cargo 3ds test` executables using Citra. Note that to use this action, |
||||||
|
you must mount `/var/run/docker.sock:/var/run/docker.sock` and `/tmp:/tmp` into |
||||||
|
the container so that the runner image can be built and doctest artifacts can |
||||||
|
be found, respectively. |
||||||
|
|
||||||
|
inputs: |
||||||
|
args: |
||||||
|
description: Extra arguments to pass to `cargo 3ds test` |
||||||
|
required: false |
||||||
|
default: '' |
||||||
|
|
||||||
|
runner-image: |
||||||
|
description: The name of the container image to build for running tests in |
||||||
|
required: false |
||||||
|
default: test-runner-3ds |
||||||
|
|
||||||
|
working-directory: |
||||||
|
description: Change to this directory before running tests. Defaults to $GITHUB_WORKSPACE |
||||||
|
required: false |
||||||
|
default: ${GITHUB_WORKSPACE} |
||||||
|
|
||||||
|
runs: |
||||||
|
using: composite |
||||||
|
steps: |
||||||
|
- name: Set up Docker Buildx |
||||||
|
uses: docker/setup-buildx-action@v3 |
||||||
|
|
||||||
|
- name: Build test-runner image |
||||||
|
uses: docker/build-push-action@v4 |
||||||
|
with: |
||||||
|
context: ${{ github.action_path }} |
||||||
|
tags: ${{ inputs.runner-image }}:latest |
||||||
|
push: false |
||||||
|
load: true |
||||||
|
|
||||||
|
- name: Ensure docker is installed in the container |
||||||
|
shell: bash |
||||||
|
run: apt-get update -y && apt-get install docker.io -y |
||||||
|
|
||||||
|
- name: Run cargo 3ds test |
||||||
|
shell: bash |
||||||
|
# Set a custom runner for `cargo test` commands to use. |
||||||
|
# Use ${GITHUB_WORKSPACE} due to |
||||||
|
# https://github.com/actions/runner/issues/2058, which also means |
||||||
|
# we have to export this instead of using the env: key |
||||||
|
run: | |
||||||
|
cd ${{ inputs.working-directory }} |
||||||
|
export CARGO_TARGET_ARMV6K_NINTENDO_3DS_RUNNER=" |
||||||
|
docker run --rm |
||||||
|
-v ${{ runner.temp }}:${{ runner.temp }} |
||||||
|
-v ${{ github.workspace }}/target:/app/target |
||||||
|
-v ${{ github.workspace }}:${GITHUB_WORKSPACE} |
||||||
|
${{ inputs.runner-image }}:latest" |
||||||
|
env |
||||||
|
cargo 3ds -v test ${{ inputs.args }} |
||||||
|
env: |
||||||
|
# Ensure that doctests get built into a path which is mounted on the host |
||||||
|
# as well as in this container (via the bind mount in the RUNNER command) |
||||||
|
TMPDIR: ${{ runner.temp }} |
@ -0,0 +1,68 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
# Uncomment for debugging the action itself. Maybe consider a job summary or |
||||||
|
# grouping the output, to keep this stuff visible but make it simpler to use: |
||||||
|
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions |
||||||
|
|
||||||
|
# set -x |
||||||
|
|
||||||
|
function cleanup_jobs() { |
||||||
|
# shellcheck disable=SC2317 # Unreachable because it's only used in trap |
||||||
|
if [ -n "$(jobs -p)" ]; then |
||||||
|
sleep 5 & |
||||||
|
wait -n |
||||||
|
# shellcheck disable=SC2046 # We want to expand jobs here and for `wait` |
||||||
|
kill -9 $(jobs -p) |
||||||
|
# shellcheck disable=SC2046 |
||||||
|
wait $(jobs -p) &>/dev/null |
||||||
|
fi |
||||||
|
} |
||||||
|
|
||||||
|
trap cleanup_jobs EXIT |
||||||
|
|
||||||
|
EXE_ELF=$1 |
||||||
|
EXE_3DSX="$(dirname "$EXE")/$(basename "$EXE" .elf).3dsx" |
||||||
|
|
||||||
|
EXE_TO_RUN="$EXE_ELF" |
||||||
|
if [ -f "$EXE_3DSX" ]; then |
||||||
|
echo >&2 "Found $(basename "$EXE_3DSX"), it will be run instead of $(basename "$EXE_ELF")" |
||||||
|
EXE_TO_RUN="$EXE_3DSX" |
||||||
|
fi |
||||||
|
|
||||||
|
VIDEO_OUT="$(dirname "$EXE_ELF")/$(basename "$EXE_ELF" .elf)_capture.webm" |
||||||
|
|
||||||
|
CITRA_LOG_DIR=~/.local/share/citra-emu/log |
||||||
|
CITRA_OUT="$CITRA_LOG_DIR/citra_output.txt" |
||||||
|
|
||||||
|
xvfb-run --auto-servernum \ |
||||||
|
citra \ |
||||||
|
--appimage-extract-and-run \ |
||||||
|
--dump-video="$VIDEO_OUT" \ |
||||||
|
"$EXE_TO_RUN" \ |
||||||
|
&>"$CITRA_OUT" & |
||||||
|
CITRA_PID=$! |
||||||
|
|
||||||
|
# Citra 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 |
||||||
|
cleanup_jobs |
||||||
|
|
||||||
|
CITRA_LOG="$CITRA_LOG_DIR/citra_log.txt" |
||||||
|
|
||||||
|
for f in "$CITRA_LOG" "$CITRA_OUT"; do |
||||||
|
OUT="$(dirname "$EXE_ELF")/$(basename "$EXE_ELF" .elf)_$(basename "$f")" |
||||||
|
if test -f "$f"; then |
||||||
|
cp "$f" "$OUT" |
||||||
|
if [ $STATUS -ne 0 ]; then |
||||||
|
echo >&2 "$(basename $f) copied to $OUT" |
||||||
|
fi |
||||||
|
else |
||||||
|
echo >&2 "WARNING: $(basename "$f") not found" |
||||||
|
fi |
||||||
|
done |
||||||
|
|
||||||
|
exit $STATUS |
Loading…
Reference in new issue