Skip to content

Commit

Permalink
Allow release file reuploads to different workspaces
Browse files Browse the repository at this point in the history
Reuploads of the same release file (with same filename and same
content) are prohibited. However, a file  with the same name/content
may legitimately be reuploaded to a different workspace. Update the
check for already uploaded files to check for the same filename/content
within the target workspace only.
  • Loading branch information
rebkwok committed Jan 14, 2025
1 parent 1fbe102 commit d3912b6
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
9 changes: 5 additions & 4 deletions jobserver/releases.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,24 @@ def build_outputs_zip(release_files, url_builder_func):
return in_memory_zf


def check_not_already_uploaded(filename, filehash, backend):
"""Check if this filename/filehash combination has been uploaded before."""
def check_not_already_uploaded(workspace, filename, filehash, backend):
"""Check if this workspace/filename/filehash combination has been uploaded before."""
duplicate = ReleaseFile.objects.filter(
release__backend=backend,
workspace=workspace,
name=filename,
filehash=filehash,
)
if duplicate.exists():
raise ReleaseFileAlreadyExists(
f"This version of '{filename}' has already been uploaded from backend '{backend.slug}'"
f"This version of '{filename}' in workspace {workspace} has already been uploaded from backend '{backend.slug}'"
)


@transaction.atomic
def create_release(workspace, backend, created_by, requested_files, **kwargs):
for f in requested_files:
check_not_already_uploaded(f["name"], f["sha256"], backend)
check_not_already_uploaded(workspace, f["name"], f["sha256"], backend)

release = Release.objects.create(
workspace=workspace,
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/jobserver/api/test_releases.py
Original file line number Diff line number Diff line change
Expand Up @@ -818,10 +818,10 @@ def test_releaseworkspaceapi_post_create_release_with_oversized_file(

def test_releaseworkspaceapi_post_release_already_exists(api_rf, project_membership):
user = UserFactory(roles=[OutputChecker])

release = ReleaseFactory()
rfile = ReleaseFileFactory(
release=release,
workspace=release.workspace,
created_by=user,
name="file.txt",
filehash="hash",
Expand Down
38 changes: 35 additions & 3 deletions tests/unit/jobserver/test_releases.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def test_build_outputs_zip_with_missing_files(build_release_with_files):


def test_create_release_reupload():
rfile = ReleaseFileFactory(name="file1.txt", filehash="hash")
workspace = WorkspaceFactory(name="workspace")
rfile = ReleaseFileFactory(workspace=workspace, name="file1.txt", filehash="hash")

files = [
{
Expand All @@ -93,20 +94,51 @@ def test_create_release_reupload():
"url": "",
"size": 4,
"sha256": "hash",
"mtime": "2022-08-17T13:37Z",
"date": "2022-08-17T13:37Z",
"metadata": {},
}
]

with pytest.raises(releases.ReleaseFileAlreadyExists):
releases.create_release(
rfile.release.workspace,
workspace,
rfile.release.backend,
rfile.release.created_by,
files,
)


def test_create_release_reupload_to_different_workspace():
workspace = WorkspaceFactory(name="workspace")
another_workspace = WorkspaceFactory(name="another_workspace")
rfile = ReleaseFileFactory(workspace=workspace, name="file1.txt", filehash="hash")

files = [
{
"name": "file1.txt",
"path": "path/to/file1.txt",
"url": "",
"size": 4,
"sha256": "hash",
"date": "2022-08-17T13:37Z",
"metadata": {},
}
]

release = releases.create_release(
another_workspace,
rfile.release.backend,
rfile.release.created_by,
files,
)
assert release.requested_files == files
assert release.files.count() == 1

rfile = release.files.first()
rfile.filehash == "hash"
rfile.size == 4


def test_create_release_success():
backend = BackendFactory()
workspace = WorkspaceFactory()
Expand Down

0 comments on commit d3912b6

Please sign in to comment.