diff --git a/server/api/pipeline.go b/server/api/pipeline.go index f454168a710..05b5fb0a8fb 100644 --- a/server/api/pipeline.go +++ b/server/api/pipeline.go @@ -90,19 +90,25 @@ func CreatePipeline(c *gin.Context) { func createTmpPipeline(event model.WebhookEvent, commit *model.Commit, user *model.User, opts *model.PipelineOptions) *model.Pipeline { return &model.Pipeline{ - Event: event, - Commit: commit.SHA, - Branch: opts.Branch, - Timestamp: time.Now().UTC().Unix(), - - Avatar: user.Avatar, - Message: "MANUAL PIPELINE @ " + opts.Branch, + Event: event, + Commit: &model.Commit{ + SHA: commit.SHA, + Message: "MANUAL PIPELINE @ " + opts.Branch, + ForgeURL: commit.ForgeURL, + Author: model.CommitAuthor{ + Name: user.Login, + Email: user.Email, + }, + Timestamp: time.Now().UTC().Unix(), + }, + Branch: opts.Branch, + + Avatar: user.Avatar, Ref: opts.Branch, AdditionalVariables: opts.Variables, Author: user.Login, - Email: user.Email, ForgeURL: commit.ForgeURL, } diff --git a/server/api/user.go b/server/api/user.go index c34213411e0..e3f87d8b79e 100644 --- a/server/api/user.go +++ b/server/api/user.go @@ -64,7 +64,11 @@ func GetFeed(c *gin.Context) { if err != nil { c.String(http.StatusInternalServerError, "Error fetching feed. %s", err) } else { - c.JSON(http.StatusOK, feed) + fs := make([]*model.APIFeed, 0, len(feed)) + for _, f := range feed { + fs = append(fs, f.ToAPIModel()) + } + c.JSON(http.StatusOK, fs) } return } diff --git a/server/cron/cron.go b/server/cron/cron.go index 777be65c9ac..1de77adcaec 100644 --- a/server/cron/cron.go +++ b/server/cron/cron.go @@ -144,11 +144,14 @@ func CreatePipeline(ctx context.Context, store store.Store, cron *model.Cron) (* } return repo, &model.Pipeline{ - Event: model.EventCron, - Commit: commit.SHA, + Event: model.EventCron, + Commit: &model.Commit{ + SHA: commit.SHA, + ForgeURL: commit.ForgeURL, + Timestamp: cron.NextExec, + }, Ref: "refs/heads/" + cron.Branch, Branch: cron.Branch, - Timestamp: cron.NextExec, Cron: cron.Name, ForgeURL: commit.ForgeURL, AdditionalVariables: cron.Variables, diff --git a/server/cron/cron_test.go b/server/cron/cron_test.go index 61ffe262260..9bc70a41527 100644 --- a/server/cron/cron_test.go +++ b/server/cron/cron_test.go @@ -63,7 +63,7 @@ func TestCreatePipeline(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, &model.Pipeline{ Branch: "default", - Commit: "sha1", + Commit: &model.Commit{SHA: "sha1", ForgeURL: "https://example.com/sha1"}, Event: "cron", ForgeURL: "https://example.com/sha1", Ref: "refs/heads/default", diff --git a/server/forge/bitbucket/bitbucket.go b/server/forge/bitbucket/bitbucket.go index b0392cf7b65..366d2571cd4 100644 --- a/server/forge/bitbucket/bitbucket.go +++ b/server/forge/bitbucket/bitbucket.go @@ -242,7 +242,7 @@ func (c *config) Repos(ctx context.Context, u *model.User, p *model.ListOptions) // File fetches the file from the Bitbucket repository and returns its contents. func (c *config) File(ctx context.Context, u *model.User, r *model.Repo, p *model.Pipeline, f string) ([]byte, error) { - config, err := c.newClient(ctx, u).FindSource(r.Owner, r.Name, p.Commit, f) + config, err := c.newClient(ctx, u).FindSource(r.Owner, r.Name, p.Commit.SHA, f) if err != nil { var rspErr internal.Error if ok := errors.As(err, &rspErr); ok && rspErr.Status == http.StatusNotFound { @@ -261,7 +261,7 @@ func (c *config) Dir(ctx context.Context, u *model.User, r *model.Repo, p *model repoPathFiles := []*forge_types.FileMeta{} client := c.newClient(ctx, u) for { - filesResp, err := client.GetRepoFiles(r.Owner, r.Name, p.Commit, f, page) + filesResp, err := client.GetRepoFiles(r.Owner, r.Name, p.Commit.SHA, f, page) if err != nil { var rspErr internal.Error if ok := errors.As(err, &rspErr); ok && rspErr.Status == http.StatusNotFound { @@ -277,7 +277,7 @@ func (c *config) Dir(ctx context.Context, u *model.User, r *model.Repo, p *model Name: filename, } if file.Type == "commit_file" { - fileData, err := c.newClient(ctx, u).FindSource(r.Owner, r.Name, p.Commit, file.Path) + fileData, err := c.newClient(ctx, u).FindSource(r.Owner, r.Name, p.Commit.SHA, file.Path) if err != nil { return nil, err } @@ -322,7 +322,7 @@ func (c *config) Status(ctx context.Context, user *model.User, repo *model.Repo, status.Refname = pipeline.Branch } - return c.newClient(ctx, user).CreateStatus(repo.Owner, repo.Name, pipeline.Commit, &status) + return c.newClient(ctx, user).CreateStatus(repo.Owner, repo.Name, pipeline.Commit.SHA, &status) } // Activate activates the repository by registering repository push hooks with @@ -454,7 +454,7 @@ func (c *config) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod switch pl.Event { case model.EventPush: // List only the latest push changes - pl.ChangedFiles, err = c.newClient(ctx, u).ListChangedFiles(repo.Owner, repo.Name, pl.Commit) + pl.ChangedFiles, err = c.newClient(ctx, u).ListChangedFiles(repo.Owner, repo.Name, pl.Commit.SHA) if err != nil { return nil, nil, err } diff --git a/server/forge/bitbucket/bitbucket_test.go b/server/forge/bitbucket/bitbucket_test.go index 81c1f023e56..9c4d0c779ac 100644 --- a/server/forge/bitbucket/bitbucket_test.go +++ b/server/forge/bitbucket/bitbucket_test.go @@ -209,7 +209,7 @@ func TestBitbucket(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "martinherren1984/publictestrepo", r.FullName) assert.Equal(t, "master", r.Branch) - assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit) + assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit.SHA) assert.Equal(t, []string{"main.go"}, b.ChangedFiles) } @@ -276,7 +276,7 @@ var ( } fakePipeline = &model.Pipeline{ - Commit: "9ecad50", + Commit: &model.Commit{SHA: "9ecad50"}, } fakeWorkflow = &model.Workflow{ diff --git a/server/forge/bitbucket/convert.go b/server/forge/bitbucket/convert.go index 937d61695cf..8f5ff670a6b 100644 --- a/server/forge/bitbucket/convert.go +++ b/server/forge/bitbucket/convert.go @@ -166,26 +166,32 @@ func convertPullHook(from *internal.PullRequestHook) *model.Pipeline { } pipeline := &model.Pipeline{ - Event: event, - Commit: from.PullRequest.Source.Commit.Hash, - Ref: fmt.Sprintf("refs/pull-requests/%d/from", from.PullRequest.ID), + Event: event, + Commit: &model.Commit{ + SHA: from.PullRequest.Source.Commit.Hash, + Message: from.PullRequest.Title, + ForgeURL: from.PullRequest.Links.HTML.Href, + Author: model.CommitAuthor{ + Name: from.Actor.Login, + }, + Timestamp: from.PullRequest.Updated.UTC().Unix(), + }, + Ref: fmt.Sprintf("refs/pull-requests/%d/from", from.PullRequest.ID), Refspec: fmt.Sprintf( "%s:%s", from.PullRequest.Source.Branch.Name, from.PullRequest.Dest.Branch.Name, ), - ForgeURL: from.PullRequest.Links.HTML.Href, - Branch: from.PullRequest.Source.Branch.Name, - Message: from.PullRequest.Title, - Avatar: from.Actor.Links.Avatar.Href, - Author: from.Actor.Login, - Sender: from.Actor.Login, - Timestamp: from.PullRequest.Updated.UTC().Unix(), - FromFork: from.PullRequest.Source.Repo.UUID != from.PullRequest.Dest.Repo.UUID, + ForgeURL: from.PullRequest.Links.HTML.Href, + Branch: from.PullRequest.Source.Branch.Name, + Avatar: from.Actor.Links.Avatar.Href, + Author: from.Actor.Login, + Sender: from.Actor.Login, + FromFork: from.PullRequest.Source.Repo.UUID != from.PullRequest.Dest.Repo.UUID, } if from.PullRequest.State == stateClosed { - pipeline.Commit = from.PullRequest.MergeCommit.Hash + pipeline.Commit.SHA = from.PullRequest.MergeCommit.Hash pipeline.Ref = fmt.Sprintf("refs/heads/%s", from.PullRequest.Dest.Branch.Name) pipeline.Branch = from.PullRequest.Dest.Branch.Name } @@ -197,14 +203,20 @@ func convertPullHook(from *internal.PullRequestHook) *model.Pipeline { // hook to the Woodpecker pipeline struct holding commit information. func convertPushHook(hook *internal.PushHook, change *internal.Change) *model.Pipeline { pipeline := &model.Pipeline{ - Commit: change.New.Target.Hash, - ForgeURL: change.New.Target.Links.HTML.Href, - Branch: change.New.Name, - Message: change.New.Target.Message, - Avatar: hook.Actor.Links.Avatar.Href, - Author: hook.Actor.Login, - Sender: hook.Actor.Login, - Timestamp: change.New.Target.Date.UTC().Unix(), + Commit: &model.Commit{ + SHA: change.New.Target.Hash, + Message: change.New.Target.Message, + ForgeURL: change.New.Target.Links.HTML.Href, + Author: model.CommitAuthor{ + Name: hook.Actor.Login, + }, + Timestamp: change.New.Target.Date.UTC().Unix(), + }, + ForgeURL: change.New.Target.Links.HTML.Href, + Branch: change.New.Name, + Avatar: hook.Actor.Links.Avatar.Href, + Author: hook.Actor.Login, + Sender: hook.Actor.Login, } switch change.New.Type { case "tag", "annotated_tag", "bookmark": @@ -216,7 +228,7 @@ func convertPushHook(hook *internal.PushHook, change *internal.Change) *model.Pi pipeline.Ref = fmt.Sprintf("refs/heads/%s", change.New.Name) } if len(change.New.Target.Author.Raw) != 0 { - pipeline.Email = extractEmail(change.New.Target.Author.Raw) + pipeline.Commit.Author.Email = extractEmail(change.New.Target.Author.Raw) } return pipeline } diff --git a/server/forge/bitbucket/convert_test.go b/server/forge/bitbucket/convert_test.go index cf9b04fe9a7..d2b1c3bcecc 100644 --- a/server/forge/bitbucket/convert_test.go +++ b/server/forge/bitbucket/convert_test.go @@ -129,13 +129,13 @@ func Test_convertPullHook(t *testing.T) { assert.Equal(t, model.EventPull, pipeline.Event) assert.Equal(t, hook.Actor.Login, pipeline.Author) assert.Equal(t, hook.Actor.Links.Avatar.Href, pipeline.Avatar) - assert.Equal(t, hook.PullRequest.Source.Commit.Hash, pipeline.Commit) + assert.Equal(t, hook.PullRequest.Source.Commit.Hash, pipeline.Commit.SHA) assert.Equal(t, hook.PullRequest.Source.Branch.Name, pipeline.Branch) assert.Equal(t, hook.PullRequest.Links.HTML.Href, pipeline.ForgeURL) assert.Equal(t, "refs/pull-requests/1/from", pipeline.Ref) assert.Equal(t, "change:main", pipeline.Refspec) - assert.Equal(t, hook.PullRequest.Title, pipeline.Message) - assert.Equal(t, hook.PullRequest.Updated.Unix(), pipeline.Timestamp) + assert.Equal(t, hook.PullRequest.Title, pipeline.Commit.Message) + assert.Equal(t, hook.PullRequest.Updated.Unix(), pipeline.Commit.Timestamp) } func Test_convertPushHook(t *testing.T) { @@ -153,15 +153,15 @@ func Test_convertPushHook(t *testing.T) { pipeline := convertPushHook(&hook, &change) assert.Equal(t, model.EventPush, pipeline.Event) - assert.Equal(t, "test@domain.tld", pipeline.Email) + assert.Equal(t, "test@domain.tld", pipeline.Commit.Author.Email) assert.Equal(t, hook.Actor.Login, pipeline.Author) assert.Equal(t, hook.Actor.Links.Avatar.Href, pipeline.Avatar) - assert.Equal(t, change.New.Target.Hash, pipeline.Commit) + assert.Equal(t, change.New.Target.Hash, pipeline.Commit.SHA) assert.Equal(t, change.New.Name, pipeline.Branch) assert.Equal(t, change.New.Target.Links.HTML.Href, pipeline.ForgeURL) assert.Equal(t, "refs/heads/main", pipeline.Ref) - assert.Equal(t, change.New.Target.Message, pipeline.Message) - assert.Equal(t, change.New.Target.Date.Unix(), pipeline.Timestamp) + assert.Equal(t, change.New.Target.Message, pipeline.Commit.Message) + assert.Equal(t, change.New.Target.Date.Unix(), pipeline.Commit.Timestamp) } func Test_convertPushHookTag(t *testing.T) { diff --git a/server/forge/bitbucket/parse_test.go b/server/forge/bitbucket/parse_test.go index 8b3c5f416a0..314a1e18638 100644 --- a/server/forge/bitbucket/parse_test.go +++ b/server/forge/bitbucket/parse_test.go @@ -60,7 +60,7 @@ func Test_parseHook(t *testing.T) { assert.NotNil(t, pr) assert.Equal(t, "user_name/repo_name", r.FullName) assert.Equal(t, model.EventPull, b.Event) - assert.Equal(t, "d3022fc0ca3d", b.Commit) + assert.Equal(t, "d3022fc0ca3d", b.Commit.SHA) }) t.Run("pull-request merged", func(t *testing.T) { @@ -74,7 +74,7 @@ func Test_parseHook(t *testing.T) { assert.NotNil(t, pr) assert.Equal(t, "anbraten/test-2", r.FullName) assert.Equal(t, model.EventPullClosed, b.Event) - assert.Equal(t, "006704dbeab2", b.Commit) + assert.Equal(t, "006704dbeab2", b.Commit.SHA) }) t.Run("pull-request closed", func(t *testing.T) { @@ -88,7 +88,7 @@ func Test_parseHook(t *testing.T) { assert.NotNil(t, pr) assert.Equal(t, "anbraten/test-2", r.FullName) assert.Equal(t, model.EventPullClosed, b.Event) - assert.Equal(t, "f90e18fc9d45", b.Commit) + assert.Equal(t, "f90e18fc9d45", b.Commit.SHA) }) t.Run("malformed push", func(t *testing.T) { @@ -124,7 +124,7 @@ func Test_parseHook(t *testing.T) { assert.Nil(t, pr) assert.Equal(t, "martinherren1984/publictestrepo", r.FullName) assert.Equal(t, "https://bitbucket.org/martinherren1984/publictestrepo", r.Clone) - assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit) - assert.Equal(t, "a\n", b.Message) + assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit.SHA) + assert.Equal(t, "a\n", b.Commit.Message) }) } diff --git a/server/forge/bitbucketdatacenter/bitbucketdatacenter.go b/server/forge/bitbucketdatacenter/bitbucketdatacenter.go index 2d25872d4a5..aade374e5ff 100644 --- a/server/forge/bitbucketdatacenter/bitbucketdatacenter.go +++ b/server/forge/bitbucketdatacenter/bitbucketdatacenter.go @@ -272,7 +272,7 @@ func (c *client) File(ctx context.Context, u *model.User, r *model.Repo, p *mode return nil, fmt.Errorf("unable to create bitbucket client: %w", err) } - b, resp, err := bc.Projects.GetTextFileContent(ctx, r.Owner, r.Name, f, p.Commit) + b, resp, err := bc.Projects.GetTextFileContent(ctx, r.Owner, r.Name, f, p.Commit.SHA) if err != nil { if resp != nil && resp.StatusCode == http.StatusNotFound { // requested directory might not exist @@ -291,7 +291,7 @@ func (c *client) Dir(ctx context.Context, u *model.User, r *model.Repo, p *model return nil, fmt.Errorf("unable to create bitbucket client: %w", err) } - opts := &bitbucket.FilesListOptions{At: p.Commit} + opts := &bitbucket.FilesListOptions{At: p.Commit.SHA} all := make([]*forge_types.FileMeta, 0) for { list, resp, err := bc.Projects.ListFiles(ctx, r.Owner, r.Name, path, opts) @@ -335,7 +335,7 @@ func (c *client) Status(ctx context.Context, u *model.User, repo *model.Repo, pi DateAdded: bitbucket.DateTime(time.Unix(pipeline.Started, 0)), Ref: fmt.Sprintf("refs/heads/%s", pipeline.Branch), } - _, err = bc.Projects.CreateBuildStatus(ctx, repo.Owner, repo.Name, pipeline.Commit, status) + _, err = bc.Projects.CreateBuildStatus(ctx, repo.Owner, repo.Name, pipeline.Commit.SHA, status) return err } @@ -566,19 +566,23 @@ func (c *client) updatePipelineFromCommits(ctx context.Context, u *model.User, r return nil, fmt.Errorf("unable to create bitbucket client: %w", err) } - commit, _, err := bc.Projects.GetCommit(ctx, r.Owner, r.Name, p.Commit) + if p.Commit == nil { + p.Commit = &model.Commit{} + } + + commit, _, err := bc.Projects.GetCommit(ctx, r.Owner, r.Name, p.Commit.SHA) if err != nil { return nil, fmt.Errorf("unable to read commit: %w", err) } // In Bitbucket Data Center, when using annotated tags, the webhook's ToHash is the tag object SHA, not the actual commit SHA. // Update p.Commit so that build statuses are posted to the correct commit SHA. - if p.Event == model.EventTag && commit.ID != "" && commit.ID != p.Commit { - p.Commit = commit.ID + if p.Event == model.EventTag && commit.ID != "" && commit.ID != p.Commit.SHA { + p.Commit.SHA = commit.ID p.ForgeURL = fmt.Sprintf("%s/projects/%s/repos/%s/commits/%s", c.url, r.Owner, r.Name, commit.ID) } - p.Message = commit.Message + p.Commit.Message = commit.Message opts := &bitbucket.CompareChangesOptions{} if currCommit != "" { diff --git a/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go b/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go index 23a4a0762d3..c63c459b038 100644 --- a/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go +++ b/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go @@ -113,7 +113,7 @@ var ( fakePipeline = &model.Pipeline{ ID: 1, Number: 42, - Commit: "3ce383490b3d90d79460c60f67ba2580acc6cc59", + Commit: &model.Commit{SHA: "3ce383490b3d90d79460c60f67ba2580acc6cc59"}, Started: 1759825800, Finished: 1759825883, Branch: "feature-branch", diff --git a/server/forge/bitbucketdatacenter/convert.go b/server/forge/bitbucketdatacenter/convert.go index 8bf24bd452e..f103ab75a99 100644 --- a/server/forge/bitbucketdatacenter/convert.go +++ b/server/forge/bitbucketdatacenter/convert.go @@ -88,16 +88,23 @@ func convertRepositoryPushEvent(ev *bitbucket.RepositoryPushEvent, baseURL strin return nil } + forgeURL := fmt.Sprintf("%s/projects/%s/repos/%s/commits/%s", baseURL, ev.Repository.Project.Key, ev.Repository.Slug, change.ToHash) pipeline := &model.Pipeline{ - Commit: change.ToHash, - Branch: change.Ref.DisplayID, - Message: "", - Avatar: bitbucketAvatarURL(baseURL, ev.Actor.Slug), - Author: authorLabel(ev.Actor.Name), - Email: ev.Actor.Email, - Timestamp: time.Time(ev.Date).UTC().Unix(), - Ref: ev.Changes[0].RefId, - ForgeURL: fmt.Sprintf("%s/projects/%s/repos/%s/commits/%s", baseURL, ev.Repository.Project.Key, ev.Repository.Slug, change.ToHash), + Commit: &model.Commit{ + SHA: change.ToHash, + Message: "", + ForgeURL: forgeURL, + Author: model.CommitAuthor{ + Name: authorLabel(ev.Actor.Name), + Email: ev.Actor.Email, + }, + Timestamp: time.Time(ev.Date).UTC().Unix(), + }, + Branch: change.Ref.DisplayID, + Avatar: bitbucketAvatarURL(baseURL, ev.Actor.Slug), + Author: authorLabel(ev.Actor.Name), + Ref: ev.Changes[0].RefId, + ForgeURL: forgeURL, } if strings.HasPrefix(ev.Changes[0].RefId, "refs/tags/") { @@ -125,19 +132,26 @@ func convertGetCommitRange(ev *bitbucket.RepositoryPushEvent) (currCommit, prevC } func convertPullRequestEvent(ev *bitbucket.PullRequestEvent, baseURL string) *model.Pipeline { + forgeURL := fmt.Sprintf("%s/projects/%s/repos/%s/commits/%s", baseURL, ev.PullRequest.Source.Repository.Project.Key, ev.PullRequest.Source.Repository.Slug, ev.PullRequest.Source.Latest) pipeline := &model.Pipeline{ - Commit: ev.PullRequest.Source.Latest, - Branch: ev.PullRequest.Source.DisplayID, - Title: ev.PullRequest.Title, - Message: ev.PullRequest.Title, - Avatar: bitbucketAvatarURL(baseURL, ev.Actor.Slug), - Author: authorLabel(ev.Actor.Name), - Email: ev.Actor.Email, - Timestamp: time.Time(ev.Date).UTC().Unix(), - Ref: fmt.Sprintf("refs/pull-requests/%d/from", ev.PullRequest.ID), - ForgeURL: fmt.Sprintf("%s/projects/%s/repos/%s/commits/%s", baseURL, ev.PullRequest.Source.Repository.Project.Key, ev.PullRequest.Source.Repository.Slug, ev.PullRequest.Source.Latest), - Refspec: fmt.Sprintf("%s:%s", ev.PullRequest.Source.DisplayID, ev.PullRequest.Target.DisplayID), - FromFork: ev.PullRequest.Source.Repository.ID != ev.PullRequest.Target.Repository.ID, + Commit: &model.Commit{ + SHA: ev.PullRequest.Source.Latest, + Message: ev.PullRequest.Title, + ForgeURL: forgeURL, + Author: model.CommitAuthor{ + Name: authorLabel(ev.Actor.Name), + Email: ev.Actor.Email, + }, + Timestamp: time.Time(ev.Date).UTC().Unix(), + }, + Branch: ev.PullRequest.Source.DisplayID, + Title: ev.PullRequest.Title, + Avatar: bitbucketAvatarURL(baseURL, ev.Actor.Slug), + Author: authorLabel(ev.Actor.Name), + Ref: fmt.Sprintf("refs/pull-requests/%d/from", ev.PullRequest.ID), + ForgeURL: forgeURL, + Refspec: fmt.Sprintf("%s:%s", ev.PullRequest.Source.DisplayID, ev.PullRequest.Target.DisplayID), + FromFork: ev.PullRequest.Source.Repository.ID != ev.PullRequest.Target.Repository.ID, } if ev.EventKey == bitbucket.EventKeyPullRequestMerged || ev.EventKey == bitbucket.EventKeyPullRequestDeclined || ev.EventKey == bitbucket.EventKeyPullRequestDeleted { diff --git a/server/forge/bitbucketdatacenter/convert_test.go b/server/forge/bitbucketdatacenter/convert_test.go index 96a0298991b..88794cd6679 100644 --- a/server/forge/bitbucketdatacenter/convert_test.go +++ b/server/forge/bitbucketdatacenter/convert_test.go @@ -153,16 +153,23 @@ func Test_convertRepositoryPushEvent(t *testing.T) { }, }, to: &model.Pipeline{ - Commit: "1234567890abcdef", - Branch: "branch", - Message: "", - Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", - Author: "John Doe", - Email: "john.doe@mail.com", - Timestamp: now.UTC().Unix(), - Ref: "refs/head/branch", - ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", - Event: model.EventPush, + Commit: &model.Commit{ + SHA: "1234567890abcdef", + Message: "", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Timestamp: now.UTC().Unix(), + Author: model.CommitAuthor{ + Name: "John Doe", + Email: "john.doe@mail.com", + }, + }, + Branch: "branch", + Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", + Author: "John Doe", + + Ref: "refs/head/branch", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Event: model.EventPush, }, }, } @@ -213,18 +220,25 @@ func Test_convertPullRequestEvent(t *testing.T) { } to := convertPullRequestEvent(from, "https://base.url") assert.Equal(t, &model.Pipeline{ - Commit: "1234567890abcdef", - Branch: "branch", - Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", - Author: "John Doe", - Email: "john.doe@mail.com", - Timestamp: now.UTC().Unix(), - Ref: "refs/pull-requests/123/from", - ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", - Event: model.EventPull, - Refspec: "branch:main", - Title: "my title", - Message: "my title", + Commit: &model.Commit{ + SHA: "1234567890abcdef", + Message: "my title", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Timestamp: now.UTC().Unix(), + Author: model.CommitAuthor{ + Name: "John Doe", + Email: "john.doe@mail.com", + }, + }, + Branch: "branch", + Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", + Author: "John Doe", + + Ref: "refs/pull-requests/123/from", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Event: model.EventPull, + Refspec: "branch:main", + Title: "my title", }, to) } @@ -269,18 +283,25 @@ func Test_convertPullRequestCloseEvent(t *testing.T) { } to := convertPullRequestEvent(from, "https://base.url") assert.Equal(t, &model.Pipeline{ - Commit: "1234567890abcdef", - Branch: "branch", - Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", - Author: "John Doe", - Email: "john.doe@mail.com", - Timestamp: now.UTC().Unix(), - Ref: "refs/pull-requests/123/from", - ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", - Event: model.EventPullClosed, - Refspec: "branch:main", - Title: "my title", - Message: "my title", + Commit: &model.Commit{ + SHA: "1234567890abcdef", + Message: "my title", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Timestamp: now.UTC().Unix(), + Author: model.CommitAuthor{ + Name: "John Doe", + Email: "john.doe@mail.com", + }, + }, + Branch: "branch", + Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", + Author: "John Doe", + + Ref: "refs/pull-requests/123/from", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Event: model.EventPullClosed, + Refspec: "branch:main", + Title: "my title", }, to) } diff --git a/server/forge/bitbucketdatacenter/parse_test.go b/server/forge/bitbucketdatacenter/parse_test.go index 65ab7a406b5..f1708d31472 100644 --- a/server/forge/bitbucketdatacenter/parse_test.go +++ b/server/forge/bitbucketdatacenter/parse_test.go @@ -45,7 +45,7 @@ func Test_parseHook(t *testing.T) { assert.NotNil(t, result.Pipeline) assert.NotNil(t, result.Payload) assert.Equal(t, "DEV/network-monitor", result.Repo.FullName) - assert.Equal(t, "1c7589876bc8b5e83122b1656925d679915193d4", result.Pipeline.Commit) + assert.Equal(t, "1c7589876bc8b5e83122b1656925d679915193d4", result.Pipeline.Commit.SHA) assert.Equal(t, model.EventPull, result.Pipeline.Event) }) @@ -67,7 +67,7 @@ func Test_parseHook(t *testing.T) { assert.NotNil(t, result.Pipeline) assert.NotNil(t, result.Payload) assert.Equal(t, "DEV/deployment-automation", result.Repo.FullName) - assert.Equal(t, "716e510cecbe203618609cf103c54e040b949739", result.Pipeline.Commit) + assert.Equal(t, "716e510cecbe203618609cf103c54e040b949739", result.Pipeline.Commit.SHA) assert.Equal(t, model.EventPull, result.Pipeline.Event) }) @@ -89,7 +89,7 @@ func Test_parseHook(t *testing.T) { assert.Equal(t, curCommit, "76797d54bca87db6d1e3e82ee40622c7908aa514") assert.Equal(t, prevCommit, "e0e15221b987fd8296141c0faa6a79f7c86ca4ce") assert.Equal(t, "DEV/deployment-automation", result.Repo.FullName) - assert.Equal(t, "76797d54bca87db6d1e3e82ee40622c7908aa514", result.Pipeline.Commit) + assert.Equal(t, "76797d54bca87db6d1e3e82ee40622c7908aa514", result.Pipeline.Commit.SHA) assert.Equal(t, model.EventPush, result.Pipeline.Event) }) @@ -111,7 +111,7 @@ func Test_parseHook(t *testing.T) { assert.NotNil(t, result.Pipeline) assert.NotNil(t, result.Payload) assert.Equal(t, "DEV/deployment-automation", result.Repo.FullName) - assert.Equal(t, "993203acecdb65ffe947424d0917768b0e5c3903", result.Pipeline.Commit) + assert.Equal(t, "993203acecdb65ffe947424d0917768b0e5c3903", result.Pipeline.Commit.SHA) assert.Equal(t, model.EventPullClosed, result.Pipeline.Event) }) } diff --git a/server/forge/forgejo/forgejo.go b/server/forge/forgejo/forgejo.go index 6fbac5888ba..c046930b543 100644 --- a/server/forge/forgejo/forgejo.go +++ b/server/forge/forgejo/forgejo.go @@ -275,7 +275,7 @@ func (c *Forgejo) File(ctx context.Context, u *model.User, r *model.Repo, b *mod return nil, err } - cfg, resp, err := client.GetFile(r.Owner, r.Name, b.Commit, f) + cfg, resp, err := client.GetFile(r.Owner, r.Name, b.Commit.SHA, f) if err != nil && resp != nil && resp.StatusCode == http.StatusNotFound { return nil, errors.Join(err, &forge_types.ErrConfigNotFound{Configs: []string{f}}) } @@ -291,7 +291,7 @@ func (c *Forgejo) Dir(ctx context.Context, u *model.User, r *model.Repo, b *mode } // List files in repository - contents, resp, err := client.ListContents(r.Owner, r.Name, b.Commit, f) + contents, resp, err := client.ListContents(r.Owner, r.Name, b.Commit.SHA, f) if err != nil { if resp != nil && resp.StatusCode == http.StatusNotFound { return nil, errors.Join(err, &forge_types.ErrConfigNotFound{Configs: []string{f}}) @@ -326,7 +326,7 @@ func (c *Forgejo) Status(ctx context.Context, user *model.User, repo *model.Repo _, _, err = client.CreateStatus( repo.Owner, repo.Name, - pipeline.Commit, + pipeline.Commit.SHA, forgejo.CreateStatusOption{ State: getStatus(workflow.State), TargetURL: common.GetPipelineStatusURL(repo, pipeline, workflow), @@ -509,12 +509,15 @@ func (c *Forgejo) Hook(ctx context.Context, r *http.Request) (*model.Repo, *mode if pipeline.TagTitle == "" { pipeline.TagTitle = strings.Split(pipeline.Ref, "/")[2] } - if pipeline.Commit == "" { + if pipeline.Commit == nil || pipeline.Commit.SHA == "" { sha, err := c.getTagCommitSHA(ctx, repo, pipeline.TagTitle) if err != nil { return nil, nil, err } - pipeline.Commit = sha + if pipeline.Commit == nil { + pipeline.Commit = &model.Commit{} + } + pipeline.Commit.SHA = sha } case model.EventPull, model.EventPullClosed, model.EventPullMetadata: diff --git a/server/forge/forgejo/forgejo_test.go b/server/forge/forgejo/forgejo_test.go index d31fa8b50e5..84c54b1d962 100644 --- a/server/forge/forgejo/forgejo_test.go +++ b/server/forge/forgejo/forgejo_test.go @@ -161,7 +161,7 @@ var ( } fakePipeline = &model.Pipeline{ - Commit: "9ecad50", + Commit: &model.Commit{SHA: "9ecad50"}, } fakeWorkflow = &model.Workflow{ diff --git a/server/forge/forgejo/helper.go b/server/forge/forgejo/helper.go index 2045c544b3c..1a8f7fe2aac 100644 --- a/server/forge/forgejo/helper.go +++ b/server/forge/forgejo/helper.go @@ -88,16 +88,22 @@ func pipelineFromPush(hook *pushHook) *model.Pipeline { } return &model.Pipeline{ - Event: model.EventPush, - Commit: hook.After, + Event: model.EventPush, + Commit: &model.Commit{ + SHA: hook.After, + Message: message, + ForgeURL: link, + Author: model.CommitAuthor{ + Name: hook.Sender.UserName, + Email: hook.Sender.Email, + }, + Timestamp: time.Now().UTC().Unix(), + }, Ref: hook.Ref, ForgeURL: link, Branch: strings.TrimPrefix(hook.Ref, "refs/heads/"), - Message: message, Avatar: avatar, Author: hook.Sender.UserName, - Email: hook.Sender.Email, - Timestamp: time.Now().UTC().Unix(), Sender: hook.Sender.UserName, ChangedFiles: getChangedFilesFromPushHook(hook), } @@ -128,16 +134,22 @@ func pipelineFromTag(hook *pushHook) *model.Pipeline { ref := strings.TrimPrefix(hook.Ref, "refs/tags/") return &model.Pipeline{ - Event: model.EventTag, - Commit: hook.Sha, - Ref: fmt.Sprintf("refs/tags/%s", ref), - TagTitle: ref, - ForgeURL: fmt.Sprintf("%s/src/tag/%s", hook.Repo.HTMLURL, ref), - Avatar: avatar, - Author: hook.Sender.UserName, - Sender: hook.Sender.UserName, - Email: hook.Sender.Email, - Timestamp: time.Now().UTC().Unix(), + Event: model.EventTag, + Commit: &model.Commit{ + SHA: hook.Sha, + ForgeURL: fmt.Sprintf("%s/src/tag/%s", hook.Repo.HTMLURL, ref), + Author: model.CommitAuthor{ + Name: hook.Sender.UserName, + Email: hook.Sender.Email, + }, + Timestamp: time.Now().UTC().Unix(), + }, + Ref: fmt.Sprintf("refs/tags/%s", ref), + TagTitle: ref, + ForgeURL: fmt.Sprintf("%s/src/tag/%s", hook.Repo.HTMLURL, ref), + Avatar: avatar, + Author: hook.Sender.UserName, + Sender: hook.Sender.UserName, } } @@ -163,16 +175,22 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline { } pipeline := &model.Pipeline{ - Event: event, - Commit: hook.PullRequest.Head.Sha, + Event: event, + Commit: &model.Commit{ + SHA: hook.PullRequest.Head.Sha, + Message: hook.PullRequest.Title, + ForgeURL: hook.PullRequest.HTMLURL, + Author: model.CommitAuthor{ + Name: hook.PullRequest.Poster.UserName, + Email: hook.Sender.Email, + }, + }, ForgeURL: hook.PullRequest.HTMLURL, Ref: fmt.Sprintf("refs/pull/%d/head", hook.Number), Branch: hook.PullRequest.Base.Ref, - Message: hook.PullRequest.Title, Author: hook.PullRequest.Poster.UserName, Avatar: avatar, Sender: hook.Sender.UserName, - Email: hook.Sender.Email, Title: hook.PullRequest.Title, Refspec: fmt.Sprintf( "%s:%s", @@ -205,7 +223,14 @@ func pipelineFromRelease(hook *releaseHook) *model.Pipeline { ) return &model.Pipeline{ - Event: model.EventRelease, + Event: model.EventRelease, + Commit: &model.Commit{ + ForgeURL: hook.Release.HTMLURL, + Author: model.CommitAuthor{ + Name: hook.Sender.UserName, + Email: hook.Sender.Email, + }, + }, Ref: fmt.Sprintf("refs/tags/%s", hook.Release.TagName), ForgeURL: hook.Release.HTMLURL, Branch: hook.Release.Target, @@ -217,7 +242,6 @@ func pipelineFromRelease(hook *releaseHook) *model.Pipeline { Avatar: avatar, Author: hook.Sender.UserName, Sender: hook.Sender.UserName, - Email: hook.Sender.Email, } } diff --git a/server/forge/forgejo/helper_test.go b/server/forge/forgejo/helper_test.go index 4e8184bf763..d6223864465 100644 --- a/server/forge/forgejo/helper_test.go +++ b/server/forge/forgejo/helper_test.go @@ -66,11 +66,11 @@ func Test_parsePush(t *testing.T) { hook, _ := parsePush(buf) pipeline := pipelineFromPush(hook) assert.Equal(t, model.EventPush, pipeline.Event) - assert.Equal(t, hook.After, pipeline.Commit) + assert.Equal(t, hook.After, pipeline.Commit.SHA) assert.Equal(t, hook.Ref, pipeline.Ref) assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL) assert.Equal(t, "main", pipeline.Branch) - assert.Equal(t, hook.Commits[0].Message, pipeline.Message) + assert.Equal(t, hook.Commits[0].Message, pipeline.Commit.Message) assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) assert.Equal(t, hook.Sender.UserName, pipeline.Author) assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles) @@ -91,7 +91,7 @@ func Test_parsePush(t *testing.T) { hook, _ := parsePush(buf) pipeline := pipelineFromTag(hook) assert.Equal(t, model.EventTag, pipeline.Event) - assert.Equal(t, hook.Sha, pipeline.Commit) + assert.Equal(t, hook.Sha, pipeline.Commit.SHA) assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref) assert.Empty(t, pipeline.Branch) assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL) @@ -131,12 +131,12 @@ func Test_parsePullRequest(t *testing.T) { hook, _ := parsePullRequest(buf) pipeline := pipelineFromPullRequest(hook) assert.Equal(t, model.EventPull, pipeline.Event) - assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit) + assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit.SHA) assert.Equal(t, "refs/pull/1/head", pipeline.Ref) assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/pull/1", pipeline.ForgeURL) assert.Equal(t, "main", pipeline.Branch) assert.Equal(t, "feature/changes:main", pipeline.Refspec) - assert.Equal(t, hook.PullRequest.Title, pipeline.Message) + assert.Equal(t, hook.PullRequest.Title, pipeline.Commit.Message) assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) assert.Equal(t, hook.PullRequest.Poster.UserName, pipeline.Author) }) diff --git a/server/forge/forgejo/parse_test.go b/server/forge/forgejo/parse_test.go index a67b5e8387e..36e393a8094 100644 --- a/server/forge/forgejo/parse_test.go +++ b/server/forge/forgejo/parse_test.go @@ -63,15 +63,21 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "push", - Commit: "28c3613ae62640216bea5e7dc71aa65356e4298b", + Author: "6543", + Event: "push", + Commit: &model.Commit{ + SHA: "28c3613ae62640216bea5e7dc71aa65356e4298b", + Message: "Delete '.woodpecker/.check.yml'\n", + ForgeURL: "https://codeberg.org/meisam/woodpecktester/commit/28c3613ae62640216bea5e7dc71aa65356e4298b", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@obermui.de", + }, + }, Branch: "fdsafdsa", Ref: "refs/heads/fdsafdsa", - Message: "Delete '.woodpecker/.check.yml'\n", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@obermui.de", ForgeURL: "https://codeberg.org/meisam/woodpecktester/commit/28c3613ae62640216bea5e7dc71aa65356e4298b", ChangedFiles: []string{".woodpecker/.check.yml"}, }, @@ -97,15 +103,21 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "gordon", - Event: "push", - Commit: "ef98532add3b2feb7a137426bba1248724367df5", + Author: "gordon", + Event: "push", + Commit: &model.Commit{ + SHA: "ef98532add3b2feb7a137426bba1248724367df5", + Message: "bump\n", + ForgeURL: "http://forgejo.golang.org/gordon/hello-world/commit/ef98532add3b2feb7a137426bba1248724367df5", + Author: model.CommitAuthor{ + Name: "gordon", + Email: "gordon@golang.org", + }, + }, Branch: "main", Ref: "refs/heads/main", - Message: "bump\n", Sender: "gordon", Avatar: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - Email: "gordon@golang.org", ForgeURL: "http://forgejo.golang.org/gordon/hello-world/commit/ef98532add3b2feb7a137426bba1248724367df5", ChangedFiles: []string{"CHANGELOG.md", "app/controller/application.rb"}, }, @@ -131,15 +143,21 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "test-user", - Event: "push", - Commit: "29be01c073851cf0db0c6a466e396b725a670453", + Author: "test-user", + Event: "push", + Commit: &model.Commit{ + SHA: "29be01c073851cf0db0c6a466e396b725a670453", + Message: "add some text\n", + ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/compare/6efcf5b7c98f3e7a491675164b7a2e7acac27941...29be01c073851cf0db0c6a466e396b725a670453", + Author: model.CommitAuthor{ + Name: "test-user", + Email: "test@noreply.localhost", + }, + }, Branch: "main", Ref: "refs/heads/main", - Message: "add some text\n", Sender: "test-user", Avatar: "http://127.0.0.1:3000/avatars/dd46a756faad4727fb679320751f6dea", - Email: "test@noreply.localhost", ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/compare/6efcf5b7c98f3e7a491675164b7a2e7acac27941...29be01c073851cf0db0c6a466e396b725a670453", ChangedFiles: []string{"aaa", "aa"}, }, @@ -169,11 +187,17 @@ func TestForgejoParser(t *testing.T) { Event: model.EventTag, TagTitle: "v1.0.0", Author: "gordon", - Commit: "ef98532add3b2feb7a137426bba1248724367df5", + Commit: &model.Commit{ + SHA: "ef98532add3b2feb7a137426bba1248724367df5", + ForgeURL: "http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0", + Author: model.CommitAuthor{ + Name: "gordon", + Email: "gordon@golang.org", + }, + }, Ref: "refs/tags/v1.0.0", Sender: "gordon", Avatar: "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - Email: "gordon@golang.org", ForgeURL: "http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0", }, }, @@ -199,17 +223,23 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "gordon", - Event: "pull_request", - Commit: "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + Author: "gordon", + Event: "pull_request", + Commit: &model.Commit{ + SHA: "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + Message: "Update the README with new information", + ForgeURL: "http://forgejo.golang.org/gordon/hello-world/pull/1", + Author: model.CommitAuthor{ + Name: "gordon", + Email: "gordon@golang.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "feature/changes:main", Title: "Update the README with new information", - Message: "Update the README with new information", Sender: "gordon", Avatar: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - Email: "gordon@golang.org", ForgeURL: "http://forgejo.golang.org/gordon/hello-world/pull/1", PullRequestLabels: []string{}, }, @@ -237,17 +267,23 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request", - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request", + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{}, }, @@ -275,17 +311,23 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "test", - Event: "pull_request", - Commit: "788ed8d02d3b7fcfcf6386dbcbca696aa1d4dc25", + Author: "test", + Event: "pull_request", + Commit: &model.Commit{ + SHA: "788ed8d02d3b7fcfcf6386dbcbca696aa1d4dc25", + Message: "New Pull", + ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/pulls/2", + Author: model.CommitAuthor{ + Name: "test", + Email: "test@noreply.localhost", + }, + }, Branch: "main", Ref: "refs/pull/2/head", Refspec: "test-patch-1:main", Title: "New Pull", - Message: "New Pull", Sender: "test", Avatar: "http://127.0.0.1:3000/avatars/dd46a756faad4727fb679320751f6dea", - Email: "test@noreply.localhost", ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/pulls/2", PullRequestLabels: []string{ "Kind/Bug", @@ -315,18 +357,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "anbraten", - Event: "pull_request_metadata", - EventReason: []string{"edited"}, - Commit: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Author: "anbraten", + Event: "pull_request_metadata", + EventReason: []string{"edited"}, + Commit: &model.Commit{ + SHA: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Message: "Adjust file", + ForgeURL: "https://forgejo.com/anbraten/test-repo/pulls/1", + Author: model.CommitAuthor{ + Name: "anbraten", + Email: "anbraten@sender.forgejo.com", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "anbraten-patch-1:main", Title: "Adjust file", - Message: "Adjust file", Sender: "anbraten", Avatar: "https://seccdn.libravatar.org/avatar/fc9b6fe77c6b732a02925a62a81f05a0?d=identicon", - Email: "anbraten@sender.forgejo.com", ForgeURL: "https://forgejo.com/anbraten/test-repo/pulls/1", PullRequestLabels: []string{}, }, @@ -353,17 +401,23 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "anbraten", - Event: "pull_request_closed", - Commit: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Author: "anbraten", + Event: "pull_request_closed", + Commit: &model.Commit{ + SHA: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Message: "Adjust file", + ForgeURL: "https://forgejo.com/anbraten/test-repo/pulls/1", + Author: model.CommitAuthor{ + Name: "anbraten", + Email: "anbraten@sender.forgejo.com", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "anbraten-patch-1:main", Title: "Adjust file", - Message: "Adjust file", Sender: "anbraten", Avatar: "https://seccdn.libravatar.org/avatar/fc9b6fe77c6b732a02925a62a81f05a0?d=identicon", - Email: "anbraten@sender.forgejo.com", ForgeURL: "https://forgejo.com/anbraten/test-repo/pulls/1", PullRequestLabels: []string{}, }, @@ -390,17 +444,23 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "anbraten", - Event: "pull_request_closed", - Commit: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Author: "anbraten", + Event: "pull_request_closed", + Commit: &model.Commit{ + SHA: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Message: "Adjust file", + ForgeURL: "https://forgejo.com/anbraten/test-repo/pulls/1", + Author: model.CommitAuthor{ + Name: "anbraten", + Email: "anbraten@noreply.forgejo.com", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "anbraten-patch-1:main", Title: "Adjust file", - Message: "Adjust file", Sender: "anbraten", Avatar: "https://seccdn.libravatar.org/avatar/fc9b6fe77c6b732a02925a62a81f05a0?d=identicon", - Email: "anbraten@noreply.forgejo.com", ForgeURL: "https://forgejo.com/anbraten/test-repo/pulls/1", PullRequestLabels: []string{}, }, @@ -438,7 +498,13 @@ func TestForgejoParser(t *testing.T) { TagTitle: "0.0.5", Sender: "anbraten", Avatar: "https://git.xxx/user/avatar/anbraten/-1", - Email: "anbraten@noreply.xxx", + Commit: &model.Commit{ + ForgeURL: "https://git.xxx/anbraten/demo/releases/tag/0.0.5", + Author: model.CommitAuthor{ + Name: "anbraten", + Email: "anbraten@noreply.xxx", + }, + }, ForgeURL: "https://git.xxx/anbraten/demo/releases/tag/0.0.5", }, }, @@ -464,18 +530,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"assigned"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"assigned"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{}, ChangedFiles: nil, @@ -503,18 +575,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"milestoned"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"milestoned"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{}, PullRequestMilestone: "mile v2", @@ -543,18 +621,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"label_updated"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"label_updated"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{"Kind/Documentation", "Kind/Enhancement"}, PullRequestMilestone: "mile v2", @@ -583,18 +667,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"unassigned"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"unassigned"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{"Kind/Documentation", "Kind/Enhancement"}, PullRequestMilestone: "mile v2", @@ -623,18 +713,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"milestoned"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"milestoned"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{"Kind/Documentation", "Kind/Enhancement"}, PullRequestMilestone: "mile v2", @@ -663,18 +759,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"label_updated"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"label_updated"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{"Kind/Enhancement", "Kind/Testing"}, PullRequestMilestone: "mile v1", @@ -703,18 +805,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"label_cleared"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"label_cleared"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{}, PullRequestMilestone: "mile v1", @@ -743,18 +851,24 @@ func TestForgejoParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request_metadata", - EventReason: []string{"demilestoned"}, - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request_metadata", + EventReason: []string{"demilestoned"}, + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{}, ChangedFiles: nil, @@ -772,7 +886,9 @@ func TestForgejoParser(t *testing.T) { assert.ErrorIs(t, err, tc.err) } else if assert.NoError(t, err) { assert.EqualValues(t, tc.repo, r) - p.Timestamp = 0 + if p.Commit != nil { + p.Commit.Timestamp = 0 + } assert.EqualValues(t, tc.pipe, p) } }) diff --git a/server/forge/gitea/gitea.go b/server/forge/gitea/gitea.go index 09dd4c32673..1da4984440a 100644 --- a/server/forge/gitea/gitea.go +++ b/server/forge/gitea/gitea.go @@ -277,7 +277,7 @@ func (c *Gitea) File(ctx context.Context, u *model.User, r *model.Repo, b *model return nil, err } - cfg, resp, err := client.GetFile(r.Owner, r.Name, b.Commit, f) + cfg, resp, err := client.GetFile(r.Owner, r.Name, b.Commit.SHA, f) if err != nil && resp != nil && resp.StatusCode == http.StatusNotFound { return nil, errors.Join(err, &forge_types.ErrConfigNotFound{Configs: []string{f}}) } @@ -293,7 +293,7 @@ func (c *Gitea) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model. } // List files in repository - contents, resp, err := client.ListContents(r.Owner, r.Name, b.Commit, f) + contents, resp, err := client.ListContents(r.Owner, r.Name, b.Commit.SHA, f) if err != nil { if resp != nil && resp.StatusCode == http.StatusNotFound { return nil, errors.Join(err, &forge_types.ErrConfigNotFound{Configs: []string{f}}) @@ -328,7 +328,7 @@ func (c *Gitea) Status(ctx context.Context, user *model.User, repo *model.Repo, _, _, err = client.CreateStatus( repo.Owner, repo.Name, - pipeline.Commit, + pipeline.Commit.SHA, gitea.CreateStatusOption{ State: getStatus(workflow.State), TargetURL: common.GetPipelineStatusURL(repo, pipeline, workflow), @@ -516,12 +516,15 @@ func (c *Gitea) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model. if pipeline.TagTitle == "" { pipeline.TagTitle = strings.Split(pipeline.Ref, "/")[2] } - if pipeline.Commit == "" { + if pipeline.Commit == nil || pipeline.Commit.SHA == "" { sha, err := c.getTagCommitSHA(ctx, repo, pipeline.TagTitle) if err != nil { return nil, nil, err } - pipeline.Commit = sha + if pipeline.Commit == nil { + pipeline.Commit = &model.Commit{} + } + pipeline.Commit.SHA = sha } case model.EventPull, model.EventPullClosed, model.EventPullMetadata: diff --git a/server/forge/gitea/gitea_test.go b/server/forge/gitea/gitea_test.go index 07354193777..88a011a2bd8 100644 --- a/server/forge/gitea/gitea_test.go +++ b/server/forge/gitea/gitea_test.go @@ -162,7 +162,7 @@ var ( } fakePipeline = &model.Pipeline{ - Commit: "9ecad50", + Commit: &model.Commit{SHA: "9ecad50"}, } fakeWorkflow = &model.Workflow{ diff --git a/server/forge/gitea/helper.go b/server/forge/gitea/helper.go index bdcdbe0bad6..19a61037b6a 100644 --- a/server/forge/gitea/helper.go +++ b/server/forge/gitea/helper.go @@ -89,16 +89,22 @@ func pipelineFromPush(hook *pushHook) *model.Pipeline { } return &model.Pipeline{ - Event: model.EventPush, - Commit: hook.After, + Event: model.EventPush, + Commit: &model.Commit{ + SHA: hook.After, + Message: message, + ForgeURL: link, + Author: model.CommitAuthor{ + Name: hook.Sender.UserName, + Email: hook.Sender.Email, + }, + Timestamp: time.Now().UTC().Unix(), + }, Ref: hook.Ref, ForgeURL: link, Branch: strings.TrimPrefix(hook.Ref, "refs/heads/"), - Message: message, Avatar: avatar, Author: hook.Sender.UserName, - Email: hook.Sender.Email, - Timestamp: time.Now().UTC().Unix(), Sender: hook.Sender.UserName, ChangedFiles: getChangedFilesFromPushHook(hook), } @@ -129,16 +135,22 @@ func pipelineFromTag(hook *pushHook) *model.Pipeline { ref := strings.TrimPrefix(hook.Ref, "refs/tags/") return &model.Pipeline{ - Event: model.EventTag, - TagTitle: ref, - Commit: hook.Sha, - Ref: fmt.Sprintf("refs/tags/%s", ref), - ForgeURL: fmt.Sprintf("%s/src/tag/%s", hook.Repo.HTMLURL, ref), - Avatar: avatar, - Author: hook.Sender.UserName, - Sender: hook.Sender.UserName, - Email: hook.Sender.Email, - Timestamp: time.Now().UTC().Unix(), + Event: model.EventTag, + TagTitle: ref, + Commit: &model.Commit{ + SHA: hook.Sha, + ForgeURL: fmt.Sprintf("%s/src/tag/%s", hook.Repo.HTMLURL, ref), + Author: model.CommitAuthor{ + Name: hook.Sender.UserName, + Email: hook.Sender.Email, + }, + Timestamp: time.Now().UTC().Unix(), + }, + Ref: fmt.Sprintf("refs/tags/%s", ref), + ForgeURL: fmt.Sprintf("%s/src/tag/%s", hook.Repo.HTMLURL, ref), + Avatar: avatar, + Author: hook.Sender.UserName, + Sender: hook.Sender.UserName, } } @@ -164,16 +176,22 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline { } pipeline := &model.Pipeline{ - Event: event, - Commit: hook.PullRequest.Head.Sha, + Event: event, + Commit: &model.Commit{ + SHA: hook.PullRequest.Head.Sha, + Message: hook.PullRequest.Title, + ForgeURL: hook.PullRequest.HTMLURL, + Author: model.CommitAuthor{ + Name: hook.PullRequest.Poster.UserName, + Email: hook.Sender.Email, + }, + }, ForgeURL: hook.PullRequest.HTMLURL, Ref: fmt.Sprintf("refs/pull/%d/head", hook.Number), Branch: hook.PullRequest.Base.Ref, - Message: hook.PullRequest.Title, Author: hook.PullRequest.Poster.UserName, Avatar: avatar, Sender: hook.Sender.UserName, - Email: hook.Sender.Email, Title: hook.PullRequest.Title, Refspec: fmt.Sprintf( "%s:%s", @@ -207,14 +225,20 @@ func pipelineFromRelease(hook *releaseHook) *model.Pipeline { ) return &model.Pipeline{ - Event: model.EventRelease, + Event: model.EventRelease, + Commit: &model.Commit{ + ForgeURL: hook.Release.HTMLURL, + Author: model.CommitAuthor{ + Name: hook.Sender.UserName, + Email: hook.Sender.Email, + }, + }, Ref: fmt.Sprintf("refs/tags/%s", hook.Release.TagName), ForgeURL: hook.Release.HTMLURL, Branch: hook.Release.Target, Avatar: avatar, Author: hook.Sender.UserName, Sender: hook.Sender.UserName, - Email: hook.Sender.Email, Release: &model.Release{ Title: hook.Release.Title, IsPrerelease: hook.Release.IsPrerelease, diff --git a/server/forge/gitea/helper_test.go b/server/forge/gitea/helper_test.go index b290c537872..eb6215df9a0 100644 --- a/server/forge/gitea/helper_test.go +++ b/server/forge/gitea/helper_test.go @@ -67,11 +67,11 @@ func Test_parsePush(t *testing.T) { hook, _ := parsePush(buf) pipeline := pipelineFromPush(hook) assert.Equal(t, model.EventPush, pipeline.Event) - assert.Equal(t, hook.After, pipeline.Commit) + assert.Equal(t, hook.After, pipeline.Commit.SHA) assert.Equal(t, hook.Ref, pipeline.Ref) assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL) assert.Equal(t, "main", pipeline.Branch) - assert.Equal(t, hook.Commits[0].Message, pipeline.Message) + assert.Equal(t, hook.Commits[0].Message, pipeline.Commit.Message) assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) assert.Equal(t, hook.Sender.UserName, pipeline.Author) assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles) @@ -92,7 +92,7 @@ func Test_parsePush(t *testing.T) { hook, _ := parsePush(buf) pipeline := pipelineFromTag(hook) assert.Equal(t, model.EventTag, pipeline.Event) - assert.Equal(t, hook.Sha, pipeline.Commit) + assert.Equal(t, hook.Sha, pipeline.Commit.SHA) assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref) assert.Empty(t, pipeline.Branch) assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL) @@ -132,12 +132,12 @@ func Test_parsePullRequest(t *testing.T) { hook, _ := parsePullRequest(buf) pipeline := pipelineFromPullRequest(hook) assert.Equal(t, model.EventPull, pipeline.Event) - assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit) + assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit.SHA) assert.Equal(t, "refs/pull/1/head", pipeline.Ref) assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/pull/1", pipeline.ForgeURL) assert.Equal(t, "main", pipeline.Branch) assert.Equal(t, "feature/changes:main", pipeline.Refspec) - assert.Equal(t, hook.PullRequest.Title, pipeline.Message) + assert.Equal(t, hook.PullRequest.Title, pipeline.Commit.Message) assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) assert.Equal(t, hook.PullRequest.Poster.UserName, pipeline.Author) }) diff --git a/server/forge/gitea/parse_test.go b/server/forge/gitea/parse_test.go index 5d4ade9773d..1c63969c324 100644 --- a/server/forge/gitea/parse_test.go +++ b/server/forge/gitea/parse_test.go @@ -83,15 +83,21 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "push", - Commit: "28c3613ae62640216bea5e7dc71aa65356e4298b", + Author: "6543", + Event: "push", + Commit: &model.Commit{ + SHA: "28c3613ae62640216bea5e7dc71aa65356e4298b", + Message: "Delete '.woodpecker/.check.yml'\n", + ForgeURL: "https://codeberg.org/meisam/woodpecktester/commit/28c3613ae62640216bea5e7dc71aa65356e4298b", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@obermui.de", + }, + }, Branch: "fdsafdsa", Ref: "refs/heads/fdsafdsa", - Message: "Delete '.woodpecker/.check.yml'\n", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@obermui.de", ForgeURL: "https://codeberg.org/meisam/woodpecktester/commit/28c3613ae62640216bea5e7dc71aa65356e4298b", ChangedFiles: []string{".woodpecker/.check.yml"}, }, @@ -117,15 +123,21 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "gordon", - Event: "push", - Commit: "ef98532add3b2feb7a137426bba1248724367df5", + Author: "gordon", + Event: "push", + Commit: &model.Commit{ + SHA: "ef98532add3b2feb7a137426bba1248724367df5", + Message: "bump\n", + ForgeURL: "http://gitea.golang.org/gordon/hello-world/commit/ef98532add3b2feb7a137426bba1248724367df5", + Author: model.CommitAuthor{ + Name: "gordon", + Email: "gordon@golang.org", + }, + }, Branch: "main", Ref: "refs/heads/main", - Message: "bump\n", Sender: "gordon", Avatar: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - Email: "gordon@golang.org", ForgeURL: "http://gitea.golang.org/gordon/hello-world/commit/ef98532add3b2feb7a137426bba1248724367df5", ChangedFiles: []string{"CHANGELOG.md", "app/controller/application.rb"}, }, @@ -151,15 +163,21 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "test-user", - Event: "push", - Commit: "29be01c073851cf0db0c6a466e396b725a670453", + Author: "test-user", + Event: "push", + Commit: &model.Commit{ + SHA: "29be01c073851cf0db0c6a466e396b725a670453", + Message: "add some text\n", + ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/compare/6efcf5b7c98f3e7a491675164b7a2e7acac27941...29be01c073851cf0db0c6a466e396b725a670453", + Author: model.CommitAuthor{ + Name: "test-user", + Email: "test@noreply.localhost", + }, + }, Branch: "main", Ref: "refs/heads/main", - Message: "add some text\n", Sender: "test-user", Avatar: "http://127.0.0.1:3000/avatars/dd46a756faad4727fb679320751f6dea", - Email: "test@noreply.localhost", ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/compare/6efcf5b7c98f3e7a491675164b7a2e7acac27941...29be01c073851cf0db0c6a466e396b725a670453", ChangedFiles: []string{"aaa", "aa"}, }, @@ -186,14 +204,20 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Event: model.EventTag, - Author: "gordon", - Commit: "ef98532add3b2feb7a137426bba1248724367df5", + Event: model.EventTag, + Author: "gordon", + Commit: &model.Commit{ + SHA: "ef98532add3b2feb7a137426bba1248724367df5", + ForgeURL: "http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0", + Author: model.CommitAuthor{ + Name: "gordon", + Email: "gordon@golang.org", + }, + }, Ref: "refs/tags/v1.0.0", TagTitle: "v1.0.0", Sender: "gordon", Avatar: "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - Email: "gordon@golang.org", ForgeURL: "http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0", }, }, @@ -219,17 +243,23 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "gordon", - Event: "pull_request", - Commit: "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + Author: "gordon", + Event: "pull_request", + Commit: &model.Commit{ + SHA: "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + Message: "Update the README with new information", + ForgeURL: "http://gitea.golang.org/gordon/hello-world/pull/1", + Author: model.CommitAuthor{ + Name: "gordon", + Email: "gordon@golang.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "feature/changes:main", Title: "Update the README with new information", - Message: "Update the README with new information", Sender: "gordon", Avatar: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - Email: "gordon@golang.org", ForgeURL: "http://gitea.golang.org/gordon/hello-world/pull/1", PullRequestLabels: []string{}, }, @@ -257,17 +287,23 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "6543", - Event: "pull_request", - Commit: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Author: "6543", + Event: "pull_request", + Commit: &model.Commit{ + SHA: "36b5813240a9d2daa29b05046d56a53e18f39a3e", + Message: "Some ned more AAAA", + ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", + Author: model.CommitAuthor{ + Name: "6543", + Email: "6543@noreply.codeberg.org", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "6543-patch-1:main", Title: "Some ned more AAAA", - Message: "Some ned more AAAA", Sender: "6543", Avatar: "https://codeberg.org/avatars/09a234c768cb9bca78f6b2f82d6af173", - Email: "6543@noreply.codeberg.org", ForgeURL: "https://codeberg.org/test_it/test_ci_thing/pulls/1", PullRequestLabels: []string{}, }, @@ -295,17 +331,23 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "test", - Event: "pull_request", - Commit: "788ed8d02d3b7fcfcf6386dbcbca696aa1d4dc25", + Author: "test", + Event: "pull_request", + Commit: &model.Commit{ + SHA: "788ed8d02d3b7fcfcf6386dbcbca696aa1d4dc25", + Message: "New Pull", + ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/pulls/2", + Author: model.CommitAuthor{ + Name: "test", + Email: "test@noreply.localhost", + }, + }, Branch: "main", Ref: "refs/pull/2/head", Refspec: "test-patch-1:main", Title: "New Pull", - Message: "New Pull", Sender: "test", Avatar: "http://127.0.0.1:3000/avatars/dd46a756faad4727fb679320751f6dea", - Email: "test@noreply.localhost", ForgeURL: "http://127.0.0.1:3000/Test-CI/multi-line-secrets/pulls/2", PullRequestLabels: []string{ "Kind/Bug", @@ -335,17 +377,23 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "anbraten", - Event: "pull_request_closed", - Commit: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Author: "anbraten", + Event: "pull_request_closed", + Commit: &model.Commit{ + SHA: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Message: "Adjust file", + ForgeURL: "https://gitea.com/anbraten/test-repo/pulls/1", + Author: model.CommitAuthor{ + Name: "anbraten", + Email: "anbraten@sender.gitea.com", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "anbraten-patch-1:main", Title: "Adjust file", - Message: "Adjust file", Sender: "anbraten", Avatar: "https://seccdn.libravatar.org/avatar/fc9b6fe77c6b732a02925a62a81f05a0?d=identicon", - Email: "anbraten@sender.gitea.com", ForgeURL: "https://gitea.com/anbraten/test-repo/pulls/1", PullRequestLabels: []string{}, }, @@ -356,18 +404,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"edited"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"edited"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "Edit pull title :D", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "Edit pull title :D", - Message: "Edit pull title :D", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{}, }, @@ -378,18 +432,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"edited"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"edited"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{}, }, @@ -420,18 +480,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_label repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"label_updated"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"label_updated"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{"bug", "help wanted"}, }, @@ -442,18 +508,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_label repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"label_updated"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"label_updated"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{"bug"}, }, @@ -464,18 +536,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_label repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"label_cleared"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"label_cleared"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{}, }, @@ -486,18 +564,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_milestone repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"milestoned"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"milestoned"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{"bug", "help wanted"}, PullRequestMilestone: "new mile", @@ -509,18 +593,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_milestone repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"milestoned"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"milestoned"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{"bug", "help wanted"}, PullRequestMilestone: "closed mile", @@ -532,18 +622,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_milestone repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"demilestoned"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"demilestoned"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{"bug", "help wanted"}, PullRequestMilestone: "", @@ -555,18 +651,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_assign repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"assigned"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"assigned"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{"bug"}, }, @@ -577,18 +679,24 @@ func TestGiteaParser(t *testing.T) { event: "pull_request", // type: pull_request_assign repo: pullMetaWebhookRepo, pipe: &model.Pipeline{ - Author: "jony", - Event: model.EventPullMetadata, - EventReason: []string{"unassigned"}, - Commit: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Author: "jony", + Event: model.EventPullMetadata, + EventReason: []string{"unassigned"}, + Commit: &model.Commit{ + SHA: "07977177c2cd7d46bad37b8472a9d50e7acb9d1f", + Message: "somepull", + ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", + Author: model.CommitAuthor{ + Name: "jony", + Email: "a_nice_user@noreply.example.org", + }, + }, Branch: "main", Ref: "refs/pull/7/head", Refspec: "jony-patch-1:main", Title: "somepull", - Message: "somepull", Sender: "a_nice_user", Avatar: "https://gitea.com/avatars/81027235e996f5e3ef6257152357b85d94171a2e", - Email: "a_nice_user@noreply.example.org", ForgeURL: "https://gitea.com/a_nice_user/hello_world_ci/pulls/7", PullRequestLabels: []string{"bug"}, }, @@ -615,17 +723,23 @@ func TestGiteaParser(t *testing.T) { }, }, pipe: &model.Pipeline{ - Author: "anbraten", - Event: "pull_request_closed", - Commit: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Author: "anbraten", + Event: "pull_request_closed", + Commit: &model.Commit{ + SHA: "d555a5dd07f4d0148a58d4686ec381502ae6a2d4", + Message: "Adjust file", + ForgeURL: "https://gitea.com/anbraten/test-repo/pulls/1", + Author: model.CommitAuthor{ + Name: "anbraten", + Email: "anbraten@noreply.gitea.com", + }, + }, Branch: "main", Ref: "refs/pull/1/head", Refspec: "anbraten-patch-1:main", Title: "Adjust file", - Message: "Adjust file", Sender: "anbraten", Avatar: "https://seccdn.libravatar.org/avatar/fc9b6fe77c6b732a02925a62a81f05a0?d=identicon", - Email: "anbraten@noreply.gitea.com", ForgeURL: "https://gitea.com/anbraten/test-repo/pulls/1", PullRequestLabels: []string{}, }, @@ -663,7 +777,13 @@ func TestGiteaParser(t *testing.T) { TagTitle: "0.0.5", Sender: "anbraten", Avatar: "https://git.xxx/user/avatar/anbraten/-1", - Email: "anbraten@noreply.xxx", + Commit: &model.Commit{ + ForgeURL: "https://git.xxx/anbraten/demo/releases/tag/0.0.5", + Author: model.CommitAuthor{ + Name: "anbraten", + Email: "anbraten@noreply.xxx", + }, + }, ForgeURL: "https://git.xxx/anbraten/demo/releases/tag/0.0.5", }, }, @@ -679,7 +799,9 @@ func TestGiteaParser(t *testing.T) { assert.ErrorIs(t, err, tc.err) } else if assert.NoError(t, err) { assert.EqualValues(t, tc.repo, r) - p.Timestamp = 0 + if p.Commit != nil { + p.Commit.Timestamp = 0 + } assert.EqualValues(t, tc.pipe, p) } }) diff --git a/server/forge/github/github.go b/server/forge/github/github.go index c8d8260dde5..d6904804892 100644 --- a/server/forge/github/github.go +++ b/server/forge/github/github.go @@ -271,7 +271,7 @@ func (c *client) File(ctx context.Context, u *model.User, r *model.Repo, b *mode } opts := new(github.RepositoryContentGetOptions) - opts.Ref = b.Commit + opts.Ref = b.Commit.SHA content, _, resp, err := client.Repositories.GetContents(ctx, r.Owner, r.Name, f, opts) if resp != nil && resp.StatusCode == http.StatusNotFound { return nil, errors.Join(err, &forge_types.ErrConfigNotFound{Configs: []string{f}}) @@ -293,7 +293,7 @@ func (c *client) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model } opts := new(github.RepositoryContentGetOptions) - opts.Ref = b.Commit + opts.Ref = b.Commit.SHA _, data, resp, err := client.Repositories.GetContents(ctx, r.Owner, r.Name, f, opts) if resp != nil && resp.StatusCode == http.StatusNotFound { return nil, errors.Join(err, &forge_types.ErrConfigNotFound{Configs: []string{f}}) @@ -596,7 +596,7 @@ func (c *client) Status(ctx context.Context, user *model.User, repo *model.Repo, return err } - _, _, err = client.Repositories.CreateStatus(ctx, repo.Owner, repo.Name, pipeline.Commit, github.RepoStatus{ + _, _, err = client.Repositories.CreateStatus(ctx, repo.Owner, repo.Name, pipeline.Commit.SHA, github.RepoStatus{ Context: github.Ptr(common.GetPipelineStatusContext(repo, pipeline, workflow)), State: github.Ptr(convertStatus(workflow.State)), Description: github.Ptr(common.GetPipelineStatusDescription(workflow.State)), @@ -688,12 +688,15 @@ func (c *client) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model if pipeline.TagTitle == "" { pipeline.TagTitle = strings.Split(pipeline.Ref, "/")[2] } - if pipeline.Commit == "" { + if pipeline.Commit == nil || pipeline.Commit.SHA == "" { sha, err := c.getTagCommitSHA(ctx, repo, pipeline.TagTitle) if err != nil { return nil, nil, err } - pipeline.Commit = sha + if pipeline.Commit == nil { + pipeline.Commit = &model.Commit{} + } + pipeline.Commit.SHA = sha } } } diff --git a/server/forge/github/github_test.go b/server/forge/github/github_test.go index 7ffc1fafb29..05a78e530cc 100644 --- a/server/forge/github/github_test.go +++ b/server/forge/github/github_test.go @@ -194,12 +194,12 @@ func TestHook(t *testing.T) { assert.Equal(t, model.EventPush, pipeline.Event) assert.Equal(t, "main", pipeline.Branch) assert.Equal(t, "refs/heads/main", pipeline.Ref) - assert.Equal(t, "366701fde727cb7a9e7f21eb88264f59f6f9b89c", pipeline.Commit) - assert.Equal(t, "Fix multiline secrets replacer (#700)\n\n* Fix multiline secrets replacer\r\n\r\n* Add tests", pipeline.Message) + assert.Equal(t, "366701fde727cb7a9e7f21eb88264f59f6f9b89c", pipeline.Commit.SHA) + assert.Equal(t, "Fix multiline secrets replacer (#700)\n\n* Fix multiline secrets replacer\r\n\r\n* Add tests", pipeline.Commit.Message) assert.Equal(t, "https://github.com/woodpecker-ci/woodpecker/commit/366701fde727cb7a9e7f21eb88264f59f6f9b89c", pipeline.ForgeURL) assert.Equal(t, "6543", pipeline.Author) assert.Equal(t, "https://avatars.githubusercontent.com/u/24977596?v=4", pipeline.Avatar) - assert.Equal(t, "admin@philipp.info", pipeline.Email) + assert.Equal(t, "admin@philipp.info", pipeline.Commit.Author.Email) assert.Equal(t, []string{"main.go"}, pipeline.ChangedFiles) }) @@ -219,8 +219,8 @@ func TestHook(t *testing.T) { assert.Equal(t, "main", pipeline.Branch) assert.Equal(t, "refs/pull/1/head", pipeline.Ref) assert.Equal(t, "changes:main", pipeline.Refspec) - assert.Equal(t, "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", pipeline.Commit) - assert.Equal(t, "Update the README with new information", pipeline.Message) + assert.Equal(t, "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", pipeline.Commit.SHA) + assert.Equal(t, "Update the README with new information", pipeline.Commit.Message) assert.Equal(t, "Update the README with new information", pipeline.Title) assert.Equal(t, "baxterthehacker", pipeline.Author) assert.Equal(t, "https://avatars.githubusercontent.com/u/6752317?v=3", pipeline.Avatar) @@ -243,8 +243,8 @@ func TestHook(t *testing.T) { assert.Equal(t, model.EventDeploy, pipeline.Event) assert.Equal(t, "main", pipeline.Branch) assert.Equal(t, "refs/heads/main", pipeline.Ref) - assert.Equal(t, "9049f1265b7d61be4a8904a9a27120d2064dab3b", pipeline.Commit) - assert.Equal(t, "", pipeline.Message) + assert.Equal(t, "9049f1265b7d61be4a8904a9a27120d2064dab3b", pipeline.Commit.SHA) + assert.Equal(t, "", pipeline.Commit.Message) assert.Equal(t, "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692", pipeline.ForgeURL) assert.Equal(t, "baxterthehacker", pipeline.Author) assert.Equal(t, "https://avatars.githubusercontent.com/u/6752317?v=3", pipeline.Avatar) @@ -265,12 +265,12 @@ func TestHook(t *testing.T) { assert.Equal(t, model.EventTag, pipeline.Event) assert.Equal(t, "main", pipeline.Branch) assert.Equal(t, "refs/tags/the-tag-v1", pipeline.Ref) - assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", pipeline.Commit) + assert.Equal(t, "67012991d6c69b1c58378346fca366b864d8d1a1", pipeline.Commit.SHA) assert.Equal(t, "the-tag-v1", pipeline.TagTitle) assert.Equal(t, "https://github.com/6543/test_ci_tmp/commit/67012991d6c69b1c58378346fca366b864d8d1a1", pipeline.ForgeURL) assert.Equal(t, "6543", pipeline.Author) assert.Equal(t, "https://avatars.githubusercontent.com/u/24977596?v=4", pipeline.Avatar) - assert.Equal(t, "6543@obermui.de", pipeline.Email) + assert.Equal(t, "6543@obermui.de", pipeline.Commit.Author.Email) assert.Empty(t, pipeline.ChangedFiles) }) } diff --git a/server/forge/github/parse.go b/server/forge/github/parse.go index 2334d301540..01ef06ad503 100644 --- a/server/forge/github/parse.go +++ b/server/forge/github/parse.go @@ -99,13 +99,19 @@ func parsePushHook(hook *github.PushEvent) (_ *model.Repo, _ *model.Pipeline, cu } pipeline := &model.Pipeline{ - Event: model.EventPush, - Commit: hook.GetHeadCommit().GetID(), + Event: model.EventPush, + Commit: &model.Commit{ + SHA: hook.GetHeadCommit().GetID(), + Message: hook.GetHeadCommit().GetMessage(), + ForgeURL: hook.GetHeadCommit().GetURL(), + Author: model.CommitAuthor{ + Name: hook.GetSender().GetLogin(), + Email: hook.GetHeadCommit().GetAuthor().GetEmail(), + }, + }, Ref: hook.GetRef(), ForgeURL: hook.GetHeadCommit().GetURL(), Branch: strings.TrimPrefix(hook.GetRef(), "refs/heads/"), - Message: hook.GetHeadCommit().GetMessage(), - Email: hook.GetHeadCommit().GetAuthor().GetEmail(), Avatar: hook.GetSender().GetAvatarURL(), Author: hook.GetSender().GetLogin(), Sender: hook.GetSender().GetLogin(), @@ -114,6 +120,7 @@ func parsePushHook(hook *github.PushEvent) (_ *model.Repo, _ *model.Pipeline, cu if len(pipeline.Author) == 0 { pipeline.Author = hook.GetHeadCommit().GetAuthor().GetLogin() + pipeline.Commit.Author.Name = pipeline.Author } if strings.HasPrefix(pipeline.Ref, "refs/tags/") { // just kidding, this is actually a tag event. Why did this come as a push @@ -140,10 +147,16 @@ func parsePushHook(hook *github.PushEvent) (_ *model.Repo, _ *model.Pipeline, cu // If the commit type is unsupported nil values are returned. func parseDeployHook(hook *github.DeploymentEvent) (*model.Repo, *model.Pipeline) { pipeline := &model.Pipeline{ - Event: model.EventDeploy, - Commit: hook.GetDeployment().GetSHA(), + Event: model.EventDeploy, + Commit: &model.Commit{ + SHA: hook.GetDeployment().GetSHA(), + Message: hook.GetDeployment().GetDescription(), + ForgeURL: hook.GetDeployment().GetURL(), + Author: model.CommitAuthor{ + Name: hook.GetSender().GetLogin(), + }, + }, ForgeURL: hook.GetDeployment().GetURL(), - Message: hook.GetDeployment().GetDescription(), Ref: hook.GetDeployment().GetRef(), Branch: hook.GetDeployment().GetRef(), Avatar: hook.GetSender().GetAvatarURL(), @@ -153,7 +166,7 @@ func parseDeployHook(hook *github.DeploymentEvent) (*model.Repo, *model.Pipeline DeployTask: hook.GetDeployment().GetTask(), } // if the ref is a sha or short sha we need to manually construct the ref. - if strings.HasPrefix(pipeline.Commit, pipeline.Ref) || pipeline.Commit == pipeline.Ref { + if strings.HasPrefix(pipeline.Commit.SHA, pipeline.Ref) || pipeline.Commit.SHA == pipeline.Ref { pipeline.Branch = hook.GetRepo().GetDefaultBranch() pipeline.Ref = fmt.Sprintf("refs/heads/%s", pipeline.Branch) } @@ -202,15 +215,21 @@ func parsePullHook(hook *github.PullRequestEvent, merge bool) (*github.PullReque pipeline := &model.Pipeline{ Event: event, EventReason: []string{eventAction}, - Commit: hook.GetPullRequest().GetHead().GetSHA(), - ForgeURL: hook.GetPullRequest().GetHTMLURL(), - Ref: fmt.Sprintf(headRefs, hook.GetPullRequest().GetNumber()), - Branch: hook.GetPullRequest().GetBase().GetRef(), - Message: hook.GetPullRequest().GetTitle(), - Author: hook.GetPullRequest().GetUser().GetLogin(), - Avatar: hook.GetPullRequest().GetUser().GetAvatarURL(), - Title: hook.GetPullRequest().GetTitle(), - Sender: hook.GetSender().GetLogin(), + Commit: &model.Commit{ + SHA: hook.GetPullRequest().GetHead().GetSHA(), + Message: hook.GetPullRequest().GetTitle(), + ForgeURL: hook.GetPullRequest().GetHTMLURL(), + Author: model.CommitAuthor{ + Name: hook.GetPullRequest().GetUser().GetLogin(), + }, + }, + ForgeURL: hook.GetPullRequest().GetHTMLURL(), + Ref: fmt.Sprintf(headRefs, hook.GetPullRequest().GetNumber()), + Branch: hook.GetPullRequest().GetBase().GetRef(), + Author: hook.GetPullRequest().GetUser().GetLogin(), + Avatar: hook.GetPullRequest().GetUser().GetAvatarURL(), + Title: hook.GetPullRequest().GetTitle(), + Sender: hook.GetSender().GetLogin(), Refspec: fmt.Sprintf( refSpec, hook.GetPullRequest().GetHead().GetRef(), diff --git a/server/forge/gitlab/convert.go b/server/forge/gitlab/convert.go index 42eafc28f8a..ad50ae8abc0 100644 --- a/server/forge/gitlab/convert.go +++ b/server/forge/gitlab/convert.go @@ -215,20 +215,24 @@ func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (mergeI lastCommit := obj.LastCommit - pipeline.Message = lastCommit.Message - pipeline.Commit = lastCommit.ID + pipeline.Commit = &model.Commit{ + SHA: lastCommit.ID, + Message: lastCommit.Message, + ForgeURL: obj.URL, + Author: model.CommitAuthor{ + Name: hook.User.Username, + Email: lastCommit.Author.Email, + }, + } pipeline.Ref = fmt.Sprintf(mergeRefs, obj.IID) pipeline.Branch = obj.SourceBranch pipeline.Refspec = fmt.Sprintf("%s:%s", obj.SourceBranch, obj.TargetBranch) - author := lastCommit.Author - pipeline.Author = hook.User.Username - pipeline.Email = author.Email - if len(pipeline.Email) != 0 { - pipeline.Avatar = getUserAvatar(pipeline.Email) + if len(pipeline.Commit.Author.Email) != 0 { + pipeline.Avatar = getUserAvatar(pipeline.Commit.Author.Email) } pipeline.Title = obj.Title @@ -276,7 +280,7 @@ func convertPushHook(hook *gitlab.PushEvent) (*model.Repo, *model.Pipeline, erro } pipeline.Event = model.EventPush - pipeline.Commit = hook.After + pipeline.Commit = &model.Commit{SHA: hook.After} pipeline.Branch = strings.TrimPrefix(hook.Ref, "refs/heads/") pipeline.Ref = hook.Ref @@ -286,11 +290,14 @@ func convertPushHook(hook *gitlab.PushEvent) (*model.Repo, *model.Pipeline, erro files := make([]string, 0, len(hook.Commits)*4) for _, cm := range hook.Commits { if hook.After == cm.ID { - pipeline.Email = cm.Author.Email - pipeline.Message = cm.Message - pipeline.Timestamp = cm.Timestamp.Unix() - if len(pipeline.Email) != 0 { - pipeline.Avatar = getUserAvatar(pipeline.Email) + pipeline.Commit.Message = cm.Message + pipeline.Commit.Timestamp = cm.Timestamp.Unix() + pipeline.Commit.Author = model.CommitAuthor{ + Name: hook.UserUsername, + Email: cm.Author.Email, + } + if len(pipeline.Commit.Author.Email) != 0 { + pipeline.Avatar = getUserAvatar(pipeline.Commit.Author.Email) } } @@ -336,18 +343,22 @@ func convertTagHook(hook *gitlab.TagEvent) (*model.Repo, *model.Pipeline, string pipeline.Event = model.EventTag pipeline.TagTitle = strings.TrimPrefix(strings.TrimPrefix(hook.Ref, "refs/heads/"), "refs/tags/") - pipeline.Commit = hook.After + pipeline.Commit = &model.Commit{SHA: hook.After} pipeline.Ref = hook.Ref pipeline.Author = hook.UserUsername pipeline.ForgeURL = fmt.Sprintf("%s/-/tags/%s", repo.ForgeURL, pipeline.TagTitle) + pipeline.Commit.ForgeURL = pipeline.ForgeURL for _, cm := range hook.Commits { if hook.After == cm.ID { - pipeline.Email = cm.Author.Email - pipeline.Message = cm.Message - pipeline.Timestamp = cm.Timestamp.Unix() - if len(pipeline.Email) != 0 { - pipeline.Avatar = getUserAvatar(pipeline.Email) + pipeline.Commit.Message = cm.Message + pipeline.Commit.Timestamp = cm.Timestamp.Unix() + pipeline.Commit.Author = model.CommitAuthor{ + Name: hook.UserUsername, + Email: cm.Author.Email, + } + if len(pipeline.Commit.Author.Email) != 0 { + pipeline.Avatar = getUserAvatar(pipeline.Commit.Author.Email) } break } @@ -391,15 +402,21 @@ func convertReleaseHook(hook *gitlab.ReleaseEvent) (*model.Repo, *model.Pipeline } pipeline := &model.Pipeline{ - Event: model.EventRelease, - Commit: hook.Commit.ID, + Event: model.EventRelease, + Commit: &model.Commit{ + SHA: hook.Commit.ID, + ForgeURL: hook.URL, + Author: model.CommitAuthor{ + Name: hook.Commit.Author.Name, + Email: hook.Commit.Author.Email, + }, + }, ForgeURL: hook.URL, Sender: hook.Commit.Author.Name, // Using the commit author here as Gitlab does not send the hook user. // This is not an issue because releases can be created by users with // push permissions only anyways. Author: hook.Commit.Author.Name, - Email: hook.Commit.Author.Email, Release: &model.Release{Title: hook.Name}, @@ -408,8 +425,8 @@ func convertReleaseHook(hook *gitlab.ReleaseEvent) (*model.Repo, *model.Pipeline Ref: "refs/tags/" + hook.Tag, TagTitle: hook.Tag, } - if len(pipeline.Email) != 0 { - pipeline.Avatar = getUserAvatar(pipeline.Email) + if len(pipeline.Commit.Author.Email) != 0 { + pipeline.Avatar = getUserAvatar(pipeline.Commit.Author.Email) } return repo, pipeline, nil diff --git a/server/forge/gitlab/gitlab.go b/server/forge/gitlab/gitlab.go index 30e1276076b..d8ad86699d5 100644 --- a/server/forge/gitlab/gitlab.go +++ b/server/forge/gitlab/gitlab.go @@ -366,7 +366,11 @@ func (g *GitLab) File(ctx context.Context, user *model.User, repo *model.Repo, p if err != nil { return nil, err } - file, resp, err := client.RepositoryFiles.GetRawFile(_repo.ID, fileName, &gitlab.GetRawFileOptions{Ref: &pipeline.Commit}, gitlab.WithContext(ctx)) + commitRef := "" + if pipeline.Commit != nil { + commitRef = pipeline.Commit.SHA + } + file, resp, err := client.RepositoryFiles.GetRawFile(_repo.ID, fileName, &gitlab.GetRawFileOptions{Ref: &commitRef}, gitlab.WithContext(ctx)) if resp != nil && resp.StatusCode == http.StatusNotFound { return nil, errors.Join(err, &forge_types.ErrConfigNotFound{Configs: []string{fileName}}) } @@ -386,10 +390,14 @@ func (g *GitLab) Dir(ctx context.Context, user *model.User, repo *model.Repo, pi return nil, err } + commitRef := "" + if pipeline.Commit != nil { + commitRef = pipeline.Commit.SHA + } opts := &gitlab.ListTreeOptions{ ListOptions: gitlab.ListOptions{PerPage: defaultPerPage}, Path: &path, - Ref: &pipeline.Commit, + Ref: &commitRef, Recursive: gitlab.Ptr(false), } @@ -437,7 +445,7 @@ func (g *GitLab) Status(ctx context.Context, user *model.User, repo *model.Repo, return err } - _, _, err = client.Commits.SetCommitStatus(_repo.ID, pipeline.Commit, &gitlab.SetCommitStatusOptions{ + _, _, err = client.Commits.SetCommitStatus(_repo.ID, pipeline.Commit.SHA, &gitlab.SetCommitStatusOptions{ State: getStatus(workflow.State), Description: gitlab.Ptr(common.GetPipelineStatusDescription(workflow.State)), TargetURL: gitlab.Ptr(common.GetPipelineStatusURL(repo, pipeline, workflow)), @@ -653,7 +661,7 @@ func (g *GitLab) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod return convertPushHook(event) case *gitlab.TagEvent: repo, pipeline, cmID, err := convertTagHook(event) - if err != nil || pipeline.Message != "" { + if err != nil || (pipeline.Commit != nil && pipeline.Commit.Message != "") { return repo, pipeline, err } @@ -906,11 +914,15 @@ func (g *GitLab) loadCommitFromSHA(ctx context.Context, tmpRepo *model.Repo, pip } pipeline.Author = cm.AuthorName - pipeline.Email = cm.AuthorEmail - pipeline.Message = cm.Message - pipeline.Timestamp = cm.CommittedDate.Unix() - if len(pipeline.Email) != 0 { - pipeline.Avatar = getUserAvatar(pipeline.Email) + if pipeline.Commit == nil { + pipeline.Commit = &model.Commit{} + } + pipeline.Commit.Message = cm.Message + pipeline.Commit.Timestamp = cm.CommittedDate.Unix() + pipeline.Commit.Author.Name = cm.AuthorName + pipeline.Commit.Author.Email = cm.AuthorEmail + if len(pipeline.Commit.Author.Email) != 0 { + pipeline.Avatar = getUserAvatar(pipeline.Commit.Author.Email) } return pipeline, nil diff --git a/server/model/commit.go b/server/model/commit.go index 67b7362862e..ff869dbe2d5 100644 --- a/server/model/commit.go +++ b/server/model/commit.go @@ -15,6 +15,14 @@ package model type Commit struct { - SHA string - ForgeURL string + SHA string `json:"sha"` + Message string `json:"message"` + ForgeURL string `json:"forge_url"` + Author CommitAuthor `json:"author"` + Timestamp int64 `json:"timestamp"` +} + +type CommitAuthor struct { + Name string `json:"name"` + Email string `json:"email"` } diff --git a/server/model/feed.go b/server/model/feed.go index f1690823040..5c7c5f42c22 100644 --- a/server/model/feed.go +++ b/server/model/feed.go @@ -19,35 +19,37 @@ import "fmt" // Feed represents an item in the user's feed or timeline. type Feed struct { - RepoID int64 `json:"repo_id" xorm:"repo_id"` - ID int64 `json:"id,omitempty" xorm:"pipeline_id"` - Number int64 `json:"number,omitempty" xorm:"pipeline_number"` - Event WebhookEvent `json:"event,omitempty" xorm:"pipeline_event"` - Status string `json:"status,omitempty" xorm:"pipeline_status"` - Created int64 `json:"created,omitempty" xorm:"pipeline_created"` - Started int64 `json:"started,omitempty" xorm:"pipeline_started"` - Finished int64 `json:"finished,omitempty" xorm:"pipeline_finished"` - Commit string `json:"commit,omitempty" xorm:"pipeline_commit"` - Branch string `json:"branch,omitempty" xorm:"pipeline_branch"` - Ref string `json:"ref,omitempty" xorm:"pipeline_ref"` - Refspec string `json:"refspec,omitempty" xorm:"pipeline_refspec"` - Title string `json:"title,omitempty" xorm:"pipeline_title"` - Author string `json:"author,omitempty" xorm:"pipeline_author"` - Avatar string `json:"author_avatar,omitempty" xorm:"pipeline_avatar"` - Email string `json:"author_email,omitempty" xorm:"pipeline_email"` + RepoID int64 `json:"repo_id" xorm:"repo_id"` + ID int64 `json:"id,omitempty" xorm:"pipeline_id"` + Number int64 `json:"number,omitempty" xorm:"pipeline_number"` + Event WebhookEvent `json:"event,omitempty" xorm:"pipeline_event"` + Status string `json:"status,omitempty" xorm:"pipeline_status"` + Created int64 `json:"created,omitempty" xorm:"pipeline_created"` + Started int64 `json:"started,omitempty" xorm:"pipeline_started"` + Finished int64 `json:"finished,omitempty" xorm:"pipeline_finished"` + Commit *Commit `json:"commit_pipeline,omitempty" xorm:"json 'pipeline_commit'"` // TODO change json to 'commit' in next major + Branch string `json:"branch,omitempty" xorm:"pipeline_branch"` + Ref string `json:"ref,omitempty" xorm:"pipeline_ref"` + Refspec string `json:"refspec,omitempty" xorm:"pipeline_refspec"` + Title string `json:"title,omitempty" xorm:"pipeline_title"` + Author string `json:"author,omitempty" xorm:"pipeline_author"` + Avatar string `json:"author_avatar,omitempty" xorm:"pipeline_avatar"` // Ongoing Work: https://github.com/woodpecker-ci/woodpecker/pull/4626 // // New Release *Release `json:"release,omitempty" xorm:"json 'pipeline_release'"` TagTitle string `json:"tag_title,omitempty" xorm:"pipeline_tag_title"` - // // Deprecated - Message string `json:"message,omitempty" xorm:"pipeline_message"` } func (f *Feed) ToAPIModel() *APIFeed { af := &APIFeed{ Feed: f, } + if f.Commit != nil { + af.Commit = f.Commit.SHA + af.Message = f.Commit.Message + af.Email = f.Commit.Author.Email + } switch af.Event { case EventTag: af.Message = fmt.Sprintf("created tag %s", af.TagTitle) @@ -64,4 +66,8 @@ func (f *Feed) ToAPIModel() *APIFeed { // APIFeed TODO remove in next major. type APIFeed struct { *Feed + + Commit string `json:"commit,omitempty"` // deprecated, use commit_pipeline.sha instead + Message string `json:"message,omitempty"` // deprecated, use commit_pipeline.message instead + Email string `json:"author_email,omitempty"` // deprecated, use commit_pipeline.author.email instead } // @name Feed diff --git a/server/model/pipeline.go b/server/model/pipeline.go index 0be58e50b07..6937d849327 100644 --- a/server/model/pipeline.go +++ b/server/model/pipeline.go @@ -38,7 +38,7 @@ type Pipeline struct { Finished int64 `json:"finished" xorm:"finished"` DeployTo string `json:"deploy_to" xorm:"deploy"` DeployTask string `json:"deploy_task" xorm:"deploy_task"` - Commit string `json:"commit" xorm:"commit"` + Commit *Commit `json:"commit_pipeline" xorm:"json 'commit'"` // TODO change json to 'commit' in next major Branch string `json:"branch" xorm:"branch"` RerunCount int64 `json:"rerun_count" xorm:"rerun_count"` Ref string `json:"ref" xorm:"ref"` @@ -63,11 +63,8 @@ type Pipeline struct { Release *Release `json:"release,omitempty" xorm:"json 'release'"` TagTitle string `json:"tag_title,omitempty" xorm:"tag_title"` // // Deprecated - Title string `json:"title" xorm:"title"` - Message string `json:"message" xorm:"TEXT 'message'"` - Timestamp int64 `json:"timestamp" xorm:"'timestamp'"` - Sender string `json:"sender" xorm:"sender"` // uses reported user for webhooks and name of cron for cron pipelines - Email string `json:"author_email" xorm:"varchar(500) email"` + Title string `json:"title" xorm:"title"` + Sender string `json:"sender" xorm:"sender"` // uses reported user for webhooks and name of cron for cron pipelines } // APIPipeline TODO remove deprecated properties in next major. @@ -75,6 +72,11 @@ type APIPipeline struct { *Pipeline IsPrerelease bool `json:"is_prerelease,omitempty"` // deprecated, use release.is_prerelease instead + + Commit string `json:"commit"` // deprecated, use commit_pipeline.sha instead + Message string `json:"message"` // deprecated, use commit_pipeline.message instead + Timestamp int64 `json:"timestamp"` // deprecated, use commit_pipeline.timestamp instead + Email string `json:"author_email"` // deprecated, use commit_pipeline.author.email instead } // @name Pipeline // TableName return database table name for xorm. @@ -87,6 +89,13 @@ func (p *Pipeline) ToAPIModel() *APIPipeline { Pipeline: p, } + if p.Commit != nil { + ap.Commit = p.Commit.SHA + ap.Message = p.Commit.Message + ap.Timestamp = p.Commit.Timestamp + ap.Email = p.Commit.Author.Email + } + switch p.Event { case EventCron: ap.Message = p.Cron diff --git a/server/model/pipeline_test.go b/server/model/pipeline_test.go index e728fbae6ef..a9417178f3a 100644 --- a/server/model/pipeline_test.go +++ b/server/model/pipeline_test.go @@ -28,6 +28,9 @@ func TestPipelineToAPIModel(t *testing.T) { wantMessage string wantSender string wantIsPrerelease bool + wantCommit string + wantTimestamp int64 + wantEmail string }{ { name: "cron uses cron name as message and sender", @@ -58,10 +61,26 @@ func TestPipelineToAPIModel(t *testing.T) { }, { name: "push leaves derived fields untouched", - pipeline: Pipeline{Event: EventPush, Message: "fix bug"}, + pipeline: Pipeline{Event: EventPush, Commit: &Commit{Message: "fix bug"}}, // message is the stored commit message, not overwritten wantMessage: "fix bug", }, + { + name: "commit substruct is exposed via the deprecated fields", + pipeline: Pipeline{ + Event: EventPush, + Commit: &Commit{ + SHA: "cafe1234", + Message: "fix bug", + Timestamp: 1700000000, + Author: CommitAuthor{Name: "alice", Email: "alice@example.com"}, + }, + }, + wantCommit: "cafe1234", + wantMessage: "fix bug", + wantTimestamp: 1700000000, + wantEmail: "alice@example.com", + }, } for _, tc := range tests { @@ -72,6 +91,9 @@ func TestPipelineToAPIModel(t *testing.T) { assert.Equal(t, tc.wantMessage, ap.Message) assert.Equal(t, tc.wantSender, ap.Sender) assert.Equal(t, tc.wantIsPrerelease, ap.IsPrerelease) + assert.Equal(t, tc.wantCommit, ap.Commit) + assert.Equal(t, tc.wantTimestamp, ap.Timestamp) + assert.Equal(t, tc.wantEmail, ap.Email) }) } } diff --git a/server/pipeline/create.go b/server/pipeline/create.go index 26a6a62949a..8b1c1ae583a 100644 --- a/server/pipeline/create.go +++ b/server/pipeline/create.go @@ -40,12 +40,18 @@ func Create(ctx context.Context, _store store.Store, repo *model.Repo, pipeline return nil, errors.New(msg) } - if constraint.IsSkipCommitMessage(metadata.Event(pipeline.Event), pipeline.Message) { - ref := pipeline.Commit + var commitMessage, commitSHA string + if pipeline.Commit != nil { + commitMessage = pipeline.Commit.Message + commitSHA = pipeline.Commit.SHA + } + + if constraint.IsSkipCommitMessage(metadata.Event(pipeline.Event), commitMessage) { + ref := commitSHA if len(ref) == 0 { ref = pipeline.Ref } - log.Debug().Str("repo", repo.FullName).Msgf("ignoring pipeline as skip-ci was found in the commit (%s) message '%s'", ref, pipeline.Message) + log.Debug().Str("repo", repo.FullName).Msgf("ignoring pipeline as skip-ci was found in the commit (%s) message '%s'", ref, commitMessage) return nil, ErrFiltered } diff --git a/server/pipeline/metadata/metadata.go b/server/pipeline/metadata/metadata.go index 3b4f6f2cdd3..92e1b0e34b0 100644 --- a/server/pipeline/metadata/metadata.go +++ b/server/pipeline/metadata/metadata.go @@ -126,6 +126,15 @@ func metadataPipelineFromModelPipeline(pipeline *model.Pipeline, includeParent b parent = pipeline.Parent } + var commitSHA, commitMessage, commitEmail string + var commitTimestamp int64 + if pipeline.Commit != nil { + commitSHA = pipeline.Commit.SHA + commitMessage = pipeline.Commit.Message + commitTimestamp = pipeline.Commit.Timestamp + commitEmail = pipeline.Commit.Author.Email + } + metadata := metadata.Pipeline{ Number: pipeline.Number, Parent: parent, @@ -140,15 +149,15 @@ func metadataPipelineFromModelPipeline(pipeline *model.Pipeline, includeParent b DeployTo: pipeline.DeployTo, DeployTask: pipeline.DeployTask, Commit: metadata.Commit{ - Sha: pipeline.Commit, + Sha: commitSHA, Ref: pipeline.Ref, Refspec: pipeline.Refspec, Branch: pipeline.Branch, - Message: pipeline.Message, - Timestamp: pipeline.Timestamp, + Message: commitMessage, + Timestamp: commitTimestamp, Author: metadata.Author{ Name: pipeline.Author, - Email: pipeline.Email, + Email: commitEmail, }, ChangedFiles: pipeline.ChangedFiles, PullRequestLabels: pipeline.PullRequestLabels, diff --git a/server/pipeline/metadata/metadata_test.go b/server/pipeline/metadata/metadata_test.go index 238316bf5ce..cccea57cb1f 100644 --- a/server/pipeline/metadata/metadata_test.go +++ b/server/pipeline/metadata/metadata_test.go @@ -74,8 +74,8 @@ func TestGetWorkflowMetadata(t *testing.T) { name: "Test with forge", forge: forge, repo: &model.Repo{FullName: "testUser/testRepo", ForgeURL: "https://gitea.com/testUser/testRepo", Clone: "https://gitea.com/testUser/testRepo.git", CloneSSH: "git@gitea.com:testUser/testRepo.git", Branch: "main", IsSCMPrivate: true}, - pipeline: &model.Pipeline{Number: 3, Timestamp: 1722617519, ChangedFiles: []string{"test.go", "markdown file.md"}}, - prev: &model.Pipeline{Number: 2, Timestamp: 1722610173}, + pipeline: &model.Pipeline{Number: 3, Commit: &model.Commit{Timestamp: 1722617519}, ChangedFiles: []string{"test.go", "markdown file.md"}}, + prev: &model.Pipeline{Number: 2, Commit: &model.Commit{Timestamp: 1722610173}}, workflow: &builder.Workflow{Name: "hello"}, sysURL: "https://example.com", expectedMetadata: metadata.Metadata{ diff --git a/server/services/config/combined_test.go b/server/services/config/combined_test.go index fb8e2914cc2..bd588a4690a 100644 --- a/server/services/config/combined_test.go +++ b/server/services/config/combined_test.go @@ -228,7 +228,7 @@ func TestFetchFromConfigService(t *testing.T) { f, &model.User{AccessToken: "xxx"}, repo, - &model.Pipeline{Commit: "89ab7b2d6bfb347144ac7c557e638ab402848fee"}, + &model.Pipeline{Commit: &model.Commit{SHA: "89ab7b2d6bfb347144ac7c557e638ab402848fee"}}, []*forge_types.FileMeta{}, false, ) diff --git a/server/services/config/forge_test.go b/server/services/config/forge_test.go index d4dc7f21843..36412b9e829 100644 --- a/server/services/config/forge_test.go +++ b/server/services/config/forge_test.go @@ -316,7 +316,7 @@ func TestFetch(t *testing.T) { f, &model.User{AccessToken: "xxx"}, repo, - &model.Pipeline{Commit: "89ab7b2d6bfb347144ac7c557e638ab402848fee"}, + &model.Pipeline{Commit: &model.Commit{SHA: "89ab7b2d6bfb347144ac7c557e638ab402848fee"}}, nil, false, ) diff --git a/server/store/datastore/config_test.go b/server/store/datastore/config_test.go index 81a0114d0ef..fbeaa76fac7 100644 --- a/server/store/datastore/config_test.go +++ b/server/store/datastore/config_test.go @@ -53,7 +53,7 @@ func TestConfig(t *testing.T) { pipeline := &model.Pipeline{ RepoID: repo.ID, Status: model.StatusRunning, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", + Commit: &model.Commit{SHA: "85f8c029b902ed9400bc600bac301a0aadb144ac"}, } assert.NoError(t, store.CreatePipeline(pipeline)) diff --git a/server/store/datastore/feed.go b/server/store/datastore/feed.go index 37e3ac5a57c..b5256f747af 100644 --- a/server/store/datastore/feed.go +++ b/server/store/datastore/feed.go @@ -36,9 +36,7 @@ pipelines.branch as pipeline_branch, pipelines.ref as pipeline_ref, pipelines.refspec as pipeline_refspec, pipelines.title as pipeline_title, -pipelines.message as pipeline_message, pipelines.author as pipeline_author, -pipelines.email as pipeline_email, pipelines.avatar as pipeline_avatar, pipelines.release as pipeline_release, pipelines.tag_title as pipeline_tag_title` diff --git a/server/store/datastore/feed_test.go b/server/store/datastore/feed_test.go index 705603c0611..f2e037643f4 100644 --- a/server/store/datastore/feed_test.go +++ b/server/store/datastore/feed_test.go @@ -48,17 +48,21 @@ func TestGetPipelineQueue(t *testing.T) { assert.NoError(t, store.PermUpsert(perm)) } pipeline1 := &model.Pipeline{ - RepoID: repo1.ID, - Status: model.StatusPending, - Number: 1, - Event: "push", - Commit: "abc123", - Branch: "main", - Ref: "refs/heads/main", - Message: "Initial commit", - Author: "joe", - Email: "foo@bar.com", - Title: "First pipeline", + RepoID: repo1.ID, + Status: model.StatusPending, + Number: 1, + Event: "push", + Commit: &model.Commit{ + SHA: "abc123", + Message: "Initial commit", + Author: model.CommitAuthor{ + Email: "foo@bar.com", + }, + }, + Branch: "main", + Ref: "refs/heads/main", + Author: "joe", + Title: "First pipeline", } assert.NoError(t, store.CreatePipeline(pipeline1)) @@ -72,13 +76,13 @@ func TestGetPipelineQueue(t *testing.T) { assert.Equal(t, pipeline1.Number, feedItem.Number) assert.EqualValues(t, pipeline1.Event, feedItem.Event) assert.EqualValues(t, pipeline1.Status, feedItem.Status) - assert.Equal(t, pipeline1.Commit, feedItem.Commit) + assert.Equal(t, pipeline1.Commit.SHA, feedItem.Commit.SHA) assert.Equal(t, pipeline1.Branch, feedItem.Branch) assert.Equal(t, pipeline1.Ref, feedItem.Ref) assert.Equal(t, pipeline1.Title, feedItem.Title) - assert.Equal(t, pipeline1.Message, feedItem.Message) + assert.Equal(t, pipeline1.Commit.Message, feedItem.Commit.Message) assert.Equal(t, pipeline1.Author, feedItem.Author) - assert.Equal(t, pipeline1.Email, feedItem.Email) + assert.Equal(t, pipeline1.Commit.Author.Email, feedItem.Commit.Author.Email) } func TestUserFeed(t *testing.T) { diff --git a/server/store/datastore/migration/029_update_pipeline_structure_commit.go b/server/store/datastore/migration/029_update_pipeline_structure_commit.go new file mode 100644 index 00000000000..2e3840fd7f3 --- /dev/null +++ b/server/store/datastore/migration/029_update_pipeline_structure_commit.go @@ -0,0 +1,161 @@ +// Copyright 2026 Woodpecker Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package migration + +import ( + "encoding/json" + "fmt" + "reflect" + "strings" + + "src.techknowlogick.com/xormigrate" + "xorm.io/xorm" + "xorm.io/xorm/schemas" +) + +var updatePipelineStructureCommit = xormigrate.Migration{ + ID: "update-pipeline-structure_commit", + MigrateSession: func(sess *xorm.Session) error { + // perPage sets the size of the slice to read per page. + const perPage = 100 + + type commitAuthor struct { + Name string `json:"name"` + Email string `json:"email"` + } + + type commit struct { + SHA string `json:"sha"` + Message string `json:"message"` + ForgeURL string `json:"forge_url"` + Author commitAuthor `json:"author"` + Timestamp int64 `json:"timestamp"` + } + + type pipelines struct { + ID int64 `xorm:"pk autoincr 'id'"` + Author string `xorm:"INDEX 'author'"` + ForgeURL string `xorm:"forge_url"` + + // old columns, folded into the commit substruct below + Commit string `xorm:"commit"` + Message string `xorm:"TEXT 'message'"` + Timestamp int64 `xorm:"'timestamp'"` + Email string `xorm:"varchar(500) email"` + + // new field, temporary column renamed to 'commit' at the end + CommitNew *commit `xorm:"json 'commit_new'"` + } + + if err := sess.Sync(new(pipelines)); err != nil { + return err + } + + // Postgres maps the `json` column tag to a native json type, so untyped + // bind parameters inside a CASE need an explicit cast. + jsonThen := "?" + if sess.Engine().Dialect().URI().DBType == schemas.POSTGRES { + jsonThen = "CAST(? AS json)" + } + + // marshalJSON encodes v as a JSON string, returning a nil interface for + // nil pointers so the column is written as SQL NULL rather than the + // literal "null". + marshalJSON := func(v any) (any, error) { + if rv := reflect.ValueOf(v); rv.Kind() == reflect.Pointer && rv.IsNil() { + return nil, nil + } + b, err := json.Marshal(v) + if err != nil { + return nil, err + } + return string(b), nil + } + + page := 0 + oldPipelines := make([]*pipelines, 0, perPage) + + for { + oldPipelines = oldPipelines[:0] + + if err := sess.Limit(perPage, page*perPage).Find(&oldPipelines); err != nil { + return err + } + if len(oldPipelines) == 0 { + break + } + + // Build a single bulk UPDATE for the whole page instead of one + // statement per row: the commit column becomes a CASE keyed by id, + // collapsing perPage round-trips into one statement. + var ( + commitCase strings.Builder + commitArgs []any + ids []any + ) + + for _, p := range oldPipelines { + commitJSON, err := marshalJSON(&commit{ + SHA: p.Commit, + Message: p.Message, + ForgeURL: p.ForgeURL, + Author: commitAuthor{ + Name: p.Author, + Email: p.Email, + }, + Timestamp: p.Timestamp, + }) + if err != nil { + return err + } + + ids = append(ids, p.ID) + commitCase.WriteString(" WHEN ? THEN " + jsonThen) + commitArgs = append(commitArgs, p.ID, commitJSON) + } + + placeholders := strings.TrimSuffix(strings.Repeat("?,", len(ids)), ",") + query := fmt.Sprintf( + "UPDATE `pipelines` SET `commit_new` = CASE `id`%s END WHERE `id` IN (%s)", + commitCase.String(), placeholders, + ) + + // Argument order must match the textual order of the placeholders + // above: the column's CASE, then the WHERE IN list. + execArgs := make([]any, 0, 1+len(commitArgs)+len(ids)) + execArgs = append(execArgs, query) + execArgs = append(execArgs, commitArgs...) + execArgs = append(execArgs, ids...) + + if _, err := sess.Exec(execArgs...); err != nil { + return err + } + + if len(oldPipelines) < perPage { + break + } + + page++ + } + + // the message, timestamp and email columns now live inside the commit + // substruct; the old string commit column is replaced by the json one. + if err := dropTableColumns(sess, "pipelines", "message", "timestamp", "email", "commit"); err != nil { + return err + } + + return renameColumn(sess, "pipelines", "commit_new", "commit") + }, +} diff --git a/server/store/datastore/migration/migration.go b/server/store/datastore/migration/migration.go index c3405548975..b7cafba46e3 100644 --- a/server/store/datastore/migration/migration.go +++ b/server/store/datastore/migration/migration.go @@ -57,6 +57,7 @@ var migrationTasks = []*xormigrate.Migration{ &fixForgeColumns, &addCronField, &updatePipelineStructureTagsReleases, + &updatePipelineStructureCommit, } var allBeans = []any{ diff --git a/server/store/datastore/pipeline_test.go b/server/store/datastore/pipeline_test.go index b5c0e9a3358..e96cab22881 100644 --- a/server/store/datastore/pipeline_test.go +++ b/server/store/datastore/pipeline_test.go @@ -55,7 +55,7 @@ func TestPipelines(t *testing.T) { pipeline = model.Pipeline{ RepoID: repo.ID, Status: model.StatusSuccess, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", + Commit: &model.Commit{SHA: "85f8c029b902ed9400bc600bac301a0aadb144ac"}, Event: model.EventPush, Branch: "some-branch", } @@ -63,7 +63,7 @@ func TestPipelines(t *testing.T) { assert.NoError(t, err) assert.NotZero(t, pipeline.ID) assert.EqualValues(t, 1, pipeline.Number) - assert.Equal(t, "85f8c029b902ed9400bc600bac301a0aadb144ac", pipeline.Commit) + assert.Equal(t, "85f8c029b902ed9400bc600bac301a0aadb144ac", pipeline.Commit.SHA) count, err = store.GetPipelineCount() assert.NoError(t, err) @@ -110,7 +110,7 @@ func TestPipelines(t *testing.T) { Status: model.StatusRunning, Branch: "main", Event: model.EventPull, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa", + Commit: &model.Commit{SHA: "85f8c029b902ed9400bc600bac301a0aadb144aa"}, ForgeURL: "example.com/id3", } require.NoError(t, store.CreatePipeline(pipeline3)) diff --git a/woodpecker-go/woodpecker/types.go b/woodpecker-go/woodpecker/types.go index 936e3fe49cc..7504f16f053 100644 --- a/woodpecker-go/woodpecker/types.go +++ b/woodpecker-go/woodpecker/types.go @@ -106,34 +106,50 @@ type ( // Pipeline defines a pipeline object. Pipeline struct { - ID int64 `json:"id"` - Number int64 `json:"number"` - Parent int64 `json:"parent"` - Event string `json:"event"` - EventReason []string `json:"event_reason"` - Status string `json:"status"` - Errors []*PipelineError `json:"errors"` - Created int64 `json:"created"` - Updated int64 `json:"updated"` - Started int64 `json:"started"` - Finished int64 `json:"finished"` - Deploy string `json:"deploy_to"` - Commit string `json:"commit"` - Branch string `json:"branch"` - Ref string `json:"ref"` - Refspec string `json:"refspec"` - Title string `json:"title"` - Message string `json:"message"` - Timestamp int64 `json:"timestamp"` - Sender string `json:"sender"` - Author string `json:"author"` - Avatar string `json:"author_avatar"` - Email string `json:"author_email"` - ForgeURL string `json:"forge_url"` - Reviewer string `json:"reviewed_by"` - Reviewed int64 `json:"reviewed"` - Workflows []*Workflow `json:"workflows,omitempty"` - Release *Release `json:"release,omitempty"` + ID int64 `json:"id"` + Number int64 `json:"number"` + Parent int64 `json:"parent"` + Event string `json:"event"` + EventReason []string `json:"event_reason"` + Status string `json:"status"` + Errors []*PipelineError `json:"errors"` + Created int64 `json:"created"` + Updated int64 `json:"updated"` + Started int64 `json:"started"` + Finished int64 `json:"finished"` + Deploy string `json:"deploy_to"` + Commit string `json:"commit"` + Branch string `json:"branch"` + Ref string `json:"ref"` + Refspec string `json:"refspec"` + Title string `json:"title"` + Message string `json:"message"` + Timestamp int64 `json:"timestamp"` + Sender string `json:"sender"` + Author string `json:"author"` + Avatar string `json:"author_avatar"` + Email string `json:"author_email"` + ForgeURL string `json:"forge_url"` + Reviewer string `json:"reviewed_by"` + Reviewed int64 `json:"reviewed"` + Workflows []*Workflow `json:"workflows,omitempty"` + Release *Release `json:"release,omitempty"` + CommitPipeline *Commit `json:"commit_pipeline,omitempty"` + } + + // Commit represents the commit a pipeline was triggered for. + Commit struct { + SHA string `json:"sha"` + Message string `json:"message"` + ForgeURL string `json:"forge_url"` + Author *CommitAuthor `json:"author"` + Timestamp int64 `json:"timestamp"` + } + + // CommitAuthor represents the author of a commit. + CommitAuthor struct { + Name string `json:"name"` + Email string `json:"email"` } // Workflow represents a workflow in the pipeline.