diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e7a9ee8c..a08bf0af 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -6,37 +6,40 @@ on: - cron: '0 0 * * 1' jobs: build: - runs-on: ubuntu-latest + permissions: + packages: write + strategy: + matrix: + arch: [ amd64, arm64 ] + include: + - arch: amd64 + tag: amd64-latest + runner: ubuntu-latest + - arch: arm64 + tag: aarch64-latest + runner: [self-hosted, Linux, ARM64] + runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Build tier 1 Docker image - run: make TAG=amd64-latest image-tier1 + run: make TAG=${{ matrix.tag }} image-tier1 - name: Test tier 1 Docker image - run: make TAG=amd64-latest test-tier1 + run: make TAG=${{ matrix.tag }} test-tier1 - name: Build tier 2 Docker image - run: make TAG=amd64-latest image-tier2 + run: make TAG=${{ matrix.tag }} image-tier2 - name: Test tier 2 Docker image - run: make TAG=amd64-latest test-tier2 + run: make TAG=${{ matrix.tag }} test-tier2 - name: Build tier 3 Docker image - run: make TAG=amd64-latest image-tier3 + run: make TAG=${{ matrix.tag }} image-tier3 - name: Test tier 3 Docker image - run: make TAG=amd64-latest test-tier3 + run: make TAG=${{ matrix.tag }} test-tier3 - name: Push images to Docker if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master' run: | echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin - docker push dmoj/runtimes-tier1:amd64-latest - docker push dmoj/runtimes-tier2:amd64-latest - docker push dmoj/runtimes-tier3:amd64-latest - docker run -v "$(pwd)":/code mplatform/manifest-tool \ - --username="$DOCKER_USERNAME" --password="$DOCKER_PASSWORD" \ - push from-spec /code/tier1/manifest.yml - docker run -v "$(pwd)":/code mplatform/manifest-tool \ - --username="$DOCKER_USERNAME" --password="$DOCKER_PASSWORD" \ - push from-spec /code/tier2/manifest.yml - docker run -v "$(pwd)":/code mplatform/manifest-tool \ - --username="$DOCKER_USERNAME" --password="$DOCKER_PASSWORD" \ - push from-spec /code/tier3/manifest.yml + docker push dmoj/runtimes-tier1:${{ matrix.tag }} + docker push dmoj/runtimes-tier2:${{ matrix.tag }} + docker push dmoj/runtimes-tier3:${{ matrix.tag }} env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} @@ -44,9 +47,46 @@ jobs: if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master' run: | echo "$CR_PAT" | docker login ghcr.io -u "$CR_USER" --password-stdin - docker push ghcr.io/dmoj/runtimes-tier1:amd64-latest - docker push ghcr.io/dmoj/runtimes-tier2:amd64-latest - docker push ghcr.io/dmoj/runtimes-tier3:amd64-latest + docker push ghcr.io/dmoj/runtimes-tier1:${{ matrix.tag }} + docker push ghcr.io/dmoj/runtimes-tier2:${{ matrix.tag }} + docker push ghcr.io/dmoj/runtimes-tier3:${{ matrix.tag }} + env: + CR_USER: ${{ github.actor }} + CR_PAT: ${{ secrets.GITHUB_TOKEN }} + + manifest: + permissions: + packages: write + if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master' + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Update Docker Hub Manifests + run: | + echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin + for tier in tier{1..3}; do + args=() + for arch in amd64 aarch64; do + args+=(--amend "dmoj/runtimes-$tier:$arch-latest") + done + docker manifest create "dmoj/runtimes-$tier:latest" "${args[@]}" + docker manifest push "dmoj/runtimes-$tier:latest" + done + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + - name: Push images to GitHub Containers + run: | + echo "$CR_PAT" | docker login ghcr.io -u "$CR_USER" --password-stdin + for tier in tier{1..3}; do + args=() + for arch in amd64 aarch64; do + args+=(--amend "ghcr.io/dmoj/runtimes-$tier:$arch-latest") + done + docker manifest create "ghcr.io/dmoj/runtimes-$tier:latest" "${args[@]}" + docker manifest push "ghcr.io/dmoj/runtimes-$tier:latest" + done env: - CR_USER: ${{ secrets.CR_USER }} - CR_PAT: ${{ secrets.CR_PAT }} + CR_USER: ${{ github.actor }} + CR_PAT: ${{ secrets.GITHUB_TOKEN }} diff --git a/test/run b/test/run index 036f5e3e..47278081 100755 --- a/test/run +++ b/test/run @@ -3,5 +3,6 @@ mkdir /judge cd /judge || exit curl -L https://github.com/DMOJ/judge/archive/master.tar.gz | tar -xz --strip-components=1 pip3 install -e . +python3 setup.py develop . ~judge/.profile runuser -u judge -w PATH -- bash -c '. ~/.profile; dmoj-autoconf -V' diff --git a/tier1/Dockerfile b/tier1/Dockerfile index a6aa18a5..a6670a84 100644 --- a/tier1/Dockerfile +++ b/tier1/Dockerfile @@ -7,7 +7,7 @@ RUN echo deb http://deb.debian.org/debian/ stretch main > /etc/apt/sources.list. apt-get update && \ apt-get install -y --no-install-recommends \ curl file gcc g++ python3-pip python3-dev python3-setuptools python3-wheel cython3 libseccomp-dev bzip2 gzip \ - python2 fp-compiler libxtst6 tini && \ + python2 fp-compiler libxtst6 libffi8 tini $([ "$(arch)" = aarch64 ] && echo binutils-arm-linux-gnueabihf) && \ apt-get install -y -t stretch --no-install-recommends openjdk-8-jdk-headless openjdk-8-jre-headless && \ apt-get install -y -t experimental --no-install-recommends g++-11 && \ rm -rf /var/lib/apt/lists/* && \ diff --git a/tier2/Dockerfile b/tier2/Dockerfile index 0e598f3b..a5f2ea6b 100644 --- a/tier2/Dockerfile +++ b/tier2/Dockerfile @@ -3,18 +3,19 @@ FROM dmoj/runtimes-tier1 RUN apt-get update && \ apt-get install -y --no-install-recommends \ jq apt-transport-https dirmngr gnupg ca-certificates \ - openjdk-17-jdk-headless clang ghc golang racket ruby scala nasm libc6-dev-i386 && \ + openjdk-17-jdk-headless clang ghc golang racket ruby scala nasm $([ "$(arch)" = x86_64 ] && echo libc6-dev-i386) && \ ( \ apt-get install -y --no-install-recommends make m4 patch unzip libgmp-dev && \ bash -c 'echo | sh <(curl -sL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh) --no-backup' && \ - runuser -u judge -- opam init --shell-setup --disable-sandboxing && \ - runuser -u judge -- opam install -y base core stdio zarith && \ + runuser -u judge -- opam init --shell-setup --disable-sandboxing -j$(nproc) && \ + runuser -u judge -- opam install -y -j$(nproc) base core stdio zarith && \ runuser -u judge -- opam clean && rm -rf ~judge/.opam/repo \ ) && \ - mkdir /opt/pypy2 && curl -L "$(curl https://www.pypy.org/download.html | grep /pypy2 | head -n1 | cut -d'"' -f4)" | \ + if [ "$(arch)" = x86_64 ]; then PYPY_ARCH=linux64; else PYPY_ARCH="$(arch)"; fi && \ + mkdir /opt/pypy2 && curl -L "$(curl https://www.pypy.org/download.html | grep "/pypy2.*$PYPY_ARCH" | head -n1 | cut -d'"' -f4)" | \ tar xj -C /opt/pypy2 --strip-components=1 && /opt/pypy2/bin/pypy -mcompileall && \ rm -f /opt/pypy2/bin/python* && \ - mkdir /opt/pypy3 && curl -L "$(curl https://www.pypy.org/download.html | grep /pypy3 | head -n1 | cut -d'"' -f4)" | \ + mkdir /opt/pypy3 && curl -L "$(curl https://www.pypy.org/download.html | grep "/pypy3.*$PYPY_ARCH" | head -n1 | cut -d'"' -f4)" | \ tar xj -C /opt/pypy3 --strip-components=1 && /opt/pypy3/bin/pypy -mcompileall && \ rm -f /opt/pypy3/bin/python* && \ runuser judge -c 'curl https://sh.rustup.rs -sSf | sh -s -- -y' && \ @@ -31,13 +32,13 @@ RUN apt-get update && \ runuser -u judge /home/judge/.cargo/bin/cargo fetch \ ) && \ rm -rf rust && \ - curl -L -odmd.deb "$(curl -s https://dlang.org/download.html | perl -ne 'if(/"([^"~]*_amd64.deb)/){print $1;exit}')" && \ - apt install ./dmd.deb && rm dmd.deb && \ + if [ "$(arch)" = x86_64 ]; then curl -L -odmd.deb "$(curl -s https://dlang.org/download.html | perl -ne 'if(/"([^"~]*_amd64.deb)/){print $1;exit}')" && \ + apt install ./dmd.deb && rm dmd.deb; fi && \ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \ echo "deb https://download.mono-project.com/repo/debian stable-buster main" > \ /etc/apt/sources.list.d/mono-official-stable.list && \ curl https://dmoj.ca/dmoj-apt.key | apt-key add - && \ - echo 'deb [arch=amd64] https://apt.dmoj.ca/ stretch main non-free' > /etc/apt/sources.list.d/dmoj.list && \ + echo 'deb https://apt.dmoj.ca/ bullseye main' > /etc/apt/sources.list.d/dmoj.list && \ (echo 'Package: *'; echo 'Pin: origin download.mono-project.com'; echo 'Pin-Priority: 990') > /etc/apt/preferences.d/mono && \ apt-get update && \ (cd /tmp && \ diff --git a/tier3/Dockerfile b/tier3/Dockerfile index 125ac678..df3e05d6 100644 --- a/tier3/Dockerfile +++ b/tier3/Dockerfile @@ -1,14 +1,22 @@ FROM dmoj/runtimes-tier2 -RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ - echo 'deb [arch=amd64] https://storage.googleapis.com/download.dartlang.org/linux/debian stable main' > /etc/apt/sources.list.d/dart.list && \ +RUN (cd /opt && \ + case "$(arch)" in x86_64) DART_ARCH=x64;; aarch64) DART_ARCH=arm64;; *) false;; esac && \ + curl -L -odart.zip "https://storage.googleapis.com/dart-archive/channels/stable/release/$( \ + curl -sSL https://storage.googleapis.com/dart-archive/channels/stable/release/latest/VERSION | jq -r .version \ + )/sdk/dartsdk-linux-$DART_ARCH-release.zip" && \ + unzip dart.zip && find /opt/dart-sdk -type d -exec chmod go+rx {} + && rm dart.zip) && \ + curl "https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb" --output packages-microsoft-prod.deb && \ + dpkg -i packages-microsoft-prod.deb && \ + rm packages-microsoft-prod.deb && \ apt-get update && \ apt-get install -y --no-install-recommends unzip libtinfo5 xz-utils \ - coffeescript gnucobol4 gnat gfortran tcl lua5.3 intercal php-cli dart/stable gforth swi-prolog pike8.0 sbcl && \ + coffeescript gnucobol4 gnat gfortran tcl lua5.3 intercal php-cli gforth swi-prolog pike8.0 sbcl dotnet-sdk-6.0 && \ rm -rf /var/lib/apt/lists/* && \ mkdir /opt/swift && \ - curl "$(echo -n https://swift.org; curl -s https://swift.org/download/ | grep 'Ubuntu 18.04' | head -n 1 | cut -d'"' -f 2)" | \ - tar xz -C /opt/swift --strip-components=1 && \ + if [ "$(arch)" = x86_64 ]; then \ + curl --compressed -L "$(curl --compressed -sL https://swift.org/download/ | grep 'Ubuntu 18.04' | grep 5.4 | head -n 1 | cut -d'"' -f 2)" | \ + tar xz -C /opt/swift --strip-components=1; fi && \ curl -L -ogroovy.zip "$(curl -s https://groovy.apache.org/download.html | perl -ne 'if(/(['"'"'"])(https:[^'"'"'"]+-binary-[\d.]+\.zip)\1/){print$2;exit}')" && \ unzip groovy.zip && \ mkdir /opt/groovy && \ @@ -17,9 +25,14 @@ RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - & curl -L -okotlin.zip "$(curl -s https://api.github.com/repos/JetBrains/kotlin/releases | \ jq -r '[.[] | select(.prerelease | not) | .assets | flatten | .[] | select(.name | startswith("kotlin-compiler")) | .browser_download_url][0]')" && \ unzip kotlin.zip && mv kotlinc /opt/kotlin && rm kotlin.zip && \ - curl -L -otprolog.zip "https://github.com/yingted/OpenTuring/releases/download/v1.0.0-beta/tprolog-v1.0.0-beta.zip" && \ - unzip tprolog.zip && mv tprolog /opt && rm tprolog.zip && \ + if [ "$(arch)" = x86_64 ]; then \ + curl -L -otprolog.zip "https://github.com/yingted/OpenTuring/releases/download/v1.0.0-beta/tprolog-v1.0.0-beta.zip" && \ + unzip tprolog.zip && mv tprolog /opt && rm tprolog.zip; fi && \ mkdir /opt/zig && \ - curl "https://ziglang.org/download/0.6.0/zig-linux-x86_64-0.6.0.tar.xz" | tar xJ -C /opt/zig --strip-components=1 + curl "https://ziglang.org/download/0.6.0/zig-linux-$(arch)-0.6.0.tar.xz" | tar xJ -C /opt/zig --strip-components=1 && \ + if [ "$(arch)" = x86_64 ]; then \ + mkdir /opt/lean && \ + curl --compressed -L "https://github.com/leanprover/lean4/releases/download/v4.0.0-m2/lean-4.0.0-m2-linux.tar.gz" | \ + tar xz -C /opt/lean --strip-components=1; fi -ENV PATH "/opt/tprolog:/opt/groovy/bin:/opt/kotlin/bin:${PATH}:/opt/swift/usr/bin:/opt/zig" +ENV PATH "/opt/tprolog:/opt/groovy/bin:/opt/kotlin/bin:/opt/dart-sdk/bin:${PATH}:/opt/swift/usr/bin:/opt/zig:/opt/lean/bin"