Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ RUN dnf update -y && \
python-flake8 \
python-virtualenv \
python-pip \
git
socat \
git \
git-email

# needed because for some reason newuidmap and newgidmap programs
# lose their xattrs giving them caps when the container image for
Expand Down
4 changes: 2 additions & 2 deletions denis/final.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

utilities.release_subs([sub.submission_id for sub in usernames_to_subs.values() if sub])

print(f'final subs for {assignment} released')

tags = utilities.update_tags(assignment, 'final')

utilities.run_automated_checks(tags, usernames_to_subs)

print(f'completed {assignment} assignment processing for final submission deadline')
4 changes: 2 additions & 2 deletions denis/initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@

utilities.release_subs([sub.submission_id for sub in usernames_to_subs.values() if sub])

print(f'initial subs for {assignment} released')

tags = utilities.update_tags(assignment, 'initial')

utilities.run_automated_checks(tags, usernames_to_subs)

print(f'completed {assignment} assignment processing for initial submission deadline')
4 changes: 2 additions & 2 deletions denis/peer_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

utilities.release_subs(ids)

print(f'peer review subs for {assignment} released')

tags1 = utilities.update_tags(assignment, 'review1')
tags2 = utilities.update_tags(assignment, 'review2')

utilities.run_automated_checks(tags1 + tags2, usernames_to_subs_review1 | usernames_to_subs_review2, peer=True)

print(f'completed {assignment} assignment processing for peer review submission deadline')
16 changes: 10 additions & 6 deletions mailman/patchset.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,24 @@ def tag_and_push(repo, tag_name, msg=None):
'am', '--keep']


def silent_execute(repo, args):
repo.git.execute(args, with_extended_output=False)


def do_check(repo, cover_letter, patches):
whitespace_errors = []

def am_cover_letter(keep_empty=True):
args = git_am_args.copy()
if keep_empty:
args.append("--empty=keep")
repo.git.execute([*args, str(maildir/cover_letter.msg_id)])
silent_execute(repo, [*args, str(maildir/cover_letter.msg_id)])

if try_or_false(lambda: am_cover_letter(keep_empty=False),
git.GitCommandError):
return "missing cover letter!"

repo.git.execute(["git", "am", "--abort"])
silent_execute(repo, ["git", "am", "--abort"])
if not try_or_false(lambda: am_cover_letter(keep_empty=True),
git.GitCommandError):
return ("missing cover letter and "
Expand Down Expand Up @@ -84,7 +88,7 @@ def am_cover_letter(keep_empty=True):

# Try and apply and fail if there are whitespace errors
def do_git_am(extra_args=[]):
repo.git.execute([*git_am_args, *extra_args, patch_abspath]),
silent_execute(repo, [*git_am_args, *extra_args, patch_abspath])

# if a patch is adding a single file whose name ends with .patch don't bother checking for whitespace errors
if dot_patch_hunks == 1 and other_hunks == 0:
Expand All @@ -98,7 +102,7 @@ def do_git_am(extra_args=[]):
git.GitCommandError):
continue

repo.git.execute(["git", "am", "--abort"])
silent_execute(repo, ["git", "am", "--abort"])

# Try again, if we succeed, count this patch as a whitespace error
if try_or_false(lambda: do_git_am(), git.GitCommandError):
Expand All @@ -125,7 +129,7 @@ def check(cover_letter, patches, submission_id):
if auto_feedback[-1] == '!':
for patch in patches:
patch_abspath = str(maildir / patch.msg_id)
repo.git.execute(['git', 'commit', '--allow-empty', '-F', patch_abspath])
silent_execute(repo, ['git', 'commit', '--allow-empty', '-F', patch_abspath])
tag_and_push(repo, submission_id, msg=auto_feedback)
return auto_feedback

Expand All @@ -145,7 +149,7 @@ def apply_peer_review(email, submission_id, review_id):
with repo.config_writer() as config:
config.set_value('user', 'name', 'mailman')
config.set_value('user', 'email', 'mailman@mailman')
repo.git.execute([*args, patch_abspath])
silent_execute(repo, [*args, patch_abspath])
tag_and_push(repo, submission_id)
except git.GitCommandError as e:
print(e, file=sys.stderr)
Expand Down
5 changes: 5 additions & 0 deletions mailman/submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@ def main(argv):
sub.save()

