This commit is contained in:
@@ -8,14 +8,14 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
db "code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
db "gitea.dev/models/db"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unit"
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -116,12 +116,12 @@ func TestToActionWorkflowRun_UsesTriggerEvent(t *testing.T) {
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 803})
|
||||
|
||||
run.Repo = repo
|
||||
// Scheduled runs keep Event as the registration event (push) and use TriggerEvent as the real trigger.
|
||||
run.Event = "push"
|
||||
run.TriggerEvent = "schedule"
|
||||
|
||||
apiRun, err := ToActionWorkflowRun(t.Context(), repo, run)
|
||||
apiRun, err := ToActionWorkflowRun(t.Context(), run, nil, false)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "schedule", apiRun.Event)
|
||||
}
|
||||
@@ -177,3 +177,13 @@ func TestToActionWorkflowJob_StepStatusIsIndependentOfJobStatus(t *testing.T) {
|
||||
assert.Equal(t, "completed", apiJob.Steps[1].Status, "step 1 status")
|
||||
assert.Equal(t, "failure", apiJob.Steps[1].Conclusion, "step 1 conclusion")
|
||||
}
|
||||
|
||||
func TestToActionsStatus_Cancelling(t *testing.T) {
|
||||
action, conclusion := ToActionsStatus(actions_model.StatusCancelling)
|
||||
assert.Equal(t, "in_progress", action)
|
||||
assert.Empty(t, conclusion)
|
||||
}
|
||||
|
||||
func TestToWorkflowRunAction_Cancelling(t *testing.T) {
|
||||
assert.Equal(t, "in_progress", ToWorkflowRunAction(actions_model.StatusCancelling))
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ package convert
|
||||
import (
|
||||
"context"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
perm_model "code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
activities_model "gitea.dev/models/activities"
|
||||
perm_model "gitea.dev/models/perm"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/log"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_model.User) *api.Activity {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
func WebAssetDownloadURL(repo *repo_model.Repository, attach *repo_model.Attachment) string {
|
||||
|
||||
@@ -5,39 +5,40 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
"code.gitea.io/gitea/services/gitdiff"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/nektos/act/pkg/model"
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
asymkey_model "gitea.dev/models/asymkey"
|
||||
"gitea.dev/models/auth"
|
||||
"gitea.dev/models/db"
|
||||
git_model "gitea.dev/models/git"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
"gitea.dev/models/organization"
|
||||
"gitea.dev/models/perm"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unit"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/actions"
|
||||
"gitea.dev/modules/actions/jobparser"
|
||||
"gitea.dev/modules/container"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/gitrepo"
|
||||
"gitea.dev/modules/httplib"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/setting"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/util"
|
||||
webhook_module "gitea.dev/modules/webhook"
|
||||
asymkey_service "gitea.dev/services/asymkey"
|
||||
"gitea.dev/services/gitdiff"
|
||||
)
|
||||
|
||||
// ToEmail convert models.EmailAddress to api.Email
|
||||
@@ -139,7 +140,7 @@ func getWhitelistEntities[T *user_model.User | *organization.Team](entities []T,
|
||||
|
||||
// ToBranchProtection convert a ProtectedBranch to api.BranchProtection
|
||||
func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo *repo_model.Repository) *api.BranchProtection {
|
||||
readers, err := access_model.GetUsersWithUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypePullRequests)
|
||||
readers, err := access_model.GetUsersWithAnyUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests)
|
||||
if err != nil {
|
||||
log.Error("GetRepoReaders: %v", err)
|
||||
}
|
||||
@@ -148,6 +149,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
|
||||
forcePushAllowlistUsernames := getWhitelistEntities(readers, bp.ForcePushAllowlistUserIDs)
|
||||
mergeWhitelistUsernames := getWhitelistEntities(readers, bp.MergeWhitelistUserIDs)
|
||||
approvalsWhitelistUsernames := getWhitelistEntities(readers, bp.ApprovalsWhitelistUserIDs)
|
||||
bypassAllowlistUsernames := getWhitelistEntities(readers, bp.BypassAllowlistUserIDs)
|
||||
|
||||
teamReaders, err := organization.GetTeamsWithAccessToAnyRepoUnit(ctx, repo.Owner.ID, repo.ID, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests)
|
||||
if err != nil {
|
||||
@@ -158,6 +160,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
|
||||
forcePushAllowlistTeams := getWhitelistEntities(teamReaders, bp.ForcePushAllowlistTeamIDs)
|
||||
mergeWhitelistTeams := getWhitelistEntities(teamReaders, bp.MergeWhitelistTeamIDs)
|
||||
approvalsWhitelistTeams := getWhitelistEntities(teamReaders, bp.ApprovalsWhitelistTeamIDs)
|
||||
bypassAllowlistTeams := getWhitelistEntities(teamReaders, bp.BypassAllowlistTeamIDs)
|
||||
|
||||
branchName := ""
|
||||
if !git_model.IsRuleNameSpecial(bp.RuleName) {
|
||||
@@ -181,6 +184,9 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
|
||||
EnableMergeWhitelist: bp.EnableMergeWhitelist,
|
||||
MergeWhitelistUsernames: mergeWhitelistUsernames,
|
||||
MergeWhitelistTeams: mergeWhitelistTeams,
|
||||
EnableBypassAllowlist: bp.EnableBypassAllowlist,
|
||||
BypassAllowlistUsernames: bypassAllowlistUsernames,
|
||||
BypassAllowlistTeams: bypassAllowlistTeams,
|
||||
EnableStatusCheck: bp.EnableStatusCheck,
|
||||
StatusCheckContexts: bp.StatusCheckContexts,
|
||||
RequiredApprovals: bp.RequiredApprovals,
|
||||
@@ -214,7 +220,7 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag {
|
||||
|
||||
return &api.Tag{
|
||||
Name: t.Name,
|
||||
Message: strings.ToValidUTF8(strings.TrimSpace(t.Message), "?"), // the trim is not right, 1.27 won't trim
|
||||
Message: t.MessageUTF8(),
|
||||
ID: t.ID.String(),
|
||||
Commit: ToCommitMeta(repo, t),
|
||||
ZipballURL: zipballURL,
|
||||
@@ -222,14 +228,18 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag {
|
||||
}
|
||||
}
|
||||
|
||||
// ToActionTask convert a actions_model.ActionTask to an api.ActionTask
|
||||
// ToActionTask convert an actions_model.ActionTask to an api.ActionTask
|
||||
func ToActionTask(ctx context.Context, t *actions_model.ActionTask) (*api.ActionTask, error) {
|
||||
if err := t.LoadAttributes(ctx); err != nil {
|
||||
// don't need Steps here, only need to load job and its run
|
||||
if err := t.LoadJob(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := t.Job.LoadRun(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := t.Job.Run.LoadRepo(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
url := strings.TrimSuffix(setting.AppURL, "/") + t.GetRunLink()
|
||||
|
||||
return &api.ActionTask{
|
||||
ID: t.ID,
|
||||
Name: t.Job.Name,
|
||||
@@ -240,37 +250,161 @@ func ToActionTask(ctx context.Context, t *actions_model.ActionTask) (*api.Action
|
||||
DisplayTitle: t.Job.Run.Title,
|
||||
Status: t.Status.String(),
|
||||
WorkflowID: t.Job.Run.WorkflowID,
|
||||
URL: url,
|
||||
URL: httplib.MakeAbsoluteURL(ctx, t.Job.Run.Link()),
|
||||
CreatedAt: t.Created.AsLocalTime(),
|
||||
UpdatedAt: t.Updated.AsLocalTime(),
|
||||
RunStartedAt: t.Started.AsLocalTime(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ToActionWorkflowRun(ctx context.Context, repo *repo_model.Repository, run *actions_model.ActionRun) (*api.ActionWorkflowRun, error) {
|
||||
err := run.LoadAttributes(ctx)
|
||||
if err != nil {
|
||||
func ToActionWorkflowRun(ctx context.Context, run *actions_model.ActionRun, attempt *actions_model.ActionRunAttempt, excludePullRequests bool) (_ *api.ActionWorkflowRun, err error) {
|
||||
if err := run.LoadAttributes(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if attempt == nil {
|
||||
attempt, _, err = run.GetLatestAttempt(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
runAttempt := int64(0)
|
||||
status, conclusion := ToActionsStatus(run.Status)
|
||||
startedAt := run.Started.AsLocalTime()
|
||||
completedAt := run.Stopped.AsLocalTime()
|
||||
actor := run.TriggerUser // The username of the user that triggered the initial workflow run.
|
||||
triggerUser := run.TriggerUser // The username of the user that initiated the workflow run. If the workflow run is a re-run, this value may differ from actor.
|
||||
|
||||
// previousAttemptURL is the value of ActionWorkflowRun.PreviousAttemptURL, which is declared as *string without `omitempty` on purpose:
|
||||
// a nil value must still appear in the JSON body as `"previous_attempt_url": null`, matching GitHub's Actions API.
|
||||
var previousAttemptURL *string
|
||||
|
||||
if attempt != nil {
|
||||
attempt.Run = run
|
||||
if err := attempt.LoadAttributes(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runAttempt = attempt.Attempt
|
||||
status, conclusion = ToActionsStatus(attempt.Status)
|
||||
startedAt = attempt.Started.AsLocalTime()
|
||||
completedAt = attempt.Stopped.AsLocalTime()
|
||||
triggerUser = attempt.TriggerUser
|
||||
if attempt.Attempt > 1 {
|
||||
url := fmt.Sprintf("%s/actions/runs/%d/attempts/%d", run.Repo.APIURL(ctx), run.ID, attempt.Attempt-1)
|
||||
previousAttemptURL = &url
|
||||
}
|
||||
}
|
||||
pullRequests := []*api.PullRequestMinimal{}
|
||||
if !excludePullRequests {
|
||||
pullRequests, err = loadPullRequestsForRun(ctx, run)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &api.ActionWorkflowRun{
|
||||
ID: run.ID,
|
||||
URL: fmt.Sprintf("%s/actions/runs/%d", repo.APIURL(), run.ID),
|
||||
HTMLURL: run.HTMLURL(),
|
||||
RunNumber: run.Index,
|
||||
StartedAt: run.Started.AsLocalTime(),
|
||||
CompletedAt: run.Stopped.AsLocalTime(),
|
||||
Event: run.TriggerEvent,
|
||||
DisplayTitle: run.Title,
|
||||
HeadBranch: git.RefName(run.Ref).BranchName(),
|
||||
HeadSha: run.CommitSHA,
|
||||
Status: status,
|
||||
Conclusion: conclusion,
|
||||
Path: fmt.Sprintf("%s@%s", run.WorkflowID, run.Ref),
|
||||
Repository: ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeNone}),
|
||||
TriggerActor: ToUser(ctx, run.TriggerUser, nil),
|
||||
// We do not have a way to get a different User for the actor than the trigger user
|
||||
Actor: ToUser(ctx, run.TriggerUser, nil),
|
||||
ID: run.ID,
|
||||
URL: fmt.Sprintf("%s/actions/runs/%d", run.Repo.APIURL(ctx), run.ID),
|
||||
PreviousAttemptURL: previousAttemptURL,
|
||||
HTMLURL: run.HTMLURL(ctx),
|
||||
RunNumber: run.Index,
|
||||
RunAttempt: runAttempt,
|
||||
StartedAt: startedAt,
|
||||
CompletedAt: completedAt,
|
||||
Event: run.TriggerEvent,
|
||||
DisplayTitle: run.Title,
|
||||
HeadBranch: git.RefName(run.Ref).BranchName(),
|
||||
HeadSha: run.CommitSHA,
|
||||
Status: status,
|
||||
Conclusion: conclusion,
|
||||
Path: fmt.Sprintf("%s@%s", run.WorkflowID, run.Ref),
|
||||
Repository: ToRepo(ctx, run.Repo, access_model.Permission{AccessMode: perm.AccessModeNone}),
|
||||
TriggerActor: ToUser(ctx, triggerUser, nil),
|
||||
Actor: ToUser(ctx, actor, nil),
|
||||
PullRequests: pullRequests,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// loadPullRequestsForRun returns the pull requests associated with a run, matching
|
||||
// GitHub's `pull_requests` field on workflow run responses:
|
||||
// - For pull_request / pull_request_review events, the PR whose ref triggered the run.
|
||||
// - For push events, open PRs whose head branch matches the pushed ref in the same repo.
|
||||
// - For other events, no PRs.
|
||||
func loadPullRequestsForRun(ctx context.Context, run *actions_model.ActionRun) ([]*api.PullRequestMinimal, error) {
|
||||
result := []*api.PullRequestMinimal{}
|
||||
refName := git.RefName(run.Ref)
|
||||
var prs issues_model.PullRequestList
|
||||
switch {
|
||||
case run.Event.IsPullRequest() || run.Event.IsPullRequestReview():
|
||||
index, err := strconv.ParseInt(refName.PullName(), 10, 64)
|
||||
if err != nil {
|
||||
return result, nil
|
||||
}
|
||||
pr, err := issues_model.GetPullRequestByIndex(ctx, run.RepoID, index)
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
return result, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
prs = issues_model.PullRequestList{pr}
|
||||
case run.Event == webhook_module.HookEventPush:
|
||||
branch := refName.BranchName()
|
||||
if branch == "" {
|
||||
return result, nil
|
||||
}
|
||||
var err error
|
||||
prs, err = issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, run.RepoID, branch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return result, nil
|
||||
}
|
||||
for _, pr := range prs {
|
||||
minimal, err := toPullRequestMinimal(ctx, run.Repo, pr, run.CommitSHA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, minimal)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func toPullRequestMinimal(ctx context.Context, repo *repo_model.Repository, pr *issues_model.PullRequest, headSHA string) (*api.PullRequestMinimal, error) {
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := pr.LoadHeadRepo(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
headRepo := pr.HeadRepo
|
||||
if headRepo == nil {
|
||||
headRepo = pr.BaseRepo
|
||||
}
|
||||
return &api.PullRequestMinimal{
|
||||
ID: pr.ID,
|
||||
Number: pr.Index,
|
||||
URL: fmt.Sprintf("%s/pulls/%d", repo.APIURL(ctx), pr.Index),
|
||||
Head: api.PullRequestMinimalHead{
|
||||
Ref: pr.HeadBranch,
|
||||
SHA: headSHA,
|
||||
Repo: api.PullRequestMinimalHeadRepo{
|
||||
ID: headRepo.ID,
|
||||
URL: headRepo.APIURL(ctx),
|
||||
Name: headRepo.Name,
|
||||
},
|
||||
},
|
||||
Base: api.PullRequestMinimalHead{
|
||||
Ref: pr.BaseBranch,
|
||||
SHA: pr.MergeBase,
|
||||
Repo: api.PullRequestMinimalHeadRepo{
|
||||
ID: pr.BaseRepo.ID,
|
||||
URL: pr.BaseRepo.APIURL(ctx),
|
||||
Name: pr.BaseRepo.Name,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -278,7 +412,7 @@ func ToWorkflowRunAction(status actions_model.Status) (action string) {
|
||||
switch status {
|
||||
case actions_model.StatusWaiting, actions_model.StatusBlocked:
|
||||
action = "requested"
|
||||
case actions_model.StatusRunning:
|
||||
case actions_model.StatusRunning, actions_model.StatusCancelling:
|
||||
action = "in_progress"
|
||||
default:
|
||||
if status.IsDone() {
|
||||
@@ -296,7 +430,7 @@ func ToActionsStatus(status actions_model.Status) (action, conclusion string) {
|
||||
action = "queued" // "waiting" is a naming conflict of the webhook between Gitea and GitHub Actions
|
||||
case actions_model.StatusBlocked:
|
||||
action = "waiting" // naming conflict (as above)
|
||||
case actions_model.StatusRunning:
|
||||
case actions_model.StatusRunning, actions_model.StatusCancelling:
|
||||
action = "in_progress"
|
||||
default:
|
||||
action = "completed"
|
||||
@@ -329,9 +463,9 @@ func ToActionWorkflowJob(ctx context.Context, repo *repo_model.Repository, task
|
||||
var runnerName string
|
||||
var steps []*api.ActionWorkflowStep
|
||||
|
||||
if job.TaskID != 0 {
|
||||
if effectiveTaskID := job.EffectiveTaskID(); effectiveTaskID != 0 {
|
||||
if task == nil {
|
||||
task, _, err = db.GetByID[actions_model.ActionTask](ctx, job.TaskID)
|
||||
task, _, err = db.GetByID[actions_model.ActionTask](ctx, effectiveTaskID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -366,11 +500,11 @@ func ToActionWorkflowJob(ctx context.Context, repo *repo_model.Repository, task
|
||||
return &api.ActionWorkflowJob{
|
||||
ID: job.ID,
|
||||
// missing api endpoint for this location
|
||||
URL: fmt.Sprintf("%s/actions/jobs/%d", repo.APIURL(), job.ID),
|
||||
HTMLURL: fmt.Sprintf("%s/jobs/%d", job.Run.HTMLURL(), job.ID),
|
||||
URL: fmt.Sprintf("%s/actions/jobs/%d", repo.APIURL(ctx), job.ID),
|
||||
HTMLURL: fmt.Sprintf("%s/jobs/%d", job.Run.HTMLURL(ctx), job.ID),
|
||||
RunID: job.RunID,
|
||||
// Missing api endpoint for this location, artifacts are available under a nested url
|
||||
RunURL: fmt.Sprintf("%s/actions/runs/%d", repo.APIURL(), job.RunID),
|
||||
RunURL: fmt.Sprintf("%s/actions/runs/%d", repo.APIURL(ctx), job.RunID),
|
||||
Name: job.Name,
|
||||
Labels: job.RunsOn,
|
||||
RunAttempt: job.Attempt,
|
||||
@@ -421,7 +555,7 @@ func getActionWorkflowEntry(ctx context.Context, repo *repo_model.Repository, co
|
||||
content, err := actions.GetContentFromEntry(entry)
|
||||
name := entry.Name()
|
||||
if err == nil {
|
||||
workflow, err := model.ReadWorkflow(bytes.NewReader(content))
|
||||
workflow, err := jobparser.ReadWorkflow(content)
|
||||
if err == nil {
|
||||
// Only use the name when specified in the workflow file
|
||||
if workflow.Name != "" {
|
||||
@@ -507,6 +641,64 @@ func getActionWorkflowFromCommit(ctx context.Context, repo *repo_model.Repositor
|
||||
return nil, util.NewNotExistErrorf("workflow %q not found", workflowID)
|
||||
}
|
||||
|
||||
// GetScopedActionWorkflow resolves a scoped workflow definition (under SCOPED_WORKFLOW_DIRS) from the source repo at commitSHA.
|
||||
func GetScopedActionWorkflow(ctx context.Context, sourceGitRepo *git.Repository, sourceRepo *repo_model.Repository, workflowID, commitSHA string) (*api.ActionWorkflow, error) {
|
||||
commit, err := sourceGitRepo.GetCommit(commitSHA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
folder, entries, err := actions.ListScopedWorkflows(commit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.Name() == workflowID {
|
||||
// An empty ref pins HTMLURL to commit (the run's WorkflowCommitSHA) rather than the moving default branch.
|
||||
wf := getActionWorkflowEntry(ctx, sourceRepo, commit, git.RefName(""), folder, entry)
|
||||
// TODO: a scoped workflow has no repo-level representation on the source: the workflow API scans WORKFLOW_DIRS (not SCOPED_WORKFLOW_DIRS),
|
||||
// and the badge only reflects the source's repo-level runs, so neither link resolves a scoped workflow.
|
||||
// Blank them for now and populate once a scoped-aware workflow/badge endpoint exists.
|
||||
wf.URL = ""
|
||||
wf.BadgeURL = ""
|
||||
return wf, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, util.NewNotExistErrorf("scoped workflow %q not found", workflowID)
|
||||
}
|
||||
|
||||
// ResolveActionWorkflowForRun returns the api.ActionWorkflow describing a run's workflow definition.
|
||||
// For a scoped run the definition lives in the source repo (run.WorkflowRepoID @ run.WorkflowCommitSHA) under SCOPED_WORKFLOW_DIRS,
|
||||
// not in the consuming repo, so it is resolved against the source repo.
|
||||
func ResolveActionWorkflowForRun(ctx context.Context, repo *repo_model.Repository, run *actions_model.ActionRun) (*api.ActionWorkflow, error) {
|
||||
if run.IsScopedRun {
|
||||
sourceRepo, err := repo_model.GetRepositoryByID(ctx, run.WorkflowRepoID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sourceGitRepo, err := gitrepo.OpenRepository(ctx, sourceRepo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer sourceGitRepo.Close()
|
||||
return GetScopedActionWorkflow(ctx, sourceGitRepo, sourceRepo, run.WorkflowID, run.WorkflowCommitSHA)
|
||||
}
|
||||
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
|
||||
convertedWorkflow, err := GetActionWorkflowByRef(ctx, gitRepo, repo, run.WorkflowID, git.RefName(run.Ref))
|
||||
if err != nil && errors.Is(err, util.ErrNotExist) {
|
||||
convertedWorkflow, err = GetActionWorkflow(ctx, gitRepo, repo, run.WorkflowID)
|
||||
}
|
||||
return convertedWorkflow, err
|
||||
}
|
||||
|
||||
// ToActionArtifact convert a actions_model.ActionArtifact to an api.ActionArtifact
|
||||
func ToActionArtifact(repo *repo_model.Repository, art *actions_model.ActionArtifact) (*api.ActionArtifact, error) {
|
||||
url := fmt.Sprintf("%s/actions/artifacts/%d", repo.APIURL(), art.ID)
|
||||
@@ -670,7 +862,7 @@ func ToOrganization(ctx context.Context, org *organization.Organization) *api.Or
|
||||
Description: org.Description,
|
||||
Website: org.Website,
|
||||
Location: org.Location,
|
||||
Visibility: org.Visibility.String(),
|
||||
Visibility: api.UserVisibility(org.Visibility.String()),
|
||||
RepoAdminChangeTeamAccess: org.RepoAdminChangeTeamAccess,
|
||||
}
|
||||
}
|
||||
@@ -699,9 +891,10 @@ func ToTeams(ctx context.Context, teams []*organization.Team, loadOrgs bool) ([]
|
||||
Description: t.Description,
|
||||
IncludesAllRepositories: t.IncludesAllRepositories,
|
||||
CanCreateOrgRepo: t.CanCreateOrgRepo,
|
||||
Permission: t.AccessMode.ToString(),
|
||||
Permission: api.AccessLevelName(t.AccessMode.ToString()),
|
||||
Units: t.GetUnitNames(),
|
||||
UnitsMap: t.GetUnitsMap(),
|
||||
Visibility: api.TeamVisibility(t.Visibility.String()),
|
||||
}
|
||||
|
||||
if loadOrgs {
|
||||
@@ -728,7 +921,7 @@ func ToAnnotatedTag(ctx context.Context, repo *repo_model.Repository, t *git.Tag
|
||||
Tag: t.Name,
|
||||
SHA: t.ID.String(),
|
||||
Object: ToAnnotatedTagObject(repo, c),
|
||||
Message: strings.ToValidUTF8(t.Message, "?"),
|
||||
Message: t.MessageUTF8(),
|
||||
URL: repo.APIURL() + "/git/tags/" + t.ID.String(),
|
||||
Tagger: ToCommitUser(t.Tagger),
|
||||
Verification: ToVerification(ctx, c),
|
||||
@@ -746,7 +939,7 @@ func ToAnnotatedTagObject(repo *repo_model.Repository, commit *git.Commit) *api.
|
||||
|
||||
// ToTagProtection convert a git.ProtectedTag to an api.TagProtection
|
||||
func ToTagProtection(ctx context.Context, pt *git_model.ProtectedTag, repo *repo_model.Repository) *api.TagProtection {
|
||||
readers, err := access_model.GetUsersWithUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypePullRequests)
|
||||
readers, err := access_model.GetUsersWithAnyUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests)
|
||||
if err != nil {
|
||||
log.Error("GetRepoReaders: %v", err)
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
ctx "code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/gitdiff"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/gitrepo"
|
||||
"gitea.dev/modules/log"
|
||||
api "gitea.dev/modules/structs"
|
||||
ctx "gitea.dev/services/context"
|
||||
"gitea.dev/services/gitdiff"
|
||||
)
|
||||
|
||||
// ToCommitUser convert a git.Signature to an api.CommitUser
|
||||
@@ -56,7 +56,7 @@ func ToPayloadCommit(ctx context.Context, repo *repo_model.Repository, c *git.Co
|
||||
|
||||
return &api.PayloadCommit{
|
||||
ID: c.ID.String(),
|
||||
Message: c.Message(),
|
||||
Message: c.MessageUTF8(),
|
||||
URL: repo.HTMLURL() + "/commit/" + c.ID.String(),
|
||||
Author: &api.PayloadUser{
|
||||
Name: c.Author.Name,
|
||||
@@ -171,7 +171,7 @@ func ToCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Rep
|
||||
},
|
||||
Date: commit.Committer.When.Format(time.RFC3339),
|
||||
},
|
||||
Message: commit.Message(),
|
||||
Message: commit.MessageUTF8(),
|
||||
Tree: &api.CommitMeta{
|
||||
URL: repo.APIURL() + "/git/trees/" + url.PathEscape(commit.ID.String()),
|
||||
SHA: commit.ID.String(),
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/modules/git"
|
||||
api "gitea.dev/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -21,12 +21,12 @@ func TestToCommitMeta(t *testing.T) {
|
||||
sha1 := git.Sha1ObjectFormat
|
||||
signature := &git.Signature{Name: "Test Signature", Email: "test@email.com", When: time.Unix(0, 0)}
|
||||
tag := &git.Tag{
|
||||
Name: "Test Tag",
|
||||
ID: sha1.EmptyObjectID(),
|
||||
Object: sha1.EmptyObjectID(),
|
||||
Type: "Test Type",
|
||||
Tagger: signature,
|
||||
Message: "Test Message",
|
||||
Name: "Test Tag",
|
||||
ID: sha1.EmptyObjectID(),
|
||||
Object: sha1.EmptyObjectID(),
|
||||
Type: "Test Type",
|
||||
Tagger: signature,
|
||||
CommitMessage: git.CommitMessage{MessageRaw: "Test Message"},
|
||||
}
|
||||
|
||||
commitMeta := ToCommitMeta(headRepo, tag)
|
||||
|
||||
@@ -9,16 +9,16 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/label"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/cache"
|
||||
"gitea.dev/modules/label"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/setting"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
func ToIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
|
||||
@@ -95,6 +95,13 @@ func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Iss
|
||||
apiIssue.Milestone = ToAPIMilestone(issue.Milestone)
|
||||
}
|
||||
|
||||
if err := issue.LoadProjects(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
if len(issue.Projects) > 0 {
|
||||
apiIssue.Projects = ToAPIProjectList(issue.Projects)
|
||||
}
|
||||
|
||||
if err := issue.LoadAssignees(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ package convert
|
||||
import (
|
||||
"context"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/log"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
// ToAPIComment converts a issues_model.Comment to the api.Comment format for API usage
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"gitea.dev/models/db"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/setting"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -6,9 +6,9 @@ package convert
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"gitea.dev/models/unittest"
|
||||
|
||||
_ "code.gitea.io/gitea/models/actions"
|
||||
_ "gitea.dev/models/actions"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
@@ -6,8 +6,8 @@ package convert
|
||||
import (
|
||||
"context"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToPushMirror convert from repo_model.PushMirror and remoteAddress to api.TopicResponse
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
activities_model "gitea.dev/models/activities"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
"gitea.dev/modules/log"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToNotificationThread convert a Notification to api.NotificationThread
|
||||
@@ -24,19 +24,22 @@ func ToNotificationThread(ctx context.Context, n *activities_model.Notification)
|
||||
}
|
||||
|
||||
// since user only get notifications when he has access to use minimal access mode
|
||||
if n.Repository != nil {
|
||||
perm, err := access_model.GetIndividualUserRepoPermission(ctx, n.Repository, n.User)
|
||||
if err != nil {
|
||||
log.Error("GetIndividualUserRepoPermission failed: %v", err)
|
||||
return result
|
||||
}
|
||||
if perm.HasAnyUnitAccessOrPublicAccess() { // if user has been revoked access to repo, do not show repo info
|
||||
result.Repository = ToRepo(ctx, n.Repository, perm)
|
||||
// This permission is not correct and we should not be reporting it
|
||||
for repository := result.Repository; repository != nil; repository = repository.Parent {
|
||||
repository.Permissions = nil
|
||||
}
|
||||
}
|
||||
if n.Repository == nil {
|
||||
return result
|
||||
}
|
||||
perm, err := access_model.GetIndividualUserRepoPermission(ctx, n.Repository, n.User)
|
||||
if err != nil {
|
||||
log.Error("GetIndividualUserRepoPermission failed: %v", err)
|
||||
return result
|
||||
}
|
||||
// if the user has been revoked access to the repo, do not leak repo or subject info
|
||||
if !perm.HasAnyUnitAccessOrPublicAccess() {
|
||||
return result
|
||||
}
|
||||
result.Repository = ToRepo(ctx, n.Repository, perm)
|
||||
// This permission is not correct and we should not be reporting it
|
||||
for repository := result.Repository; repository != nil; repository = repository.Parent {
|
||||
repository.Permissions = nil
|
||||
}
|
||||
|
||||
// handle Subject
|
||||
|
||||
@@ -6,13 +6,13 @@ package convert
|
||||
import (
|
||||
"testing"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
activities_model "gitea.dev/models/activities"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -39,6 +39,36 @@ func TestToNotificationThreadOmitsRepoWhenAccessRevoked(t *testing.T) {
|
||||
assert.Nil(t, thread.Repository)
|
||||
}
|
||||
|
||||
func TestToNotificationThreadOmitsSubjectWhenAccessRevoked(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
ctx := t.Context()
|
||||
// repo 2 is private; user 4 has no access to it
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
assert.NoError(t, repo.LoadOwner(ctx))
|
||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4, RepoID: repo.ID})
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
|
||||
n := &activities_model.Notification{
|
||||
ID: 12345,
|
||||
UserID: user.ID,
|
||||
RepoID: repo.ID,
|
||||
Status: activities_model.NotificationStatusUnread,
|
||||
Source: activities_model.NotificationSourceIssue,
|
||||
IssueID: issue.ID,
|
||||
UpdatedUnix: timeutil.TimeStampNow(),
|
||||
Issue: issue,
|
||||
Repository: repo,
|
||||
User: user,
|
||||
}
|
||||
|
||||
thread := ToNotificationThread(ctx, n)
|
||||
|
||||
// must not leak private issue metadata once access is revoked
|
||||
assert.Nil(t, thread.Repository)
|
||||
assert.Nil(t, thread.Subject)
|
||||
}
|
||||
|
||||
func TestToNotificationThread(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ package convert
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/packages"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"gitea.dev/models/packages"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
user_model "gitea.dev/models/user"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToPackage convert a packages.PackageDescriptor to api.Package
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package convert
|
||||
|
||||
import (
|
||||
project_model "gitea.dev/models/project"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToAPIProject converts a Project to API format
|
||||
func ToAPIProject(p *project_model.Project) *api.Project {
|
||||
apiProject := &api.Project{
|
||||
ID: p.ID,
|
||||
Title: p.Title,
|
||||
Description: p.Description,
|
||||
OwnerID: p.OwnerID,
|
||||
RepoID: p.RepoID,
|
||||
CreatorID: p.CreatorID,
|
||||
IsClosed: p.IsClosed,
|
||||
Created: p.CreatedUnix.AsTime(),
|
||||
Updated: p.UpdatedUnix.AsTime(),
|
||||
}
|
||||
if p.IsClosed && p.ClosedDateUnix > 0 {
|
||||
apiProject.Closed = p.ClosedDateUnix.AsTimePtr()
|
||||
}
|
||||
return apiProject
|
||||
}
|
||||
|
||||
// ToAPIProjectList converts a list of Projects to API format
|
||||
func ToAPIProjectList(projects []*project_model.Project) []*api.Project {
|
||||
result := make([]*api.Project, len(projects))
|
||||
for i := range projects {
|
||||
result[i] = ToAPIProject(projects[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -7,21 +7,21 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/cachegroup"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/gitdiff"
|
||||
git_model "gitea.dev/models/git"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
"gitea.dev/models/perm"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/cache"
|
||||
"gitea.dev/modules/cachegroup"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/gitrepo"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/setting"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/services/gitdiff"
|
||||
)
|
||||
|
||||
// ToAPIPullRequest assumes following fields have been assigned with valid values:
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
user_model "gitea.dev/models/user"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToPullReview convert a review to api format
|
||||
|
||||
@@ -6,9 +6,9 @@ package convert
|
||||
import (
|
||||
"testing"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -6,12 +6,12 @@ package convert
|
||||
import (
|
||||
"testing"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
issues_model "gitea.dev/models/issues"
|
||||
"gitea.dev/models/perm"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -6,8 +6,8 @@ package convert
|
||||
import (
|
||||
"context"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToAPIRelease convert a repo_model.Release to api.Release
|
||||
|
||||
@@ -6,8 +6,8 @@ package convert
|
||||
import (
|
||||
"testing"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"gitea.dev/models/db"
|
||||
git_model "gitea.dev/models/git"
|
||||
"gitea.dev/models/perm"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
unit_model "gitea.dev/models/unit"
|
||||
"gitea.dev/modules/log"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
// ToRepo converts a Repository to api.Repository
|
||||
@@ -98,11 +98,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
allowRebaseMerge := false
|
||||
allowSquash := false
|
||||
allowFastForwardOnly := false
|
||||
allowMergeUpdate := false
|
||||
allowRebaseUpdate := false
|
||||
allowManualMerge := true
|
||||
autodetectManualMerge := false
|
||||
defaultDeleteBranchAfterMerge := false
|
||||
defaultMergeStyle := repo_model.MergeStyleMerge
|
||||
defaultUpdateStyle := repo_model.UpdateStyleMerge
|
||||
defaultAllowMaintainerEdit := false
|
||||
defaultTargetBranch := ""
|
||||
if unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests); err == nil {
|
||||
@@ -114,11 +116,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
allowRebaseMerge = config.AllowRebaseMerge
|
||||
allowSquash = config.AllowSquash
|
||||
allowFastForwardOnly = config.AllowFastForwardOnly
|
||||
allowMergeUpdate = config.AllowMergeUpdate
|
||||
allowRebaseUpdate = config.AllowRebaseUpdate
|
||||
allowManualMerge = config.AllowManualMerge
|
||||
autodetectManualMerge = config.AutodetectManualMerge
|
||||
defaultDeleteBranchAfterMerge = config.DefaultDeleteBranchAfterMerge
|
||||
defaultMergeStyle = config.DefaultMergeStyle
|
||||
defaultUpdateStyle = config.DefaultUpdateStyle
|
||||
defaultAllowMaintainerEdit = config.DefaultAllowMaintainerEdit
|
||||
defaultTargetBranch = config.DefaultTargetBranch
|
||||
}
|
||||
@@ -152,11 +156,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
|
||||
mirrorInterval := ""
|
||||
var mirrorUpdated time.Time
|
||||
var lastSync time.Time
|
||||
if repo.IsMirror {
|
||||
pullMirror, err := repo_model.GetMirrorByRepoID(ctx, repo.ID)
|
||||
if err == nil {
|
||||
mirrorInterval = pullMirror.Interval.String()
|
||||
mirrorUpdated = pullMirror.UpdatedUnix.AsTime()
|
||||
lastSync = pullMirror.LastSyncUnix.AsTime()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,20 +244,23 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
AllowRebaseMerge: allowRebaseMerge,
|
||||
AllowSquash: allowSquash,
|
||||
AllowFastForwardOnly: allowFastForwardOnly,
|
||||
AllowMergeUpdate: allowMergeUpdate,
|
||||
AllowRebaseUpdate: allowRebaseUpdate,
|
||||
AllowManualMerge: allowManualMerge,
|
||||
AutodetectManualMerge: autodetectManualMerge,
|
||||
DefaultDeleteBranchAfterMerge: defaultDeleteBranchAfterMerge,
|
||||
DefaultMergeStyle: string(defaultMergeStyle),
|
||||
DefaultUpdateStyle: string(defaultUpdateStyle),
|
||||
DefaultAllowMaintainerEdit: defaultAllowMaintainerEdit,
|
||||
DefaultTargetBranch: defaultTargetBranch,
|
||||
AvatarURL: repo.AvatarLink(ctx),
|
||||
Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate,
|
||||
MirrorLastSyncAt: lastSync,
|
||||
MirrorInterval: mirrorInterval,
|
||||
MirrorUpdated: mirrorUpdated,
|
||||
RepoTransfer: transfer,
|
||||
Topics: util.SliceNilAsEmpty(repo.Topics),
|
||||
ObjectFormatName: repo.ObjectFormatName,
|
||||
ObjectFormatName: api.ObjectFormatName(repo.ObjectFormatName),
|
||||
Licenses: util.SliceNilAsEmpty(repoLicenses.StringList()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package convert
|
||||
|
||||
import (
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
)
|
||||
|
||||
// ToSecret converts Secret to API format
|
||||
func ToSecret(secret *secret_model.Secret) *api.Secret {
|
||||
result := &api.Secret{
|
||||
Name: secret.Name,
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/commitstatus"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
git_model "gitea.dev/models/git"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/commitstatus"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToCommitStatus converts git_model.CommitStatus to api.CommitStatus
|
||||
|
||||
@@ -6,9 +6,9 @@ package convert
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"gitea.dev/models/perm"
|
||||
user_model "gitea.dev/models/user"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToUser convert user_model.User to api.User
|
||||
@@ -65,7 +65,7 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap
|
||||
StarredRepos: user.NumStars,
|
||||
}
|
||||
|
||||
result.Visibility = user.Visibility.String()
|
||||
result.Visibility = api.UserVisibility(user.Visibility.String())
|
||||
|
||||
// hide primary email if API caller is anonymous or user keep email private
|
||||
if signed && (!user.KeepEmailPrivate || authed) {
|
||||
@@ -109,7 +109,7 @@ func User2UserSettings(ctx context.Context, user *user_model.User) (api.UserSett
|
||||
func ToUserAndPermission(ctx context.Context, user, doer *user_model.User, accessMode perm.AccessMode) api.RepoCollaboratorPermission {
|
||||
return api.RepoCollaboratorPermission{
|
||||
User: ToUser(ctx, user, doer),
|
||||
Permission: accessMode.ToString(),
|
||||
Permission: api.AccessLevelName(accessMode.ToString()),
|
||||
RoleName: accessMode.ToString(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ package convert
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
api "gitea.dev/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -29,11 +29,11 @@ func TestUser_ToUser(t *testing.T) {
|
||||
|
||||
apiUser = toUser(t.Context(), user1, false, false)
|
||||
assert.False(t, apiUser.IsAdmin)
|
||||
assert.Equal(t, api.VisibleTypePublic.String(), apiUser.Visibility)
|
||||
assert.Equal(t, api.UserVisibilityPublic, apiUser.Visibility)
|
||||
|
||||
user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31, IsAdmin: false, Visibility: api.VisibleTypePrivate})
|
||||
|
||||
apiUser = toUser(t.Context(), user31, true, true)
|
||||
assert.False(t, apiUser.IsAdmin)
|
||||
assert.Equal(t, api.VisibleTypePrivate.String(), apiUser.Visibility)
|
||||
assert.Equal(t, api.UserVisibilityPrivate, apiUser.Visibility)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ package convert
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToCorrectPageSize makes sure page size is in allowed range.
|
||||
|
||||
@@ -6,8 +6,8 @@ package convert
|
||||
import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"gitea.dev/modules/git"
|
||||
api "gitea.dev/modules/structs"
|
||||
)
|
||||
|
||||
// ToWikiCommit convert a git commit into a WikiCommit
|
||||
@@ -28,7 +28,7 @@ func ToWikiCommit(commit *git.Commit) *api.WikiCommit {
|
||||
},
|
||||
Date: commit.Committer.When.UTC().Format(time.RFC3339),
|
||||
},
|
||||
Message: commit.Message(),
|
||||
Message: commit.MessageUTF8(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user