Skip to content

Commit 6ab7a88

Browse files
committed
Add support for GitOps comments on Push commits
Add supports for GitOps comments on Push commits when using the Git Provider. Signed-off-by: Chmouel Boudjnah <[email protected]>
1 parent eaad896 commit 6ab7a88

File tree

8 files changed

+119
-29
lines changed

8 files changed

+119
-29
lines changed

docs/content/docs/guide/matchingevents.md

+10-3
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,10 @@ files.
178178
## Matching a PipelineRun on a Regexp in a comment
179179

180180
{{< tech_preview "Matching PipelineRun on regexp in comments" >}}
181+
{{< support_matrix github_app="true" github_webhook="true" gitea="true" gitlab="true" bitbucket_cloud="false" bitbucket_server="false" >}}
181182

182-
You can match a PipelineRun on a comment on a Pull Request with the annotation
183-
`pipelinesascode.tekton.dev/on-comment`.
183+
You can match a PipelineRun on a comment on a Pull Request or a [Pushed Commit]({{< relref "/docs/guide/running.md#gitops-commands-on-pushed-commits">}})
184+
with the annotation `pipelinesascode.tekton.dev/on-comment`.
184185

185186
The comment is a regexp and if a newly created comment has this regexp it will
186187
automatically match the PipelineRun and start it.
@@ -208,7 +209,13 @@ Note that the `on-comment` annotation will respect the `pull_request` [Policy]({
208209
so only users in the `pull_request` policy will be able to trigger the
209210
PipelineRun.
210211

211-
> *NOTE*: The `on-comment` annotation is only supported on GitHub, Gitea, and GitLab providers
212+
{{< hint info >}}
213+
214+
- The `on-comment` annotation is supported on `pull_request`. On `push` events,
215+
it is only supported [when targeting the main branch without arguments]({{< relref
216+
"/docs/guide/gitops_commands.md#gitops-commands-on-pushed-commits" >}}).
217+
218+
{{< /hint >}}
212219

213220
## Matching PipelineRun to a Pull Request labels
214221

pkg/pipelineascode/match.go

-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ func (p *PacRun) getPipelineRunsFromRepo(ctx context.Context, repo *v1alpha1.Rep
217217
p.eventEmitter.EmitMessage(nil, zap.InfoLevel, "RepositoryCannotLocatePipelineRun", msg)
218218
return nil, nil
219219
}
220-
221220
pipelineRuns, err = resolve.MetadataResolve(pipelineRuns)
222221
if err != nil && len(pipelineRuns) == 0 {
223222
p.eventEmitter.EmitMessage(repo, zap.ErrorLevel, "FailedToResolvePipelineRunMetadata", err.Error())

pkg/provider/github/detect.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func (v *Provider) detectTriggerTypeFromPayload(ghEventType string, eventInt any
109109
return triggertype.Cancel, ""
110110
}
111111
}
112-
return "", fmt.Sprintf("commit_comment: unsupported action \"%s\"", event.GetAction())
112+
return triggertype.Comment, ""
113113
}
114114
return "", fmt.Sprintf("github: event \"%v\" is not supported", ghEventType)
115115
}

