feat: deploy support

This commit is contained in:
Paul Pan 2023-08-11 18:54:00 +08:00
parent 87d5506085
commit 1365e54aec
Signed by: Paul
GPG Key ID: D639BDF5BA578AF4
22 changed files with 405 additions and 244 deletions

8
.dockerignore Normal file
View File

@ -0,0 +1,8 @@
# top
/woj
# runner
resource/runner/.mark.container
resource/runner/problem/*
resource/runner/tmp/*
resource/runner/user/*

25
.idea/jsonSchemas.xml Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JsonSchemaMappingsProjectConfiguration">
<state>
<map>
<entry key="docker-compose.yml">
<value>
<SchemaInfo>
<option name="name" value="docker-compose.yml" />
<option name="relativePathToSchema" value="https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json" />
<option name="applicationDefined" value="true" />
<option name="patterns">
<list>
<Item>
<option name="path" value="docker-compose.yml" />
</Item>
</list>
</option>
</SchemaInfo>
</value>
</entry>
</map>
</state>
</component>
</project>

View File

@ -1,8 +1,12 @@
GO := go
LDFLAGS += -X cmd.BuildTime=$(shell date -u '+%Y-%m-%d-%I-%M-%S')
LDFLAGS += -X cmd.Version=$(shell cat VERSION)+$(shell git rev-parse --short HEAD)
LDFLAGS += -X cmd.SentryDSN=$(shell cat dsn.txt)
PKG_BASE := $(shell head -n 1 go.mod | awk '{print $$2}')
BUILD_TIME := $(shell date -u '+%Y%m%d-%I%M%S')
VERSION := $(shell cat VERSION)+$(shell git rev-parse --short HEAD)
LDFLAGS += -X $(PKG_BASE)/cmd.BuildTime=$(BUILD_TIME)
LDFLAGS += -X $(PKG_BASE)/cmd.Version=$(VERSION)
LDFLAGS += -X $(PKG_BASE)/cmd.SentryDSN=$(shell cat dsn.txt)
LDFLAGS += -s -w
GOBUILD := $(GO) build -ldflags '$(LDFLAGS)'
@ -18,8 +22,7 @@ build: swagger dep
$(GOBUILD) -o woj ./cmd/woj
clean:
rm -f runner
rm -f server
rm -f woj
dep:
go mod download

35
Runner.Dockerfile Normal file
View File

@ -0,0 +1,35 @@
# builder
FROM docker.io/library/golang:alpine AS builder
ENV GOPROXY=https://goproxy.cn
WORKDIR /builder
RUN apk add --no-cache git make
RUN go install github.com/swaggo/swag/cmd/swag@latest
COPY go.mod /builder/go.mod
COPY go.sum /builder/go.sum
RUN go mod download
COPY . /builder
RUN make build
# main image
FROM quay.io/podman/stable
# pkill
RUN yum -y install jq procps-ng && yum -y clean all && rm -rf /var/cache
WORKDIR /app
# prepare images
COPY --from=builder /builder/resource/runner /app/resource/runner
RUN bash -c "cd /app/resource/runner/scripts && ./prepare_images.sh save"
# sources
COPY --from=builder /builder/config.docker.yaml /app
COPY --from=builder /builder/docker-entrypoint.sh /app
COPY --from=builder /builder/woj /app
ENTRYPOINT ["/app/docker-entrypoint.sh"]

View File

@ -1,5 +1,5 @@
# builder
FROM golang:alpine AS builder
FROM docker.io/library/golang:alpine AS builder
ENV GOPROXY=https://goproxy.cn
WORKDIR /builder
@ -16,16 +16,14 @@ RUN make build
# main image
FROM alpine:latest
FROM docker.io/library/alpine
WORKDIR /app
RUN apk --no-cache add tzdata ca-certificates libc6-compat
RUN apk --no-cache add tzdata ca-certificates libc6-compat bash
COPY --from=builder /builder/config.docker.yaml /app
COPY --from=builder /builder/docker-entrypoint.sh /app
COPY --from=builder /builder/resource/frontend /app/resource/frontend
COPY --from=builder /builder/resource/runner /app/resource/runner
COPY --from=builder /builder/woj /app
ENTRYPOINT ["/app/docker-entrypoint.sh"]

57
build_image.sh Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env bash
. resource/runner/scripts/common.sh
# version
VERSION="$(cat VERSION)"
log_info "VERSION: $VERSION"
function build_base() {
log_info "[+] Building Base Images"
pushd resource/runner/scripts || exit 1
$DOCKER build -t git.0x7f.app/woj/ubuntu-full:latest -f scripts/ubuntu-full.Dockerfile . ||
(log_error "Build Full Image failed" && exit 1)
$DOCKER build -t git.0x7f.app/woj/ubuntu-run:latest -f scripts/ubuntu-run.Dockerfile . ||
(log_error "Build Tiny Image failed" && exit 1)
popd
}
function push_base() {
log_info "[+] Pushing Base Images"
$DOCKER push "git.0x7f.app/woj/ubuntu-full:latest"
$DOCKER push "git.0x7f.app/woj/ubuntu-run:latest"
}
function build_server() {
log_info "[+] Building Server"
$DOCKER build -t "git.0x7f.app/woj/woj-server:$VERSION" -f Server.Dockerfile . ||
(log_error "[!] Failed to build Server" && exit 1)
}
function build_runner() {
log_info "[+] Building Runner"
$DOCKER build \
--cap-add=sys_admin,mknod \
--device=/dev/fuse \
--security-opt label=disable \
-t "git.0x7f.app/woj/woj-runner:$VERSION" \
-f Runner.Dockerfile . ||
(log_error "[!] Failed to build Runner" && exit 1)
}
function push_server() {
log_info "[+] Pushing Server Images"
$DOCKER push "git.0x7f.app/woj/woj-server:$VERSION"
}
function push_runner() {
log_info "[+] Pushing Runner Images"
$DOCKER push "git.0x7f.app/woj/woj-runner:$VERSION"
}
# build_base
# push_base
build_server
push_server
build_runner
push_runner

View File

@ -59,7 +59,7 @@ func init() {
}
func getBuildTime() time.Time {
build, err := time.Parse("2006-01-02-15-04-05", BuildTime)
build, err := time.Parse("20060102-150405", BuildTime)
if err != nil {
log.Printf("failed to parse build time: %v", err)
build = time.Now()

View File

@ -1,11 +1,9 @@
version: "3"
services:
server:
build: .
image: git.0x7f.app/woj/woj-server:1.1.0
restart: unless-stopped
healthcheck:
test: [ "CMD", "wget", "-q", "http://127.0.0.1:8000/health" ]
test: [ "CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8000/health" ]
interval: 5s
command: web
environment:
@ -14,7 +12,7 @@ services:
- DATABASE_USER=dev
- DATABASE_PASSWORD=password
- DATABASE_NAME=dev
- STORAGE_ENDPOINT=minio:9000
- STORAGE_ENDPOINT=storage:9000
- STORAGE_ACCESS_KEY=access_key
- STORAGE_SECRET_KEY=secret_key
- STORAGE_BUCKET=woj
@ -23,6 +21,8 @@ services:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
runner:
condition: service_started
storage:
condition: service_healthy
cache:
@ -32,22 +32,36 @@ services:
ports:
- "8000:8000"
#runner:
# build: .
# restart: unless-stopped
# command: runner
# environment:
# - REDIS_ADDRESS_PORT=cache:6379
# - DEVELOPMENT=true
# volumes:
# - runner:/app/resource/runner/user
# - /etc/timezone:/etc/timezone:ro
# - /etc/localtime:/etc/localtime:ro
# depends_on:
# - cache
runner:
image: git.0x7f.app/woj/woj-runner:1.1.0
restart: unless-stopped
command: runner
security_opt:
- "label=disable"
cap_add:
- SYS_ADMIN
- MKNOD
devices:
- "/dev/fuse"
environment:
- REDIS_ADDRESS_PORT=cache:6379
- STORAGE_ENDPOINT=storage:9000
- STORAGE_ACCESS_KEY=access_key
- STORAGE_SECRET_KEY=secret_key
- STORAGE_BUCKET=woj
- DEVELOPMENT=true
volumes:
- runner:/app/resource/runner/user
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
storage:
condition: service_healthy
cache:
condition: service_healthy
storage:
image: minio/minio:latest
image: quay.io/minio/minio:latest
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl", "-f", "http://127.0.0.1:9000/minio/health/live" ]
@ -55,13 +69,13 @@ services:
entrypoint: sh
command: -c 'mkdir -p /data/woj && minio server /data'
environment:
MINIO_ACCESS_KEY: "access_key"
MINIO_SECRET_KEY: "secret_key"
MINIO_ROOT_USER: "access_key"
MINIO_ROOT_PASSWORD: "secret_key"
volumes:
- storage:/data
cache:
image: redis:alpine
image: docker.io/library/redis:alpine
restart: unless-stopped
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
@ -70,7 +84,7 @@ services:
- cache:/data
db:
image: postgres:alpine
image: docker.io/library/postgres:alpine
restart: unless-stopped
healthcheck:
test: [ "CMD", "pg_isready", "-U", "dev" ]
@ -86,4 +100,4 @@ volumes:
runner:
storage:
cache:
db:
db:

View File

@ -1,4 +1,4 @@
#!/bin/ash
#!/bin/bash
set -eo pipefail
COLOR_RED="\e[0;31m"

View File

@ -18,7 +18,7 @@ func (s *service) EnsureDeps(force bool) e.Status {
return e.Success
}
script := filepath.Join(ScriptsDir, "prepare_container.sh")
script := filepath.Join(ScriptsDir, "prepare_images.sh")
cmd := exec.Command(script)
cmd.Dir = ScriptsDir
err := cmd.Run()

View File

@ -1,7 +1,4 @@
# docker image mark
.mark.*
# tmp dockerfile
ubuntu-full.Dockerfile
ubuntu-run.Dockerfile
# other tmp files
*.zip

View File

@ -10,5 +10,8 @@ function log_warn() { echo -e "${COLOR_YELLOW}$*${COLOR_NONE}" 1>&2; }
function log_error() { echo -e "${COLOR_RED}$*${COLOR_NONE}" 1>&2; }
# Docker or Podman
DOCKER="docker"
if [ "$USE_PODMAN" ]; then DOCKER="podman"; fi
DOCKER="podman"
if [ "$USE_DOCKER" ]; then
log_error "docker is deprecated"
log_info "Use podman instead"
fi

View File

@ -1,59 +0,0 @@
#!/usr/bin/env bash
. common.sh
cd "$(dirname "$0")"/../ || exit 1
# Check Mark
if [ -f ./.mark.container ]; then
log_warn "Docker containers already prepared"
log_warn "If you want to re-prepare the containers, please remove the file $(pwd)/.mark.container"
exit 1
fi
log_info "Preparing container..."
log_info "Using $DOCKER - $($DOCKER --version)"
# Full
log_info "Building Full Image"
cat <<EOF >ubuntu-full.Dockerfile
FROM docker.io/library/ubuntu:22.04
WORKDIR /woj/
# Install dependencies
RUN apt-get update && apt-get upgrade -y && apt-get install -y gcc g++ clang make cmake autoconf m4 libtool gperf git parallel python3 && apt-get clean && rm -rf /var/lib/apt/lists
# Copy source code
RUN mkdir -p /woj/framework && mkdir -p /woj/problem
COPY framework /woj/framework
# Build
RUN cd /woj/framework/template && ./setup.sh
RUN cd /woj/framework/scripts && ./setup.sh
# Environment
ENV WOJ_LAUNCHER=/woj/framework/scripts/woj_launcher
ENV WOJ_SANDBOX=/woj/framework/scripts/libwoj_sandbox.so
ENV TEMPLATE=/woj/framework/template
ENV TESTLIB=/woj/framework/template/testlib
ENV PREFIX=/woj/problem
EOF
$DOCKER build -t woj/ubuntu-full -f ubuntu-full.Dockerfile . || exit 1
rm ubuntu-full.Dockerfile
# Tiny
log_info "Building Tiny Image"
cat <<EOF >ubuntu-run.Dockerfile
FROM woj/ubuntu-full:latest AS builder
FROM docker.io/library/ubuntu:22.04
WORKDIR /woj/problem
RUN mkdir -p /woj/framework/scripts
COPY --from=builder /woj/framework/scripts/libwoj_sandbox.so /woj/framework/scripts/
COPY --from=builder /woj/framework/scripts/woj_launcher /woj/framework/scripts/
EOF
$DOCKER build -t woj/ubuntu-run -f ubuntu-run.Dockerfile . || exit 1
rm ubuntu-run.Dockerfile
touch ./.mark.container
log_info "Done"

View File

@ -0,0 +1,52 @@
#!/usr/bin/env bash
. common.sh
cd "$(dirname "$0")"/../ || exit 1
# Check Mark
if [ -f ./.mark.image ]; then
log_warn "Docker images already prepared"
log_warn "If you want to re-prepare the images, please remove the file $(pwd)/.mark.image"
exit 1
fi
log_info "Preparing image..."
log_info "Checking $DOCKER - $($DOCKER --version)"
# Full
if [ -f ./tmp/ubuntu-full.tar.gz ]; then
log_info "Importing Full Image"
gzip -d -c ./tmp/ubuntu-full.tar.gz | $DOCKER load || (log_error "Import Full Image failed" && exit 1)
else
log_info "Pulling Full Image"
if ! $DOCKER pull git.0x7f.app/woj/ubuntu-full:latest; then
log_warn "Pull failed, building from scratch"
log_info "Building Full Image"
$DOCKER build -t git.0x7f.app/woj/ubuntu-full:latest -f scripts/ubuntu-full.Dockerfile . || (log_error "Build Full Image failed" && exit 1)
fi
fi
# Tiny
if [ -f ./tmp/ubuntu-tiny.tar.gz ]; then
log_info "Importing Tiny Image"
gzip -d -c ./tmp/ubuntu-tiny.tar.gz | $DOCKER load || (log_error "Import Tiny Image failed" && exit 1)
else
log_info "Pulling Tiny Image"
if ! $DOCKER pull git.0x7f.app/woj/ubuntu-run:latest; then
log_warn "Pull failed, building from scratch"
log_info "Building Tiny Image"
$DOCKER build -t git.0x7f.app/woj/ubuntu-run:latest -f scripts/ubuntu-run.Dockerfile . || (log_error "Build Tiny Image failed" && exit 1)
fi
fi
# Mark
if [ "$1" == "save" ]; then
log_info "Saving Images"
$DOCKER save git.0x7f.app/woj/ubuntu-full:latest | gzip -9 >./tmp/ubuntu-full.tar.gz
$DOCKER save git.0x7f.app/woj/ubuntu-run:latest | gzip -9 >./tmp/ubuntu-tiny.tar.gz
else
touch ./.mark.image
fi
log_info "Done"

View File

@ -9,67 +9,67 @@
# $3: language
# exports: Info_Script, Info_Cmp, Info_Num, Info_Limit_Time, Info_Limit_Memory, Info_Limit_NProc
function get_problem_info() {
local err
local err
if [ ! -f "$1/problem/$2/config.json" ]; then
log_error "problem $2 not found"
return 1
fi
if [ ! -f "$1/problem/$2/config.json" ]; then
log_error "problem $2 not found"
return 1
fi
parse_language_info "$1" "$2" "$3"
err=$?
if [ "$err" -ne 0 ]; then
return "$err"
fi
parse_language_info "$1" "$2" "$3"
err=$?
if [ "$err" -ne 0 ]; then
return "$err"
fi
parse_limits "$1" "$2"
err=$?
if [ "$err" -ne 0 ]; then
return "$err"
fi
parse_limits "$1" "$2"
err=$?
if [ "$err" -ne 0 ]; then
return "$err"
fi
}
function parse_language_info() {
export Info_Script
export Info_Cmp
export Info_Script
export Info_Cmp
local lang_config
local lang_type
local lang_script
local lang_config
local lang_type
local lang_script
lang_config=$(jq ".Languages[] | select(.Lang == \"$3\")" "$1/problem/$2/config.json")
if [ -z "$lang_config" ]; then
log_error "language $3 is not supported"
return 1
fi
lang_config=$(jq ".Languages[] | select(.Lang == \"$3\")" "$1/problem/$2/config.json")
if [ -z "$lang_config" ]; then
log_error "language $3 is not supported"
return 1
fi
Info_Cmp=$(echo "$lang_config" | jq -r ".Cmp")
Info_Cmp=$(echo "$lang_config" | jq -r ".Cmp")
lang_type=$(echo "$lang_config" | jq -r ".Type")
lang_script=$(echo "$lang_config" | jq -r ".Script")
lang_type=$(echo "$lang_config" | jq -r ".Type")
lang_script=$(echo "$lang_config" | jq -r ".Script")
if [ "$lang_type" == "custom" ]; then
Info_Script="/woj/problem/judge/$lang_script"
elif [ "$lang_type" == "default" ]; then
Info_Script="/woj/framework/template/default/$3.Makefile"
else
log_warn "Config file might be corrupted!"
log_error "Unknown language type: $lang_type"
return 1
fi
if [ "$lang_type" == "custom" ]; then
Info_Script="/woj/problem/judge/$lang_script"
elif [ "$lang_type" == "default" ]; then
Info_Script="/woj/framework/template/default/$3.Makefile"
else
log_warn "Config file might be corrupted!"
log_error "Unknown language type: $lang_type"
return 1
fi
}
function parse_limits() {
export Info_Limit_Time
export Info_Limit_Memory
export Info_Limit_NProc
export Info_Num
export Info_Limit_Time
export Info_Limit_Memory
export Info_Limit_NProc
export Info_Num
local cfg
cfg="$1/problem/$2/config.json"
local cfg
cfg="$1/problem/$2/config.json"
Info_Limit_Time=$(jq ".Runtime.TimeLimit" "$cfg")
Info_Limit_Memory=$(jq ".Runtime.MemoryLimit" "$cfg")
Info_Limit_NProc=$(jq ".Runtime.NProcLimit" "$cfg")
Info_Num=$(jq ".Tasks | length" "$1/problem/$2/config.json")
Info_Limit_Time=$(jq ".Runtime.TimeLimit" "$cfg")
Info_Limit_Memory=$(jq ".Runtime.MemoryLimit" "$cfg")
Info_Limit_NProc=$(jq ".Runtime.NProcLimit" "$cfg")
Info_Num=$(jq ".Tasks | length" "$1/problem/$2/config.json")
}

View File

@ -6,8 +6,8 @@ WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
. "$WORKSPACE"/scripts/problem.sh
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then
log_warn "Usage: $0 <problem> <user_dir> <language> <timeout>"
exit 1
log_warn "Usage: $0 <problem> <user_dir> <language> <timeout>"
exit 1
fi
get_problem_info "$WORKSPACE" "$1" "$3"
@ -20,11 +20,11 @@ rm -f "$EXE_FILE" && touch "$EXE_FILE"
export TIMEOUT=${4:-60}
docker_run \
-v "$WORKSPACE"/problem/"$1"/judge:/woj/problem/judge:ro \
-v "$SRC_FILE":/woj/problem/user/"$2"."$3":ro \
-v "$EXE_FILE":/woj/problem/user/"$2".out \
-e USER_PROG="$2" \
-e LANG="$3" \
woj/ubuntu-full \
sh -c \
"cd /woj/problem/user && make -f $Info_Script compile"
-v "$WORKSPACE"/problem/"$1"/judge:/woj/problem/judge:ro \
-v "$SRC_FILE":/woj/problem/user/"$2"."$3":ro \
-v "$EXE_FILE":/woj/problem/user/"$2".out \
-e USER_PROG="$2" \
-e LANG="$3" \
git.0x7f.app/woj/ubuntu-full \
sh -c \
"cd /woj/problem/user && make -f $Info_Script compile"

View File

@ -6,35 +6,35 @@ WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
. "$WORKSPACE"/scripts/problem.sh
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then
log_warn "Usage: $0 <problem> <user_dir> <language> <timeout>"
exit 1
log_warn "Usage: $0 <problem> <user_dir> <language> <timeout>"
exit 1
fi
get_problem_info "$WORKSPACE" "$1" "$3"
export TIMEOUT=${4:-60}
for test_num in $(seq "$Info_Num"); do
std_file="$WORKSPACE/problem/$1/data/output/$test_num.output"
ans_file="$WORKSPACE/user/$2/$test_num.out.usr"
jdg_file="$WORKSPACE/user/$2/$test_num.judge"
std_file="$WORKSPACE/problem/$1/data/output/$test_num.output"
ans_file="$WORKSPACE/user/$2/$test_num.out.usr"
jdg_file="$WORKSPACE/user/$2/$test_num.judge"
if [ ! -f "$std_file" ] || [ ! -f "$ans_file" ]; then
log_error "Missing test case $test_num"
exit 1
fi
if [ ! -f "$std_file" ] || [ ! -f "$ans_file" ]; then
log_error "Missing test case $test_num"
exit 1
fi
log_info "Judging test case $test_num"
log_info "Judging test case $test_num"
touch "$jdg_file"
touch "$jdg_file"
docker_run \
-v "$WORKSPACE"/problem/"$1"/judge:/woj/problem/judge:ro \
-v "$WORKSPACE"/problem/"$1"/data:/woj/problem/data:ro \
-v "$ans_file":/woj/problem/user/"$test_num".out.usr \
-v "$jdg_file":/woj/problem/user/"$test_num".judge \
-e TEST_NUM="$test_num" \
-e CMP="$Info_Cmp" \
woj/ubuntu-full \
sh -c \
"cd /woj/problem/user && make -f $Info_Script judge"
docker_run \
-v "$WORKSPACE"/problem/"$1"/judge:/woj/problem/judge:ro \
-v "$WORKSPACE"/problem/"$1"/data:/woj/problem/data:ro \
-v "$ans_file":/woj/problem/user/"$test_num".out.usr \
-v "$jdg_file":/woj/problem/user/"$test_num".judge \
-e TEST_NUM="$test_num" \
-e CMP="$Info_Cmp" \
git.0x7f.app/woj/ubuntu-full \
sh -c \
"cd /woj/problem/user && make -f $Info_Script judge"
done

View File

@ -5,28 +5,28 @@ WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
. "$WORKSPACE"/scripts/common.sh
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ]; then
log_warn "Usage: $0 <problem> <timeout>"
exit 1
log_warn "Usage: $0 <problem> <timeout>"
exit 1
fi
if [ -f "$WORKSPACE/problem/$1/.mark.prebuild" ]; then
log_warn "Problem $1 already prebuilt"
log_warn "If you want to re-prebuild the problem, please remove the file $WORKSPACE/problem/$1/.mark.prebuild"
exit 0
log_warn "Problem $1 already prebuilt"
log_warn "If you want to re-prebuild the problem, please remove the file $WORKSPACE/problem/$1/.mark.prebuild"
exit 0
fi
if [ ! -f "$WORKSPACE/problem/$1/judge/prebuild.Makefile" ]; then
log_warn "Problem $1 does not have prebuild scripts"
log_warn "$WORKSPACE/problem/$1/.mark.prebuild"
exit 0
log_warn "Problem $1 does not have prebuild scripts"
log_warn "$WORKSPACE/problem/$1/.mark.prebuild"
exit 0
fi
export TIMEOUT=${2:-300}
docker_run \
-v "$WORKSPACE/problem/$1/data":/woj/problem/data \
-v "$WORKSPACE/problem/$1/judge":/woj/problem/judge \
-e PREFIX=/woj/problem \
woj/ubuntu-full \
sh -c "cd /woj/problem/judge && make -f prebuild.Makefile prebuild && touch .mark.prebuild"
-v "$WORKSPACE/problem/$1/data":/woj/problem/data \
-v "$WORKSPACE/problem/$1/judge":/woj/problem/judge \
-e PREFIX=/woj/problem \
git.0x7f.app/woj/ubuntu-full \
sh -c "cd /woj/problem/judge && make -f prebuild.Makefile prebuild && touch .mark.prebuild"
mv "$WORKSPACE/problem/$1/judge/.mark.prebuild" "$WORKSPACE/problem/$1/.mark.prebuild" || exit 1

View File

@ -6,20 +6,20 @@ WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
. "$WORKSPACE"/scripts/problem.sh
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then
log_warn "Usage: $0 <problem> <user_dir> <language>"
exit 1
log_warn "Usage: $0 <problem> <user_dir> <language>"
exit 1
fi
if [ ! -f "$WORKSPACE/problem/$1/.mark.prebuild" ]; then
log_warn "Problem $1 has not been prebuilt"
log_warn "Please run 'problem_prebuild.sh $1' first"
exit 1
log_warn "Problem $1 has not been prebuilt"
log_warn "Please run 'problem_prebuild.sh $1' first"
exit 1
fi
if [ ! -f "$WORKSPACE/user/$2/$2.out" ]; then
log_warn "User $2 has not been compiled"
log_warn "Please run 'problem_compile.sh ...' first"
exit 1
log_warn "User $2 has not been compiled"
log_warn "Please run 'problem_compile.sh ...' first"
exit 1
fi
parse_limits "$WORKSPACE" "$1"
@ -35,37 +35,37 @@ TIMEOUT=$(((LIMIT_TIME + 1000) / 1000 + 4))
log_info "Timeout: $TIMEOUT"
for test_num in $(seq "$Info_Num"); do
test_case="$WORKSPACE/problem/$1/data/input/$test_num.input"
exe_file="$WORKSPACE/user/$2/$2.out"
ans_file="$WORKSPACE/user/$2/$test_num.out.usr"
ifo_file="$WORKSPACE/user/$2/$test_num.info"
test_case="$WORKSPACE/problem/$1/data/input/$test_num.input"
exe_file="$WORKSPACE/user/$2/$2.out"
ans_file="$WORKSPACE/user/$2/$test_num.out.usr"
ifo_file="$WORKSPACE/user/$2/$test_num.info"
if [ ! -f "$test_case" ]; then
log_error "Test case $test_num does not exist"
exit 1
fi
if [ ! -f "$test_case" ]; then
log_error "Test case $test_num does not exist"
exit 1
fi
log_info "Running test case $test_num"
rm -f "$ans_file" && touch "$ans_file"
rm -f "$ifo_file" && touch "$ifo_file"
docker_run \
--cpus 1 \
--network none \
-v "$test_case":/woj/problem/data/input/"$test_num".input:ro \
-v "$exe_file":/woj/user/"$2".out:ro \
-v "$ans_file":/woj/user/"$test_num".out.usr \
-v "$ifo_file":/woj/user/"$test_num".info \
woj/ubuntu-run \
sh -c \
"cd /woj/user && /woj/framework/scripts/woj_launcher \
--memory_limit=$Info_Limit_Memory \
--nproc_limit=$Info_Limit_NProc \
--time_limit=$Info_Limit_Time \
--sandbox_path=/woj/framework/scripts/libwoj_sandbox.so \
--sandbox_template=$3 \
--sandbox_action=nothing \
--file_input=/woj/problem/data/input/$test_num.input \
--file_output=/woj/user/$test_num.out.usr \
--file_info=/woj/user/$test_num.info \
--program=/woj/user/$2.out"
log_info "Running test case $test_num"
rm -f "$ans_file" && touch "$ans_file"
rm -f "$ifo_file" && touch "$ifo_file"
docker_run \
--cpus 1 \
--network none \
-v "$test_case":/woj/problem/data/input/"$test_num".input:ro \
-v "$exe_file":/woj/user/"$2".out:ro \
-v "$ans_file":/woj/user/"$test_num".out.usr \
-v "$ifo_file":/woj/user/"$test_num".info \
git.0x7f.app/woj/ubuntu-run \
sh -c \
"cd /woj/user && /woj/framework/scripts/woj_launcher \
--memory_limit=$Info_Limit_Memory \
--nproc_limit=$Info_Limit_NProc \
--time_limit=$Info_Limit_Time \
--sandbox_path=/woj/framework/scripts/libwoj_sandbox.so \
--sandbox_template=$3 \
--sandbox_action=nothing \
--file_input=/woj/problem/data/input/$test_num.input \
--file_output=/woj/user/$test_num.out.usr \
--file_info=/woj/user/$test_num.info \
--program=/woj/user/$2.out"
done

View File

@ -3,17 +3,17 @@
. common.sh
function docker_run() {
local timeout=${TIMEOUT:-10}
local log_file=${LOG_FILE:-"/dev/stderr"}
local log_limit=${LOG_LIMIT:-4K}
log_info "$DOCKER run with timeout $timeout"
CONTAINER_NAME=$(uuidgen)
(
sleep "$timeout"
$DOCKER kill "$CONTAINER_NAME"
) &
$DOCKER run --rm --name "$CONTAINER_NAME" "$@" 2>&1 | head -c "$log_limit" >"$log_file"
pkill -P $$
$DOCKER kill "$CONTAINER_NAME" >/dev/null 2>&1
return 0
local timeout=${TIMEOUT:-10}
local log_file=${LOG_FILE:-"/dev/stderr"}
local log_limit=${LOG_LIMIT:-4K}
log_info "$DOCKER run with timeout $timeout"
CONTAINER_NAME=$(uuidgen)
(
sleep "$timeout"
$DOCKER kill "$CONTAINER_NAME"
) &
$DOCKER run --rm --name "$CONTAINER_NAME" "$@" 2>&1 | head -c "$log_limit" >"$log_file"
pkill -P $$
$DOCKER kill "$CONTAINER_NAME" >/dev/null 2>&1
return 0
}

View File

@ -0,0 +1,20 @@
FROM docker.io/library/ubuntu:22.04
WORKDIR /woj/
# Install dependencies
RUN apt-get update && apt-get upgrade -y && apt-get install -y gcc g++ clang make cmake autoconf m4 libtool gperf git parallel python3 && apt-get clean && rm -rf /var/lib/apt/lists
# Copy source code
RUN mkdir -p /woj/framework && mkdir -p /woj/problem
COPY framework /woj/framework
# Build
RUN cd /woj/framework/template && ./setup.sh
RUN cd /woj/framework/scripts && ./setup.sh
# Environment
ENV WOJ_LAUNCHER=/woj/framework/scripts/woj_launcher
ENV WOJ_SANDBOX=/woj/framework/scripts/libwoj_sandbox.so
ENV TEMPLATE=/woj/framework/template
ENV TESTLIB=/woj/framework/template/testlib
ENV PREFIX=/woj/problem

View File

@ -0,0 +1,8 @@
FROM woj/ubuntu-full:latest AS builder
FROM docker.io/library/ubuntu:22.04
WORKDIR /woj/problem
RUN mkdir -p /woj/framework/scripts
COPY --from=builder /woj/framework/scripts/libwoj_sandbox.so /woj/framework/scripts/
COPY --from=builder /woj/framework/scripts/woj_launcher /woj/framework/scripts/