Skip to content

fix(actions): preserve created_unix when re-uploading an expired artifact#38296

Open
bircni wants to merge 2 commits into
go-gitea:mainfrom
bircni:fix/artifact-createdunix
Open

fix(actions): preserve created_unix when re-uploading an expired artifact#38296
bircni wants to merge 2 commits into
go-gitea:mainfrom
bircni:fix/artifact-createdunix

Conversation

@bircni

@bircni bircni commented Jul 1, 2026

Copy link
Copy Markdown
Member

When a workflow re-uploads an artifact whose previous content had already
expired (and whose storage blob was removed by the cleanup job), CreateArtifact
revives the existing DB row as a fresh pending upload. This PR fixes two problems
in that path and adds test coverage.

1. Revive path resets status/storage but leaves stale content pointers

Previously, a matching row in a terminal state (Expired / PendingDeletion /
Deleted) was "revived" by only bumping expired_unix. That left the row stuck
in its terminal status while still pointing at a StoragePath/FileSize that no
longer correspond to any content. A re-upload now reinitializes the row in place
as a brand-new UploadPending record (the unique index on
run_id/run_attempt_id/name/path requires updating the existing row rather than
inserting a second one).

2. created_unix was being clobbered on every re-upload

The revive path returned a struct whose CreatedUnix was 0. Both callers hand
that returned struct straight to UpdateArtifactByID, which uses AllCols()
so the zero value overwrote the row's original creation timestamp. The fix
carries existing.CreatedUnix onto the returned struct so the subsequent
AllCols() update preserves it.

Why

Re-running a job after its artifact expired is a normal case. Without this fix
the artifact row keeps a dead status and stale storage pointers, and its
created_unix gets reset to "now" on every re-upload.

@bircni bircni added this to the 28.0 milestone Jul 1, 2026
@bircni bircni requested a review from Zettat123 July 1, 2026 10:12
@bircni bircni added the backport/v1.27 This PR should be backported to Gitea 1.26 label Jul 1, 2026
@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Jul 1, 2026
@lunny

lunny commented Jul 1, 2026

Copy link
Copy Markdown
Member

When and why a re-upload was allowed?

@bircni

bircni commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

When and why a re-upload was allowed?

On a rerun of a job...

@lunny

lunny commented Jul 1, 2026

Copy link
Copy Markdown
Member

When and why a re-upload was allowed?

On a rerun of a job...

Wouldn’t there be a job attempt ID to prevent them from overriding each other?

@bircni

bircni commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

When and why a re-upload was allowed?

On a rerun of a job...

Wouldn’t there be a job attempt ID to prevent them from overriding each other?

Reruns don't override each other — cloneRunJobForAttempt assigns a new RunAttemptID, and the unique key includes run_attempt_id, so each attempt gets its own row. The re-upload this fixes is within the same run+attempt: upload-artifact@v4 with overwrite: true deletes the artifact (SetArtifactNeedDeleteByRunAttemptPendingDeletion) and then re-creates the same name/path. The old code revived that dead row by only bumping expired_unix, leaving it in a terminal status pointing at a deleted blob. IsTerminal() catches that and reinitializes it as a fresh pending upload instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/v1.27 This PR should be backported to Gitea 1.26 lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. type/bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants