Skip to content

Commit

Permalink
feat: artifacts (#422)
Browse files Browse the repository at this point in the history
  • Loading branch information
Topvennie authored May 16, 2024
1 parent 143c994 commit dda6010
Show file tree
Hide file tree
Showing 16 changed files with 156 additions and 34 deletions.
10 changes: 10 additions & 0 deletions backend/api/fixtures/realistic/realistic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
time_limit: 10
memory_limit: 50
show_log: false
show_artifact: false
- model: api.extracheck
pk: 1
fields:
Expand All @@ -182,6 +183,7 @@
time_limit: 30
memory_limit: 128
show_log: true
show_artifact: true

# MARK: Students
- model: api.student
Expand Down Expand Up @@ -457,41 +459,49 @@
fields:
extra_check: 0
log_file: fixtures/realistic/projects/0/0/submissions/0/submission_1/logs/log_extra_check_0.txt
artifact: ""
- model: api.extracheckresult
pk: 3
fields:
extra_check: 1
log_file: fixtures/realistic/projects/0/0/submissions/0/submission_1/logs/log_extra_check_1.txt
artifact: fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_1.zip
- model: api.extracheckresult
pk: 5
fields:
extra_check: 0
log_file: fixtures/realistic/projects/0/0/submissions/0/submission_2/logs/log_extra_check_0.txt
artifact: ""
- model: api.extracheckresult
pk: 6
fields:
extra_check: 1
log_file: fixtures/realistic/projects/0/0/submissions/0/submission_2/logs/log_extra_check_1.txt
artifact: fixtures/realistic/projects/0/0/submissions/0/submission_2/artifacts/artifact_extra_check_1.zip
- model: api.extracheckresult
pk: 8
fields:
extra_check: 0
log_file: ""
artifact: ""
- model: api.extracheckresult
pk: 9
fields:
extra_check: 1
log_file: ""
artifact: ""
- model: api.extracheckresult
pk: 11
fields:
extra_check: 0
log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt
artifact: ""
- model: api.extracheckresult
pk: 12
fields:
extra_check: 1
log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt
artifact: ""

# MARK: Teachers
- model: api.teacher
Expand Down
32 changes: 18 additions & 14 deletions backend/api/locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -34,61 +34,61 @@ msgstr "Docker image is ready"
msgid "dockerimage.state.error"
msgstr "Docker image failed to build"

#: models/submission.py:61
#: models/submission.py:62
msgid "submission.state.queued"
msgstr "Queued"

#: models/submission.py:62
#: models/submission.py:63
msgid "submission.state.running"
msgstr "Running"

#: models/submission.py:63
#: models/submission.py:64
msgid "submission.state.success"
msgstr "Success"

#: models/submission.py:64
#: models/submission.py:65
msgid "submission.state.failed"
msgstr "Failed"

#: models/submission.py:69
#: models/submission.py:70
msgid "submission.error.blockedextension"
msgstr "The zip file contains a file with a non-allowed extension."

#: models/submission.py:70
#: models/submission.py:71
msgid "submission.error.obligatedextensionnotfound"
msgstr ""
"The submitted zip file doesn't have any file with an obligated file "
"extension."

#: models/submission.py:71
#: models/submission.py:72
msgid "submission.error.filedirnotfound"
msgstr "The submitted zip file lacks an obligated directory."

#: models/submission.py:74
#: models/submission.py:75
msgid "submission.error.dockerimageerror"
msgstr "try again later."

#: models/submission.py:75
#: models/submission.py:76
msgid "submission.error.timelimit"
msgstr "Timelimit exceeded."

#: models/submission.py:76
#: models/submission.py:77
msgid "submission.error.memorylimit"
msgstr "Memorylimit exceeded."

#: models/submission.py:77
#: models/submission.py:78
msgid "submission.error.checkerror"
msgstr "A check failed."

#: models/submission.py:78
#: models/submission.py:79
msgid "submission.error.runtimeerror"
msgstr "Crashed."

#: models/submission.py:79
#: models/submission.py:80
msgid "submission.error.unknown"
msgstr "Unkown error."

#: models/submission.py:80
#: models/submission.py:81
msgid "submission.error.failedstructurecheck"
msgstr "The zip file doesn't have the right structure."

Expand Down Expand Up @@ -287,3 +287,7 @@ msgstr "No zip file available."
#: views/submission_view.py:50
msgid "extra_check_result.download.log"
msgstr "No log file available."

#: views/submission_view.py:60
msgid "extra_check_result.download.artifact"
msgstr "No artifact available."
34 changes: 20 additions & 14 deletions backend/api/locale/nl/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -34,61 +34,61 @@ msgstr "Docker image is klaar."
msgid "dockerimage.state.error"
msgstr "Docker image is gefaald om te bouwen."

#: models/submission.py:61
#: models/submission.py:62
msgid "submission.state.queued"
msgstr "wachten"

#: models/submission.py:62
#: models/submission.py:63
msgid "submission.state.running"
msgstr "lopen"

#: models/submission.py:63
#: models/submission.py:64
msgid "submission.state.success"
msgstr "succes"

#: models/submission.py:64
#: models/submission.py:65
msgid "submission.state.failed"
msgstr "gefaald"

#: models/submission.py:69
#: models/submission.py:70
msgid "submission.error.blockedextension"
msgstr "De zip file bevat een niet toegelaten bestandstype."

#: models/submission.py:70
#: models/submission.py:71
msgid "submission.error.obligatedextensionnotfound"
msgstr ""
"Er is geen enkel bestand met een bepaalde bestandstype die verplicht is in "
"het ingediende zip-bestand."

#: models/submission.py:71
#: models/submission.py:72
msgid "submission.error.filedirnotfound"
msgstr "De ingediende zip file mankeerd een verplichtte map."

#: models/submission.py:74
#: models/submission.py:75
msgid "submission.error.dockerimageerror"
msgstr "Probeer later opnieuw."

#: models/submission.py:75
#: models/submission.py:76
msgid "submission.error.timelimit"
msgstr "Tijdslimit bereikt."

#: models/submission.py:76
#: models/submission.py:77
msgid "submission.error.memorylimit"
msgstr "Geheugenlimiet bereikt."

#: models/submission.py:77
#: models/submission.py:78
msgid "submission.error.checkerror"
msgstr "Een check faalde."

#: models/submission.py:78
#: models/submission.py:79
msgid "submission.error.runtimeerror"
msgstr "Crashed."

#: models/submission.py:79
#: models/submission.py:80
msgid "submission.error.unknown"
msgstr "Onbekende fout."

#: models/submission.py:80
#: models/submission.py:81
msgid "submission.error.failedstructurecheck"
msgstr "De ingediende zip file heeft niet de juiste structuur."

Expand Down Expand Up @@ -288,3 +288,9 @@ msgstr "Geen zip bestand beschikbaar."
#: views/submission_view.py:50
msgid "extra_check_result.download.log"
msgstr "Geen log bestand beschikbaar."

#: views/submission_view.py:60
#, fuzzy
#| msgid "extra_check_result.download.log"
msgid "extra_check_result.download.artifact"
msgstr "Geen artifact beschikbaar."
5 changes: 5 additions & 0 deletions backend/api/logic/get_file_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ def get_docker_image_file_path(instance: DockerImage, _: str) -> str:

def get_docker_image_tag(instance: DockerImage) -> str:
return f"{DOCKER_BUILD_ROOT_NAME}_{instance.id}"


def get_extra_check_artifact_file_path(instance: ExtraCheckResult, uuid: str) -> str:
return (f"{_get_project_dir_path(instance.submission.group.project)}"
f"submissions/{instance.submission.group.id}/{uuid}/artifacts/{_get_uuid()}.zip")
24 changes: 24 additions & 0 deletions backend/api/migrations/0025_extracheckresult_artifact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 5.0.4 on 2024-05-13 21:33

from api.logic.get_file_path import get_extra_check_artifact_file_path
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0024_alter_dockerimage_state'),
]

