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
6 changes: 6 additions & 0 deletions container-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ services:
dockerfile: Containerfile
additional_contexts:
- watcher_source=./watcher
- denis_source=./denis
volumes:
- type: volume
source: email-mail
Expand All @@ -133,12 +134,17 @@ services:
source: email-logs
target: /var/lib/email/logs
read_only: true
- type: volume
source: denis-db
target: /var/lib/denis
read_only: true
- type: volume
source: submissions-db
target: /var/lib/mailman
read_only: false
depends_on:
- smtp
- denis
networks:
- mailman
denis:
Expand Down
1 change: 1 addition & 0 deletions mailman/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ RUN mkdir -p /var/lib/mailman/ && \
RUN chown -R 100:100 /var/lib/mailman

COPY --from=build /watcher/watcher /usr/local/bin/watcher
COPY --from=denis_source . ./denis

VOLUME /var/lib/email/

Expand Down
5 changes: 3 additions & 2 deletions mailman/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ class Meta:

class Submission(BaseModel):
submission_id = peewee.TextField(unique=True)
assignment = peewee.TextField()
timestamp = peewee.IntegerField()
user = peewee.TextField()
status = peewee.TextField()
recipient = peewee.TextField()
email_count = peewee.IntegerField()
in_reply_to = peewee.TextField(null=True)


if __name__ == '__main__':
Expand Down
57 changes: 20 additions & 37 deletions mailman/submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@
from pathlib import Path
import sys

import patchset
import db

ASSIGNMENT_LIST = ["introductions",
"exercise0", "exercise1", "exercise2",
"programming0", "programming1", "programming2",
"final0", "final1"]


Email = collections.namedtuple('Email', ['rcpt', 'msg_id'])

Expand All @@ -35,37 +29,26 @@ def main(argv):
if not emails:
return 0

cover_letter, *patches = emails

# if the 'cover letter' is not addressed to
# an assignment inbox, this email session
# isn't a patchset at all
if cover_letter.rcpt not in ASSIGNMENT_LIST:
# TODO process peer review
return 0

sub = db.Submission(submission_id=logfile, assignment=cover_letter.rcpt,
timestamp=timestamp, user=user, status='new')

# only one email
if not patches:
# only one patch, but addressed to an
# assignment inbox. This cannot be valid.
sub.status = 'no patches or no cover letter'
sub.save()
return 0

mis_addressed_patches = [str(i+1) for i, patch in enumerate(patches)
if patch.rcpt != cover_letter.rcpt]

if mis_addressed_patches:
sub.status = (f'patch(es) {",".join(mis_addressed_patches)} '
f'not addressed to {cover_letter.rcpt}')
sub.save()
return 0

sub.status = patchset.check(cover_letter, patches, submission_id=logfile)
sub.save()
irt_header = 'In-Reply-To: <'
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 not line.startswith(irt_header):
continue
at_sign = line.find('@', len(irt_header))
if -1 == at_sign:
continue
reply_email_id = line[len(irt_header):at_sign]

# "clear the lower 16 bits" to get the reviewee patchset id
reply_id = reply_email_id[:-4] + '0000'
break

db.Submission.create(submission_id=logfile, timestamp=timestamp,
user=user, recipient=emails[0].rcpt,
email_count=len(emails), in_reply_to=reply_id)


if __name__ == "__main__":
Expand Down
5 changes: 3 additions & 2 deletions orbit/radius.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,15 +389,16 @@ def handle_dashboard(rocket):

def submission_fields(sub):
return (datetime.fromtimestamp(sub.timestamp).isoformat(),
sub.assignment, sub.submission_id, sub.status)
sub.recipient, sub.email_count, sub.in_reply_to or '-',
sub.submission_id, )

# Split data from Submission table into values for HTML table
table_data = [[f'<td>{val}</td>' for val in submission_fields(sub)]
for sub in submissions]
table_content = '</tr>\n<tr>'.join(''.join(row) for row in table_data)

return rocket.respond(f"""<table>
<tr><th>Timestamp</th><th>Assignment</th><th>Submission ID</th><th>Status</th></tr>
<tr><th>Timestamp</th><th>Recipient</th><th>Email Count</th><th>In Reply To</th><th>Submission ID</th></tr>
<tr>{table_content}</tr>
</table>
""")
Expand Down