irt_header = 'In-Reply-To: <'
sender_msg_id_header = 'X-KDLP-Orig-Message-ID: <'
sender_msg_id = None
reply_id = None
with open(f'/var/lib/email/mail/{emails[0].msg_id}') as f:
for line in f:
if not line:
break
if line.startswith(sender_msg_id_header):
sender_msg_id = line.removeprefix('X-KDLP-Orig-')
if not line.startswith(irt_header):
continue
at_sign = line.find('@', len(irt_header))
Expand All @@ -59,6 +63,7 @@ def main(argv):
def set_status(status):
sub.status = status
sub.save()
print(f'finished processing {sender_msg_id}')
return 0

asn_db = denis.db.Assignment
Expand Down
10 changes: 7 additions & 3 deletions script-lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ set -ex

shellcheck start.sh
shellcheck dev_sockets.sh

# -x needed to make shellcheck follow `source` command
shellcheck script-lint.sh
shellcheck test.sh
shellcheck -x test.sh
shellcheck -x test-sub1.sh
shellcheck -x test-sub2.sh
shellcheck -x test-sub3.sh
shellcheck orbit/warpdrive.sh
shellcheck orbit/start.sh
shellcheck denis/configure.sh
Expand All @@ -20,8 +25,7 @@ shellcheck git/cgi-bin/git-receive-pack
shellcheck git/hooks/post-update
shellcheck daily_backup.sh

# -x needed to make shellcheck follow `source` command
shellcheck -x backup/backup.sh
shellcheck -x backup/restore.sh

test "$(git ls-tree -r HEAD | grep -c '.*\.sh$')" -eq "14" || (echo "New script detected. Does it need to be added to script-lint?" && false)
test "$(git ls-tree -r HEAD | grep -c '.*\.sh$')" -eq "17" || (echo "New script detected. Does it need to be added to script-lint?" && false)
20 changes: 12 additions & 8 deletions start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ trap 'podman-compose down -v' EXIT

# wait until synapse is done initializing
podman-compose logs -f submatrix 2>&1 | sed '/Synapse now listening on TCP port 8008/ q'
if [ -f test.sh ]
then
./test.sh
else
virtualenv .
pip install -r requirements.txt
pytest
fi
./test.sh
podman-compose down -v
podman-compose up -d
podman-compose logs -f submatrix 2>&1 | sed '/Synapse now listening on TCP port 8008/ q'
./dev_sockets.sh &
./test-sub1.sh
podman-compose down -v
podman-compose up -d
./test-sub2.sh
podman-compose down -v
podman-compose up -d
./test-sub3.sh
195 changes: 195 additions & 0 deletions test-lib
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# This line:
# - aborts the script after any pipeline returns nonzero (e)
# - shows all commands as they are run (x)
# - sets any dereference of an unset variable to trigger an error (u)
# - enables job control (m)
# - causes the return value of a pipeline to be the nonzero return value
# of the furthest right failing command or zero if no command failed (o pipefail)
set -exumo pipefail

PODMAN=${PODMAN:-podman}
PODMAN_COMPOSE=${PODMAN_COMPOSE:-podman-compose}
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
WORKDIR=$(mktemp -d)

PINP_CONFIG='-c user.name=PINP -c user.email=podman@podman'

HOSTNAME_FROM_DOTENV="$(sh -c '
set -o allexport
. ./.env
exec jq -r -n "env.SINGULARITY_HOSTNAME"
')"

SINGULARITY_HOSTNAME=${SINGULARITY_HOSTNAME:-"${HOSTNAME_FROM_DOTENV}"}

