-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement actions artifacts (#22738)
Implement action artifacts server api. This change is used for supporting https://github.com/actions/upload-artifact and https://github.com/actions/download-artifact in gitea actions. It can run sample workflow from doc https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts. The api design is inspired by https://github.com/nektos/act/blob/master/pkg/artifacts/server.go and includes some changes from gitea internal structs and methods. Actions artifacts contains two parts: - Gitea server api and storage (this pr implement basic design without some complex cases supports) - Runner communicate with gitea server api (in comming) Old pr #22345 is outdated after actions merged. I create new pr from main branch. ![897f7694-3e0f-4f7c-bb4b-9936624ead45](https://user-images.githubusercontent.com/2142787/219382371-eb3cf810-e4e0-456b-a8ff-aecc2b1a1032.jpeg) Add artifacts list in actions workflow page.
- Loading branch information
Showing
24 changed files
with
1,127 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
// This artifact server is inspired by https://github.com/nektos/act/blob/master/pkg/artifacts/server.go. | ||
// It updates url setting and uses ObjectStore to handle artifacts persistence. | ||
|
||
package actions | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
|
||
"code.gitea.io/gitea/models/db" | ||
"code.gitea.io/gitea/modules/timeutil" | ||
"code.gitea.io/gitea/modules/util" | ||
) | ||
|
||
const ( | ||
// ArtifactStatusUploadPending is the status of an artifact upload that is pending | ||
ArtifactStatusUploadPending = 1 | ||
// ArtifactStatusUploadConfirmed is the status of an artifact upload that is confirmed | ||
ArtifactStatusUploadConfirmed = 2 | ||
// ArtifactStatusUploadError is the status of an artifact upload that is errored | ||
ArtifactStatusUploadError = 3 | ||
) | ||
|
||
func init() { | ||
db.RegisterModel(new(ActionArtifact)) | ||
} | ||
|
||
// ActionArtifact is a file that is stored in the artifact storage. | ||
type ActionArtifact struct { | ||
ID int64 `xorm:"pk autoincr"` | ||
RunID int64 `xorm:"index UNIQUE(runid_name)"` // The run id of the artifact | ||
RunnerID int64 | ||
RepoID int64 `xorm:"index"` | ||
OwnerID int64 | ||
CommitSHA string | ||
StoragePath string // The path to the artifact in the storage | ||
FileSize int64 // The size of the artifact in bytes | ||
FileCompressedSize int64 // The size of the artifact in bytes after gzip compression | ||
ContentEncoding string // The content encoding of the artifact | ||
ArtifactPath string // The path to the artifact when runner uploads it | ||
ArtifactName string `xorm:"UNIQUE(runid_name)"` // The name of the artifact when runner uploads it | ||
Status int64 `xorm:"index"` // The status of the artifact, uploading, expired or need-delete | ||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | ||
UpdatedUnix timeutil.TimeStamp `xorm:"updated index"` | ||
} | ||
|
||
// CreateArtifact create a new artifact with task info or get same named artifact in the same run | ||
func CreateArtifact(ctx context.Context, t *ActionTask, artifactName string) (*ActionArtifact, error) { | ||
if err := t.LoadJob(ctx); err != nil { | ||
return nil, err | ||
} | ||
artifact, err := getArtifactByArtifactName(ctx, t.Job.RunID, artifactName) | ||
if errors.Is(err, util.ErrNotExist) { | ||
artifact := &ActionArtifact{ | ||
RunID: t.Job.RunID, | ||
RunnerID: t.RunnerID, | ||
RepoID: t.RepoID, | ||
OwnerID: t.OwnerID, | ||
CommitSHA: t.CommitSHA, | ||
Status: ArtifactStatusUploadPending, | ||
} | ||
if _, err := db.GetEngine(ctx).Insert(artifact); err != nil { | ||
return nil, err | ||
} | ||
return artifact, nil | ||
} else if err != nil { | ||
return nil, err | ||
} | ||
return artifact, nil | ||
} | ||
|
||
func getArtifactByArtifactName(ctx context.Context, runID int64, name string) (*ActionArtifact, error) { | ||
var art ActionArtifact | ||
has, err := db.GetEngine(ctx).Where("run_id = ? AND artifact_name = ?", runID, name).Get(&art) | ||
if err != nil { | ||
return nil, err | ||
} else if !has { | ||
return nil, util.ErrNotExist | ||
} | ||
return &art, nil | ||
} | ||
|
||
// GetArtifactByID returns an artifact by id | ||
func GetArtifactByID(ctx context.Context, id int64) (*ActionArtifact, error) { | ||
var art ActionArtifact | ||
has, err := db.GetEngine(ctx).ID(id).Get(&art) | ||
if err != nil { | ||
return nil, err | ||
} else if !has { | ||
return nil, util.ErrNotExist | ||
} | ||
|
||
return &art, nil | ||
} | ||
|
||
// UpdateArtifactByID updates an artifact by id | ||
func UpdateArtifactByID(ctx context.Context, id int64, art *ActionArtifact) error { | ||
art.ID = id | ||
_, err := db.GetEngine(ctx).ID(id).AllCols().Update(art) | ||
return err | ||
} | ||
|
||
// ListArtifactsByRunID returns all artifacts of a run | ||
func ListArtifactsByRunID(ctx context.Context, runID int64) ([]*ActionArtifact, error) { | ||
arts := make([]*ActionArtifact, 0, 10) | ||
return arts, db.GetEngine(ctx).Where("run_id=?", runID).Find(&arts) | ||
} | ||
|
||
// ListUploadedArtifactsByRunID returns all uploaded artifacts of a run | ||
func ListUploadedArtifactsByRunID(ctx context.Context, runID int64) ([]*ActionArtifact, error) { | ||
arts := make([]*ActionArtifact, 0, 10) | ||
return arts, db.GetEngine(ctx).Where("run_id=? AND status=?", runID, ArtifactStatusUploadConfirmed).Find(&arts) | ||
} | ||
|
||
// ListArtifactsByRepoID returns all artifacts of a repo | ||
func ListArtifactsByRepoID(ctx context.Context, repoID int64) ([]*ActionArtifact, error) { | ||
arts := make([]*ActionArtifact, 0, 10) | ||
return arts, db.GetEngine(ctx).Where("repo_id=?", repoID).Find(&arts) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
- | ||
id: 791 | ||
title: "update actions" | ||
repo_id: 4 | ||
owner_id: 1 | ||
workflow_id: "artifact.yaml" | ||
index: 187 | ||
trigger_user_id: 1 | ||
ref: "refs/heads/master" | ||
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" | ||
event: "push" | ||
is_fork_pull_request: 0 | ||
status: 1 | ||
started: 1683636528 | ||
stopped: 1683636626 | ||
created: 1683636108 | ||
updated: 1683636626 | ||
need_approval: 0 | ||
approved_by: 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
- | ||
id: 192 | ||
run_id: 791 | ||
repo_id: 4 | ||
owner_id: 1 | ||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 | ||
is_fork_pull_request: 0 | ||
name: job_2 | ||
attempt: 1 | ||
job_id: job_2 | ||
task_id: 47 | ||
status: 1 | ||
started: 1683636528 | ||
stopped: 1683636626 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
- | ||
id: 47 | ||
job_id: 192 | ||
attempt: 3 | ||
runner_id: 1 | ||
status: 6 # 6 is the status code for "running", running task can upload artifacts | ||
started: 1683636528 | ||
stopped: 1683636626 | ||
repo_id: 4 | ||
owner_id: 1 | ||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 | ||
is_fork_pull_request: 0 | ||
token_hash: 6d8ef48297195edcc8e22c70b3020eaa06c52976db67d39b4260c64a69a2cc1508825121b7b8394e48e00b1bf8718b2a867e | ||
token_salt: jVuKnSPGgy | ||
token_last_eight: eeb1a71a | ||
log_filename: artifact-test2/2f/47.log | ||
log_in_storage: 1 | ||
log_length: 707 | ||
log_size: 90179 | ||
log_expired: 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package v1_20 //nolint | ||
|
||
import ( | ||
"code.gitea.io/gitea/modules/timeutil" | ||
|
||
"xorm.io/xorm" | ||
) | ||
|
||
func CreateActionArtifactTable(x *xorm.Engine) error { | ||
// ActionArtifact is a file that is stored in the artifact storage. | ||
type ActionArtifact struct { | ||
ID int64 `xorm:"pk autoincr"` | ||
RunID int64 `xorm:"index UNIQUE(runid_name)"` // The run id of the artifact | ||
RunnerID int64 | ||
RepoID int64 `xorm:"index"` | ||
OwnerID int64 | ||
CommitSHA string | ||
StoragePath string // The path to the artifact in the storage | ||
FileSize int64 // The size of the artifact in bytes | ||
FileCompressedSize int64 // The size of the artifact in bytes after gzip compression | ||
ContentEncoding string // The content encoding of the artifact | ||
ArtifactPath string // The path to the artifact when runner uploads it | ||
ArtifactName string `xorm:"UNIQUE(runid_name)"` // The name of the artifact when runner uploads it | ||
Status int64 `xorm:"index"` // The status of the artifact | ||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | ||
UpdatedUnix timeutil.TimeStamp `xorm:"updated index"` | ||
} | ||
|
||
return x.Sync(new(ActionArtifact)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.