operations = [
migrations.AddField(
model_name='extracheckresult',
name='artifact',
field=models.FileField(max_length=256, null=True, upload_to=get_extra_check_artifact_file_path),
),
migrations.AddField(
model_name='extracheck',
name='show_artifact',
field=models.BooleanField(default=True),
),
]
7 changes: 7 additions & 0 deletions backend/api/models/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,10 @@ class ExtraCheck(models.Model):
blank=False,
null=False
)

# Whether the artifacts should made available to the student
show_artifact = models.BooleanField(
default=True,
blank=False,
null=False
)
11 changes: 10 additions & 1 deletion backend/api/models/submission.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import TYPE_CHECKING

from api.logic.get_file_path import (get_extra_check_log_file_path,
from api.logic.get_file_path import (get_extra_check_artifact_file_path,
get_extra_check_log_file_path,
get_submission_file_path)
from api.models.checks import ExtraCheck, StructureCheck
from api.models.group import Group
Expand Down Expand Up @@ -137,3 +138,11 @@ class ExtraCheckResult(CheckResult):
blank=False,
null=True
)

# File path for the artifact of the extra checks
artifact = models.FileField(
upload_to=get_extra_check_artifact_file_path,
max_length=256,
blank=False,
null=True
)
15 changes: 15 additions & 0 deletions backend/api/permissions/submission_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,18 @@ def has_object_permission(self, request: Request, view: APIView, obj: ExtraCheck
return obj.extra_check.show_log

return True


class ExtraCheckResultArtifactPermission(ExtraCheckResultPermission):
def has_object_permission(self, request: Request, view: APIView, obj: ExtraCheckResult) -> bool:
result = super().has_object_permission(request, view, obj)

if not result:
return False

user: User = cast(User, request.user)

if is_student(user):
return obj.extra_check.show_artifact

return True
3 changes: 3 additions & 0 deletions backend/api/serializers/submission_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ def to_representation(self, instance: ExtraCheckResult) -> dict | None:
representation["log_file"] = request.build_absolute_uri(
reverse("extra-check-result-detail", args=[str(instance.id)]) + "log/"
)
representation["artifact"] = request.build_absolute_uri(
reverse("extra-check-result-detail", args=[str(instance.id)]) + "artifact/"
)
return representation

return None
Expand Down
Loading

0 comments on commit dda6010

Please sign in to comment.