setup_testdir() {
# Create test dir if it does not exist yet
mkdir -p test

# Reset the test directory
rm -f test/*

# put the cert in there
${PODMAN} cp singularity_nginx_1:/etc/ssl/nginx/fullchain.pem test/ca_cert.pem
}

CURL_OPTS=( \
--verbose \
--cacert test/ca_cert.pem \
--fail \
--no-progress-meter \
)


get_git_port() { pushd "$SCRIPT_DIR" > /dev/null ; podman-compose port git 8000 ; popd > /dev/null ; } ;

# preconditions:
# - SCRIPT_DIR defined (singularity repo root)
# - WORKDIR defined (arbitrary) temp directory
setup_submissions_and_grading_repo() {
pushd "$SCRIPT_DIR"
# crete and push fresh submissions repo
rm -rf repos/submissions
git/admin.sh submissions "course submissions repository"
pushd repos
git init --bare submissions
echo "course submissions repository" > submissions/description
# create a temporary workdir to push an initial commit to the submission repo
git init submissions_init
pushd submissions_init
echo "# submissions" > README.md
git add README.md
git status
git -c user.name=singularity -c user.email=singularity@singularity commit -sm 'init submissions repo'
git push ../submissions master
popd
rm -rf submissions_init
pushd submissions
git push --mirror http://localhost:"$(get_git_port)"/cgi-bin/git-receive-pack/submissions
popd
popd
popd

pushd "$WORKDIR"
mkdir certs
pushd certs
${PODMAN} volume export singularity_ssl-certs > certs.tar
tar xf certs.tar
popd
git clone http://localhost:"$(get_git_port)"/submissions
popd
}

# create or recreate dummy assignment
create_dummy_assignment() {
test -n "$1"
local asn="$1"

pushd "$SCRIPT_DIR"
if denis/configure.sh dump | grep -q "^$asn:"; then
denis/configure.sh remove -a "$asn"
fi
denis/configure.sh dummy -a "$asn"
popd
}

# create or recreate dummy assignment
trigger_deadline() {
test -n "$1"
test -n "$2"
local asn="$1"
local cmp="$2"

pushd "$SCRIPT_DIR"
denis/configure.sh trigger -a "$asn" -c "$cmp"
if [ "$cmp" == "peer" ]; then
cmp="$cmp review"
fi
podman-compose logs -f denis | ( sed "/completed $asn assignment processing for $cmp submission deadline/ q" && kill 0 ) || true
popd
}

# preconditions:
# - called after setup_submissions_and_grading_repo
setup_submissions_for() {
test -n "$1"
local user="$1"

pushd "$SCRIPT_DIR"
orbit/warpdrive.sh -u "$user" -p builder -n || orbit/warpdrive.sh -u "$user" -p builder -m
popd

pushd "$WORKDIR"/submissions
git config user.name "$user"
git config user.email "$user"@localhost.localdomain
git config sendemail.smtpUser "$user"
git config sendemail.smtpPass builder
git config sendemail.smtpserver localhost.localdomain
git config sendemail.smtpserverport 1465
git config sendemail.smtpencryption ssl
popd
}

# preconditions:
# - no non-tracked files in submissions repo
# - called after setup_submissions_for
enter_and_checkout() {
test -n "$1"
local branch="$1"

pushd "$WORKDIR"/submissions
git checkout --orphan "$1"
if [ -n "$(ls)" ]
then
git rm -rf ./*
fi
}

# preconditions:
# - called after a call to enter_and_checkout
exit_after_sending() {
test -n "$1"
local asn="$1"

git send-email \
--confirm=never \
--smtp-ssl-cert-path="$WORKDIR"/certs/fullchain.pem \
--to "$asn"@localhost.localdomain \
./*.patch | tee "$WORKDIR"/last_email
last_id=$(grep -m 1 "Message-ID" "$WORKDIR"/last_email)
rm ./*.patch
popd
podman-compose logs -f mailman | ( sed "/finished processing $last_id/ q" && kill 0 ) || true
}

# preconditions:
# - called after a call to enter_and_checkout
write_commit_to() {
test -n "$1" && test -n "$2"
local content="$1"
local file="$2"
set +u # necessary since $3 is unbound in 2 arg case
local opt="$3"
set -x

mkdir -p $(dirname "$file")

if [ "$opt" == "append" ]; then
echo "$content" >> "$file"
else
echo "$content" > "$file"
fi

git add "$file"
git commit -sm "add $content to $file"
}

# preconditions:
# - called after a call to write_commit_to
fixup_cover() {
test -n "$1"
sed -i "s/\*\*\* SUBJECT HERE \*\*\*/$1/g" *0000-cover-letter.patch
sed -i "s/\*\*\* BLURB HERE \*\*\*/$1/g" *0000-cover-letter.patch
sed -i "\$a\\Signed-off-by: $(git config user.name) <$(git config user.email)>" *0000-cover-letter.patch
}

Loading