diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..84d8ac81 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# http://editorconfig.org +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 +indent_size = 4 +indent_style = space + +[*.{yml,yaml}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.github/workflows/build_chroot.yml b/.github/workflows/build_chroot.yml new file mode 100644 index 00000000..2a504292 --- /dev/null +++ b/.github/workflows/build_chroot.yml @@ -0,0 +1,64 @@ +# yaml-language-server: $schema=https://json-schema.org/draft-07/schema# +name: Build Chroot + +on: + workflow_dispatch: + inputs: + version: + description: "version" + required: true + default: "latest" + repo: + description: "repo" + required: true + default: "DOMjudge/domjudge" + commit_id: + description: "git commit id" + required: false + +jobs: + build-chroot: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + with: + image: tonistiigi/binfmt:latest + platforms: all + + - name: Available platforms + run: echo ${{ steps.qemu.outputs.platforms }} + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Inspect builder + run: | + echo "Name: ${{ steps.buildx.outputs.name }}" + echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}" + echo "Status: ${{ steps.buildx.outputs.status }}" + echo "Flags: ${{ steps.buildx.outputs.flags }}" + echo "Platforms: ${{ steps.buildx.outputs.platforms }}" + + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Download DOMjudge + run: | + bash ./docker/download.sh ${{ github.event.inputs.version }} ${{ github.event.inputs.repo }} ${{ github.event.inputs.commit_id }} + + - name: Build and Push + uses: docker/build-push-action@v2 + with: + context: ./docker + file: ./docker/judgehost/Dockerfile.chroot + platforms: linux/amd64,linux/arm64 + push: true + tags: dup4/domjudge-default-judgehost-chroot:${{ github.event.inputs.version }} diff --git a/.github/workflows/build_domserver.yml b/.github/workflows/build_domserver.yml new file mode 100644 index 00000000..d0682a4e --- /dev/null +++ b/.github/workflows/build_domserver.yml @@ -0,0 +1,78 @@ +# yaml-language-server: $schema=https://json-schema.org/draft-07/schema# +name: Build Domserver + +on: + workflow_dispatch: + inputs: + version: + description: "version" + required: true + default: "latest" + repo: + description: "repo" + required: true + default: "DOMjudge/domjudge" + commit_id: + description: "git commit id" + required: false + +jobs: + build-domserver: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + id: qemu + uses: docker/setup-qemu-action@v3 + with: + image: tonistiigi/binfmt:latest + platforms: all + + - name: Available platforms + run: echo ${{ steps.qemu.outputs.platforms }} + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + + - name: Inspect builder + run: | + echo "Name: ${{ steps.buildx.outputs.name }}" + echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}" + echo "Status: ${{ steps.buildx.outputs.status }}" + echo "Flags: ${{ steps.buildx.outputs.flags }}" + echo "Platforms: ${{ steps.buildx.outputs.platforms }}" + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to ALiYun Shanghai Container Registry + uses: docker/login-action@v3 + with: + registry: registry.cn-shanghai.aliyuncs.com + username: ${{ secrets.ALIYUN_REGISTRY_USERNAME }} + password: ${{ secrets.ALIYUN_REGISTRY_TOKEN }} + + - name: Download DOMjudge + run: | + bash ./docker/download.sh ${{ github.event.inputs.version }} ${{ github.event.inputs.repo }} ${{ github.event.inputs.commit_id }} + + - name: Build and Push + uses: docker/build-push-action@v5 + env: + registry_namespace: dup4 + image_name: domjudge-domserver + tag: ${{ github.event.inputs.version }} + with: + context: ./docker + file: ./docker/domserver/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ env.registry_namespace }}/${{ env.image_name }}:${{ env.tag }} + registry.cn-shanghai.aliyuncs.com/${{ env.registry_namespace }}/${{ env.image_name }}:${{ env.tag }} diff --git a/.github/workflows/build_judgehost.yml b/.github/workflows/build_judgehost.yml new file mode 100644 index 00000000..a366dd84 --- /dev/null +++ b/.github/workflows/build_judgehost.yml @@ -0,0 +1,80 @@ +# yaml-language-server: $schema=https://json-schema.org/draft-07/schema# +name: Build Judgehost + +on: + workflow_dispatch: + inputs: + version: + description: "version" + required: true + default: "latest" + repo: + description: "repo" + required: true + default: "DOMjudge/domjudge" + commit_id: + description: "git commit id" + required: false + +jobs: + build-judgehost: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + id: qemu + uses: docker/setup-qemu-action@v3 + with: + image: tonistiigi/binfmt:latest + platforms: all + + - name: Available platforms + run: echo ${{ steps.qemu.outputs.platforms }} + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + + - name: Inspect builder + run: | + echo "Name: ${{ steps.buildx.outputs.name }}" + echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}" + echo "Status: ${{ steps.buildx.outputs.status }}" + echo "Flags: ${{ steps.buildx.outputs.flags }}" + echo "Platforms: ${{ steps.buildx.outputs.platforms }}" + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to ALiYun Shanghai Container Registry + uses: docker/login-action@v3 + with: + registry: registry.cn-shanghai.aliyuncs.com + username: ${{ secrets.ALIYUN_REGISTRY_USERNAME }} + password: ${{ secrets.ALIYUN_REGISTRY_TOKEN }} + + - name: Download DOMjudge + run: | + bash ./docker/download.sh ${{ github.event.inputs.version }} ${{ github.event.inputs.repo }} ${{ github.event.inputs.commit_id }} + + - name: Build + env: + tag: ${{ github.event.inputs.version }} + run: | + cd ./docker + sudo bash -e build-judgehost.sh dup4/domjudge-judgehost:${{ env.tag }} + + - name: Push + env: + registry_namespace: dup4 + image_name: domjudge-judgehost + tag: ${{ github.event.inputs.version }} + run: | + docker push ${{ env.registry_namespace }}/${{ env.image_name }}:${{ env.tag }} + docker tag ${{ env.registry_namespace }}/${{ env.image_name }}:${{ env.tag }} registry.cn-shanghai.aliyuncs.com/${{ env.registry_namespace }}/${{ env.image_name }}:${{ env.tag }} + docker push registry.cn-shanghai.aliyuncs.com/${{ env.registry_namespace }}/${{ env.image_name }}:${{ env.tag }} diff --git a/.github/workflows/build_judgehost_in_docker.yml b/.github/workflows/build_judgehost_in_docker.yml new file mode 100644 index 00000000..0bc89088 --- /dev/null +++ b/.github/workflows/build_judgehost_in_docker.yml @@ -0,0 +1,65 @@ +# yaml-language-server: $schema=https://json-schema.org/draft-07/schema# +name: Build Judgehost In Docker + +on: + workflow_dispatch: + inputs: + version: + description: "version" + required: true + default: "latest" + repo: + description: "repo" + required: true + default: "DOMjudge/domjudge" + commit_id: + description: "git commit id" + required: false + +jobs: + build-judgehost-in-docker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + with: + image: tonistiigi/binfmt:latest + platforms: all + + - name: Available platforms + run: echo ${{ steps.qemu.outputs.platforms }} + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Inspect builder + run: | + echo "Name: ${{ steps.buildx.outputs.name }}" + echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}" + echo "Status: ${{ steps.buildx.outputs.status }}" + echo "Flags: ${{ steps.buildx.outputs.flags }}" + echo "Platforms: ${{ steps.buildx.outputs.platforms }}" + + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Download DOMjudge + run: | + bash ./docker/download.sh ${{ github.event.inputs.version }} ${{ github.event.inputs.repo }} ${{ github.event.inputs.commit_id }} + + - name: Build and Push + uses: docker/build-push-action@v2 + with: + context: ./docker + file: ./docker/judgehost/Dockerfile.all + platforms: linux/amd64,linux/arm64 + allow: security.insecure + push: true + tags: dup4/domjudge-judgehost:${{ github.event.inputs.version }} diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index c6fd65e9..f6fe68ad 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -16,3 +16,5 @@ jobs: - uses: actions/checkout@v2 - name: Run ShellCheck uses: ludeeus/action-shellcheck@master + with: + severity: error \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..55f7ebef --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "editor.tabSize": 4, + "editor.insertSpaces": true, + "editor.formatOnSave": true, + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true, + "cSpell.words": [ + "buildx", + "DOCKERHUB", + "domjudge", + "judgehost", + "shellcheck" + ], +} diff --git a/docker/domserver/Dockerfile b/docker/domserver/Dockerfile index 1ca27649..3909e98e 100644 --- a/docker/domserver/Dockerfile +++ b/docker/domserver/Dockerfile @@ -2,6 +2,7 @@ FROM debian:bookworm-slim AS domserver-build LABEL org.opencontainers.image.authors="DOMjudge team " ENV DEBIAN_FRONTEND=noninteractive +ENV COMPOSER_ALLOW_SUPERUSER=1 # Install required packages for build of domserver RUN apt-get update \ @@ -17,6 +18,7 @@ RUN apt-get update \ texlive-fonts-recommended texlive-lang-european latexmk tex-gyre \ libcurl4-gnutls-dev libjsoncpp-dev libmagic-dev \ enscript lpr ca-certificates \ + moreutils \ && rm -rf /var/lib/apt/lists/* # Use venv to install latest Sphinx. 6.1.0 or higher is required to build DOMjudge docs. diff --git a/docker/download.sh b/docker/download.sh new file mode 100755 index 00000000..07c03a53 --- /dev/null +++ b/docker/download.sh @@ -0,0 +1,51 @@ +#! /bin/bash + +TOP_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")" +FILE_NAME="domjudge" +FILE="${TOP_DIR}/${FILE_NAME}.tar.gz" +DIR="${TOP_DIR}/${FILE_NAME}" + +VERSION="${1}" +REPO="${2}" +COMMIT_ID="${3}" + +if [[ -z "${VERSION}" ]]; then + VERSION="latest" +fi + +if [[ -z "${REPO}" ]]; then + REPO="DOMjudge/domjudge" +fi + +if command -v git >/dev/null 2>&1; then + GIT_COMMAND="git clone https://github.com/${REPO}.git" + if [[ -z "${COMMIT_ID}" ]] && [[ X"${VERSION}" != X"latest" ]]; then + GIT_COMMAND="${GIT_COMMAND} -b ${VERSION}" + fi + + GIT_COMMAND="${GIT_COMMAND} ${DIR}" + + ${GIT_COMMAND} + + if [[ -n "${COMMIT_ID}" ]]; then + cd "${DIR}" || exit 1 + git reset --hard "${COMMIT_ID}" + cd - || exit 1 + fi + + tar -cvzf "${FILE}" -C "${TOP_DIR}" "${FILE_NAME}" + rm -rf "${DIR}" +else + if [[ X"${VERSION}" = X"latest" ]]; then + URL=https://codeload.github.com/${REPO}/tar.gz/refs/heads/main + else + URL=https://codeload.github.com/${REPO}/tar.gz/refs/tags/${VERSION} + fi + + echo "[..] Downloading DOMjudge version ${VERSION}..." + + if ! wget --quiet "${URL}" -O "${FILE}"; then + echo "[!!] DOMjudge version ${VERSION} file not found on https://codeload.github.com/DOMjudge/domjudge" + exit 1 + fi +fi diff --git a/docker/judgehost/Dockerfile.all b/docker/judgehost/Dockerfile.all new file mode 100644 index 00000000..f4a0ae06 --- /dev/null +++ b/docker/judgehost/Dockerfile.all @@ -0,0 +1,79 @@ +FROM debian:stable-slim AS build + +ENV DEBIAN_FRONTEND=noninteractive + +USER root + +# Install required packages for build of judgehost +RUN apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + autoconf automake git \ + gcc g++ make zip unzip \ + php-cli php-zip lsb-release debootstrap \ + php-gd php-curl php-mysql php-json \ + php-gmp php-xml php-mbstring \ + sudo bsdmainutils ntp libcgroup-dev procps \ + libcurl4-gnutls-dev libjsoncpp-dev libmagic-dev \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Set up user +RUN useradd -m domjudge + +# Install composer + +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ + && php composer-setup.php \ + && mv /composer.phar /usr/local/bin/composer + +# Add DOMjudge source code and build script +ADD domjudge.tar.gz /domjudge-src +ADD judgehost/build.sh /domjudge-src + +COPY ["judgehost/chroot-and-tar.sh", "/scripts/"] + +# Build and install judgehost +RUN /domjudge-src/build.sh \ + && /scripts/chroot-and-tar.sh + +FROM debian:stable + +ENV DEBIAN_FRONTEND=noninteractive \ + CONTAINER_TIMEZONE=Europe/Amsterdam \ + DOMSERVER_BASEURL=http://domserver/ \ + JUDGEDAEMON_USERNAME=judgehost \ + JUDGEDAEMON_PASSWORD=password \ + DAEMON_ID=0 \ + DOMJUDGE_CREATE_WRITABLE_TEMP_DIR=0 \ + RUN_USER_UID_GID=62860 + +# Install required packages for running of judgehost +RUN apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y \ + dumb-init \ + acl zip unzip supervisor sudo procps libcgroup1 \ + php-cli php-zip php-gd php-curl php-mysql php-json \ + php-gmp php-xml php-mbstring python3 \ + gcc g++ default-jre-headless default-jdk ghc fp-compiler \ + && rm -rf /var/lib/apt/lists/* + +# Add chroot and judgehost data +COPY --from=build /chroot.tar.gz / +COPY --from=build /judgehost.tar.gz / + +RUN tar -zxvf chroot.tar.gz \ + && tar -zxvf judgehost.tar.gz \ + && cp /opt/domjudge/judgehost/etc/sudoers-domjudge /etc/sudoers.d/ + +# Add scripts +COPY judgehost/scripts /scripts/ + +# Make the scripts available to the root user +ENV PATH="$PATH:/opt/domjudge/judgehost/bin" + +# Change start script permissions, add user and fix permissions +COPY judgehost/configure.sh /configure.sh +RUN chmod 700 /configure.sh && /configure.sh && rm -f /configure.sh + +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/scripts/start.sh"] diff --git a/docker/judgehost/chroot-and-tar.sh b/docker/judgehost/chroot-and-tar.sh index 56da9a90..2a35c447 100755 --- a/docker/judgehost/chroot-and-tar.sh +++ b/docker/judgehost/chroot-and-tar.sh @@ -3,7 +3,10 @@ set -euo pipefail # Usage: https://github.com/DOMjudge/domjudge/blob/main/misc-tools/dj_make_chroot.in#L58-L87 -/opt/domjudge/judgehost/bin/dj_make_chroot +/opt/domjudge/judgehost/bin/dj_make_chroot \ + -D Ubuntu \ + -R jammy \ + -i openjdk-17-jdk-headless,openjdk-17-jre-headless cd / echo "[..] Compressing chroot"