pkg/provider/github/detect_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ func TestProvider_Detect(t *testing.T) {
6969
processReq: false,
7070
},
7171
{
72-
name: "invalid commit_comment Event",
72+
name: "non standard commit_comment Event",
7373
event: github.CommitCommentEvent{
7474
Action: github.String("something"),
7575
},
7676
eventType: "commit_comment",
7777
isGH: true,
78-
processReq: false,
78+
processReq: true,
7979
},
8080
{
8181
name: "invalid check run Event",

pkg/provider/github/parse_payload.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,8 @@ func (v *Provider) handleCommitCommentEvent(ctx context.Context, event *github.C
427427
runevent.SHA = event.GetComment().GetCommitID()
428428
runevent.HeadURL = runevent.URL
429429
runevent.BaseURL = runevent.HeadURL
430-
runevent.EventType = "push"
431-
runevent.TriggerTarget = "push"
432-
runevent.TriggerComment = event.GetComment().GetBody()
430+
runevent.TriggerTarget = triggertype.Push
431+
opscomments.SetEventTypeAndTargetPR(runevent, event.GetComment().GetBody())
433432

434433
// Set main as default branch to runevent.HeadBranch, runevent.BaseBranch
435434
runevent.HeadBranch, runevent.BaseBranch = "main", "main"

test/github_push_retest_test.go

+63-2
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,86 @@ package test
55

66
import (
77
"context"
8+
"fmt"
89
"regexp"
910
"testing"
1011

1112
"github.com/google/go-github/v66/github"
1213
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/keys"
1314
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/cctx"
1415
tgithub "github.com/openshift-pipelines/pipelines-as-code/test/pkg/github"
16+
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/options"
1517
twait "github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait"
1618
tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
1719
"gotest.tools/v3/assert"
1820
corev1 "k8s.io/api/core/v1"
1921
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2022
)
2123

24+
func TestGithubPushRequestGitOpsCommentOnComment(t *testing.T) {
25+
opsComment := "/hello-world"
26+
ctx := context.Background()
27+
g := &tgithub.PRTest{
28+
Label: "Github GitOps push/retest request",
29+
YamlFiles: []string{"testdata/pipelinerun-on-comment-annotation.yaml"},
30+
NoStatusCheck: true,
31+
TargetRefName: options.MainBranch,
32+
}
33+
g.RunPushRequest(ctx, t)
34+
defer g.TearDown(ctx, t)
35+
36+
// let's make sure we didn't create any PipelineRuns since we only match on-comment here
37+
pruns, err := g.Cnx.Clients.Tekton.TektonV1().PipelineRuns(g.TargetNamespace).List(ctx, metav1.ListOptions{})
38+
assert.NilError(t, err)
39+
assert.Equal(t, len(pruns.Items), 0)
40+
41+
g.Cnx.Clients.Log.Infof("Running ops comment %s as Push comment", opsComment)
42+
_, _, err = g.Provider.Client.Repositories.CreateComment(ctx,
43+
g.Options.Organization,
44+
g.Options.Repo, g.SHA,
45+
&github.RepositoryComment{Body: github.String(opsComment)})
46+
assert.NilError(t, err)
47+
48+
waitOpts := twait.Opts{
49+
RepoName: g.TargetNamespace,
50+
Namespace: g.TargetNamespace,
51+
MinNumberStatus: len(g.YamlFiles),
52+
PollTimeout: twait.DefaultTimeout,
53+
TargetSHA: g.SHA,
54+
}
55+
g.Cnx.Clients.Log.Info("Waiting for Repository to be updated")
56+
_, err = twait.UntilRepositoryUpdated(ctx, g.Cnx.Clients, waitOpts)
57+
assert.NilError(t, err)
58+
59+
g.Cnx.Clients.Log.Infof("Check if we have the repository set as succeeded")
60+
repo, err := g.Cnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(g.TargetNamespace).Get(ctx, g.TargetNamespace, metav1.GetOptions{})
61+
assert.NilError(t, err)
62+
assert.Equal(t, repo.Status[len(repo.Status)-1].Conditions[0].Status, corev1.ConditionTrue)
63+
64+
pruns, err = g.Cnx.Clients.Tekton.TektonV1().PipelineRuns(g.TargetNamespace).List(ctx, metav1.ListOptions{})
65+
assert.NilError(t, err)
66+
assert.Equal(t, len(pruns.Items), len(g.YamlFiles))
67+
lastPrName := pruns.Items[0].GetName()
68+
err = twait.RegexpMatchingInPodLog(
69+
context.Background(),
70+
g.Cnx,
71+
g.TargetNamespace,
72+
fmt.Sprintf("tekton.dev/pipelineRun=%s", lastPrName),
73+
"step-task",
74+
*regexp.MustCompile(opsComment),
75+
"",
76+
2)
77+
78+
assert.NilError(t, err)
79+
}
80+
2281
func TestGithubPushRequestGitOpsCommentRetest(t *testing.T) {
2382
ctx := context.Background()
2483
g := &tgithub.PRTest{
25-
Label: "Github GitOps push/retest request",
26-
YamlFiles: []string{"testdata/pipelinerun-on-push.yaml", "testdata/pipelinerun.yaml"},
84+
Label: "Github GitOps push/retest request",
85+
YamlFiles: []string{
86+
"testdata/pipelinerun-on-push.yaml", "testdata/pipelinerun.yaml",
87+
},
2788
}
2889
g.RunPushRequest(ctx, t)
2990
defer g.TearDown(ctx, t)

test/pkg/github/pr.go

+40-17
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/options"
1717
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/payload"
1818
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/repository"
19+
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/scm"
1920
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait"
2021
"github.com/tektoncd/pipeline/pkg/names"
2122
"go.uber.org/zap"
@@ -72,7 +73,7 @@ func PushFilesToRef(ctx context.Context, client *ghlib.Client, commitMessage, ba
7273
},
7374
}, &ghlib.CreateCommitOptions{})
7475
if err != nil {
75-
return "", nil, err
76+
return "", nil, fmt.Errorf("error creating commit: %w", err)
7677
}
7778

7879
ref := &ghlib.Reference{
@@ -83,9 +84,8 @@ func PushFilesToRef(ctx context.Context, client *ghlib.Client, commitMessage, ba
8384
}
8485
vref, _, err := client.Git.CreateRef(ctx, owner, repo, ref)
8586
if err != nil {
86-
return "", nil, err
87+
return "", nil, fmt.Errorf("error creating ref: %w", err)
8788
}
88-
8989
return commit.GetSHA(), vref, nil
9090
}
9191

@@ -155,6 +155,7 @@ func (g *PRTest) RunPullRequest(ctx context.Context, t *testing.T) {
155155
sha, vref, err := PushFilesToRef(ctx, ghcnx.Client, g.CommitTitle, repoinfo.GetDefaultBranch(), targetRefName,
156156
opts.Organization, opts.Repo, entries)
157157
assert.NilError(t, err)
158+
158159
g.Logger.Infof("Commit %s has been created and pushed to %s", sha, vref.GetURL())
159160
number, err := PRCreate(ctx, runcnx, ghcnx, opts.Organization,
160161
opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), g.CommitTitle)
@@ -197,14 +198,21 @@ func (g *PRTest) TearDown(ctx context.Context, t *testing.T) {
197198
if g.TargetNamespace != "" {
198199
repository.NSTearDown(ctx, t, g.Cnx, g.TargetNamespace)
199200
}
200-
g.Logger.Infof("Deleting Ref %s", g.TargetRefName)
201-
_, err := g.Provider.Client.Git.DeleteRef(ctx, g.Options.Organization, g.Options.Repo, g.TargetRefName)
202-
assert.NilError(t, err)
201+
if g.TargetRefName != options.MainBranch {
202+
branch := fmt.Sprintf("heads/%s", filepath.Base(g.TargetRefName))
203+
g.Logger.Infof("Deleting Ref %s", branch)
204+
_, err := g.Provider.Client.Git.DeleteRef(ctx, g.Options.Organization, g.Options.Repo, branch)
205+
assert.NilError(t, err)
206+
}
203207
}
204208

205209
func (g *PRTest) RunPushRequest(ctx context.Context, t *testing.T) {
206210
targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-push")
207-
targetBranch := targetNS
211+
212+
targetBranch := g.TargetRefName
213+
if targetBranch == "" {
214+
targetBranch = targetNS
215+
}
208216
targetEvent := "push"
209217
ctx, runcnx, opts, ghcnx, err := Setup(ctx, g.SecondController, g.Webhook)
210218
assert.NilError(t, err)
@@ -235,19 +243,34 @@ func (g *PRTest) RunPushRequest(ctx context.Context, t *testing.T) {
235243
targetNS, targetBranch, targetEvent, map[string]string{})
236244
assert.NilError(t, err)
237245

238-
targetRefName := fmt.Sprintf("refs/heads/%s", targetBranch)
239-
sha, vref, err := PushFilesToRef(ctx, ghcnx.Client, logmsg, repoinfo.GetDefaultBranch(), targetRefName, opts.Organization, opts.Repo, entries)
240-
g.Logger.Infof("Commit %s has been created and pushed to %s", sha, vref.GetURL())
246+
targetRefName := targetBranch
247+
cloneURL, err := scm.MakeGitCloneURL(repoinfo.GetCloneURL(), "git", *ghcnx.Token)
248+
assert.NilError(t, err)
249+
scmOpts := scm.Opts{
250+
GitURL: cloneURL,
251+
TargetRefName: targetRefName,
252+
BaseRefName: repoinfo.GetDefaultBranch(),
253+
WebURL: repoinfo.GetHTMLURL(),
254+
Log: runcnx.Clients.Log,
255+
CommitTitle: logmsg,
256+
}
257+
scm.PushFilesToRefGit(t, &scmOpts, entries)
258+
branch, _, err := ghcnx.Client.Repositories.GetBranch(ctx, opts.Organization, opts.Repo, targetBranch, 1)
259+
assert.NilError(t, err)
260+
sha := branch.GetCommit().GetSHA()
261+
g.Logger.Infof("Commit %s has been created and pushed to %s in branch %s", sha, branch.GetCommit().GetHTMLURL(), branch.GetName())
241262
assert.NilError(t, err)
242263

243-
sopt := wait.SuccessOpt{
244-
Title: logmsg,
245-
OnEvent: triggertype.Push.String(),
246-
TargetNS: targetNS,
247-
NumberofPRMatch: len(g.YamlFiles),
248-
SHA: sha,
264+
if !g.NoStatusCheck {
265+
sopt := wait.SuccessOpt{
266+
Title: logmsg,
267+
OnEvent: triggertype.Push.String(),
268+
TargetNS: targetNS,
269+
NumberofPRMatch: len(g.YamlFiles),
270+
SHA: sha,
271+
}
272+
wait.Succeeded(ctx, t, runcnx, opts, sopt)
249273
}
250-
wait.Succeeded(ctx, t, runcnx, opts, sopt)
251274

252275
g.Cnx = runcnx
253276
g.Options = opts

test/pkg/github/setup.go

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ func Setup(ctx context.Context, onSecondController, viaDirectWebhook bool) (cont
109109
Token: githubToken,
110110
URL: githubURL,
111111
}
112+
gprovider.Token = &githubToken
112113
// TODO: before PR
113114
if err := gprovider.SetClient(ctx, nil, event, nil, nil); err != nil {
114115
return ctx, nil, options.E2E{}, github.New(), err

0 commit comments

Comments
 (0)