Skip to content

Commit

Permalink
Add GitOps comments functionality to push request
Browse files Browse the repository at this point in the history
This commit enables PAC users to include
GitOps comments for push request.
Supported GitOps comments are

- /test
- /retest
- /cancel
- /test prname
- /retest prname
- /cancel prname

Signed-off-by: Savita Ashture <[email protected]>
  • Loading branch information
savitaashture authored and chmouel committed Nov 9, 2023
1 parent 0edaa50 commit f2db9f7
Show file tree
Hide file tree
Showing 19 changed files with 934 additions and 94 deletions.
98 changes: 94 additions & 4 deletions docs/content/docs/guide/running.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ entire suite of checks once again.

![github apps rerun check](/images/github-apps-rerun-checks.png)

### Gitops command on pull or merge request
### GitOps command on pull or merge request

If you are targeting a pull or merge request you can use `GitOps` comment
If you are targeting a push, pull or merge request you can use `GitOps` comment
inside your pull request, to restart all or specific Pipelines.

For example you want to restart all your pipeline you can add a comment starting
For example, you want to restart all your pipeline you can add a comment starting
with `/retest` and all PipelineRun attached to that pull or merge request will be
restarted :

Expand All @@ -141,6 +141,58 @@ roses are red, violets are blue. pipeline are bound to flake by design.
/test <pipelinerun-name>
```

### GitOps command on push request

To trigger GitOps commands in response to a push request, you can include `GitOps`
comments within your commit messages. These comments can be used to restart
either all pipelines or specific ones. Here's how it works:

For restarting all pipeline runs:

1. Use `/retest` or `/test` within your commit message.

For restarting a specific pipeline run:
2. Use `/retest <pipelinerun-name>` or `/test <pipelinerun-name>` within your
commit message. Replace `<pipelinerun-name>` with the specific name of the
pipeline run you want to restart.

**Note:**

When executing `GitOps` commands on a commit that exists in multiple branches
within a push request, the branch with the latest commit will be used.

This means:

1. If a user specifies commands like `/retest` or `/test` without any argument
in a comment on a branch, the test will automatically be performed on the **main** branch.

Examples :
1. `/retest`
2. `/test`
3. `/retest <pipelinerun-name>`
4. `/test <pipelinerun-name>`

2. If the user includes a branch specification such as `/retest branch:test` or
`/test branch:test`, the test will be executed on the commit where the comment is
located, with the context of the **test** branch.

Examples :
1. `/retest branch:test`
2. `/test branch:test`
3. `/retest <pipelinerun-name> branch:test`
4. `/test <pipelinerun-name> branch:test`

To add `GitOps` comments to a push request, follow these steps:

1. Go to your repository.
2. Click on the **Commits** section.
3. Choose one of the individual **Commit**.
4. Click on the line number where you want to add a `GitOps` comment, as shown in the image below:

![GitOps Commits For Comments](/images/gitops-comments-on-commit.png)

Please note that this feature is supported for the GitHub provider only.

## Cancelling the PipelineRun

You can cancel a running PipelineRun by commenting on the PullRequest.
Expand All @@ -159,7 +211,7 @@ It seems the infra is down, so cancelling the pipelineruns.
If you have multiple `PipelineRun` and you want to target a specific
`PipelineRun` you can use the `/cancel` comment with the PipelineRun name

Example:
Example :

```text
roses are red, violets are blue. why to run the pipeline when the infra is down.
Expand All @@ -170,3 +222,41 @@ roses are red, violets are blue. why to run the pipeline when the infra is down.
On GitHub App the status of the Pipeline will be set to `cancelled`.

![pipelinerun canceled](/images/pr-cancel.png)

### Cancelling the PipelineRun on push request

You can cancel a running PipelineRun by commenting on the commit.
Here's how you can do it.

Example :

1. Use `/cancel` to cancel all PipeineRuns.
2. Use `/cancel <pipelinerun-name>` to cancel a specific PipeineRun

**Note:**

When executing `GitOps` comments on a commit that exists in multiple branches
within a push request, the branch with the latest commit will be used.

This means:

1. If a user specifies commands like `/cancel`
without any argument in a comment on a branch,
it will automatically target the **main** branch.

Examples :
1. `/cancel`
2. `/cancel <pipelinerun-name>`

2. If the user issues a command like `/cancel branch:test`,
it will target the commit where the comment was made but use the **test** branch.

Examples :
1. `/cancel branch:test`
2. `/cancel <pipelinerun-name> branch:test`

In the GitHub App, the status of the Pipeline will be set to `cancelled`.

![GitOps Commits For Comments For PipelineRun Canceled](/images/gitops-comments-on-commit-cancel.png)

Please note that this feature is supported for the GitHub provider only.
1 change: 1 addition & 0 deletions docs/content/docs/install/github_apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Alternatively, you could set up manually by following the steps [here](#setup-ma
* Check run
* Check suite
* Issue comment
* Commit comment
* Pull request
* Push

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/images/gitops-comments-on-commit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pkg/cmd/tknpac/bootstrap/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func generateManifest(opts *bootstrapOpts) ([]byte, error) {
"check_run",
"check_suite",
"issue_comment",
"commit_comment",
"pull_request",
"push",
},
Expand Down
80 changes: 74 additions & 6 deletions pkg/pipelineascode/cancel_pipelinerun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ var (
URL: "https://github.com/fooorg/foo",
},
}
fooRepoLabelsForPush = map[string]string{
keys.URLRepository: formatting.CleanValueKubernetes("foo"),
keys.SHA: formatting.CleanValueKubernetes("foosha"),
}
fooRepoLabels = map[string]string{
keys.URLRepository: formatting.CleanValueKubernetes("foo"),
keys.SHA: formatting.CleanValueKubernetes("foosha"),
Expand Down Expand Up @@ -66,12 +70,6 @@ func TestCancelPipelinerun(t *testing.T) {
pipelineRuns []*pipelinev1.PipelineRun
cancelledPipelineRuns map[string]bool
}{
{
name: "not a pull request event",
event: &info.Event{
TriggerTarget: "push",
},
},
{
name: "cancel running",
event: &info.Event{
Expand Down Expand Up @@ -203,6 +201,76 @@ func TestCancelPipelinerun(t *testing.T) {
repo: fooRepo,
cancelledPipelineRuns: map[string]bool{},
},
{
name: "cancel running for push event",
event: &info.Event{
Repository: "foo",
SHA: "foosha",
TriggerTarget: "push",
State: info.State{
CancelPipelineRuns: true,
},
},
pipelineRuns: []*pipelinev1.PipelineRun{
{
ObjectMeta: metav1.ObjectMeta{
Name: "pr-foo",
Namespace: "foo",
Labels: fooRepoLabelsForPush,
},
Spec: pipelinev1.PipelineRunSpec{},
},
},
repo: fooRepo,
cancelledPipelineRuns: map[string]bool{
"pr-foo": true,
},
},
{
name: "cancel a specific run for push event",
event: &info.Event{
Repository: "foo",
SHA: "foosha",
TriggerTarget: "push",
State: info.State{
CancelPipelineRuns: true,
TargetCancelPipelineRun: "pr-foo-abc",
},
},
pipelineRuns: []*pipelinev1.PipelineRun{
{
ObjectMeta: metav1.ObjectMeta{
Name: "pr-foo",
Namespace: "foo",
Labels: fooRepoLabelsForPush,
Annotations: fooRepoAnnotations,
},
Spec: pipelinev1.PipelineRunSpec{},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "pr-foo-abc-123",
Namespace: "foo",
Labels: fooRepoLabelsPrFooAbc,
Annotations: fooRepoAnnotationsPrFooAbc,
},
Spec: pipelinev1.PipelineRunSpec{},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "pr-foo-pqr",
Namespace: "foo",
Labels: fooRepoLabelsForPush,
Annotations: fooRepoAnnotations,
},
Spec: pipelinev1.PipelineRunSpec{},
},
},
repo: fooRepo,
cancelledPipelineRuns: map[string]bool{
"pr-foo-abc-123": true,
},
},
}

for _, tt := range tests {
Expand Down
19 changes: 10 additions & 9 deletions pkg/pipelineascode/cancel_pipelineruns.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ var cancelMergePatch = map[string]interface{}{
}

func (p *PacRun) cancelPipelineRuns(ctx context.Context, repo *v1alpha1.Repository) error {
if p.event.TriggerTarget != "pull_request" {
msg := fmt.Sprintf("not a pullRequest event, event: %v", p.event.TriggerTarget)
p.eventEmitter.EmitMessage(repo, zap.WarnLevel, "RepositoryEvent", msg)
return nil
labelSelector := getLabelSelector(map[string]string{
keys.URLRepository: formatting.CleanValueKubernetes(p.event.Repository),
keys.SHA: formatting.CleanValueKubernetes(p.event.SHA),
})

if p.event.TriggerTarget == "pull_request" {
labelSelector = getLabelSelector(map[string]string{
keys.PullRequest: strconv.Itoa(p.event.PullRequestNumber),
})
}

prs, err := p.run.Clients.Tekton.TektonV1().PipelineRuns(repo.Namespace).List(ctx, metav1.ListOptions{
LabelSelector: getLabelSelector(map[string]string{
keys.URLRepository: formatting.CleanValueKubernetes(p.event.Repository),
keys.SHA: formatting.CleanValueKubernetes(p.event.SHA),
keys.PullRequest: strconv.Itoa(p.event.PullRequestNumber),
}),
LabelSelector: labelSelector,
})
if err != nil {
return fmt.Errorf("failed to list pipelineRuns : %w", err)
Expand Down
13 changes: 13 additions & 0 deletions pkg/provider/github/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ func detectTriggerTypeFromPayload(ghEventType string, eventInt any) (info.Trigge
return info.TriggerTypeCheckRunRerequested, ""
}
return "", fmt.Sprintf("check_run: unsupported action \"%s\"", event.GetAction())
case *github.CommitCommentEvent:
if event.GetAction() == "created" {
if provider.IsTestRetestComment(event.GetComment().GetBody()) {
return info.TriggerTypeRetest, ""
}
if provider.IsOkToTestComment(event.GetComment().GetBody()) {
return info.TriggerTypeOkToTest, ""
}
if provider.IsCancelComment(event.GetComment().GetBody()) {
return info.TriggerTypeCancel, ""
}
}
return "", fmt.Sprintf("commit_comment: unsupported action \"%s\"", event.GetAction())
}
return "", fmt.Sprintf("github: event \"%v\" is not supported", ghEventType)
}
52 changes: 50 additions & 2 deletions pkg/provider/github/detect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,17 @@ func TestProvider_Detect(t *testing.T) {
event: github.CommitCommentEvent{
Action: github.String("something"),
},
eventType: "release",
wantReason: "event \"release\" is not supported",
isGH: true,
processReq: false,
},
{
name: "invalid commit_comment Event",
event: github.CommitCommentEvent{
Action: github.String("something"),
},
eventType: "commit_comment",
wantReason: "event \"commit_comment\" is not supported",
isGH: true,
processReq: false,
},
Expand Down Expand Up @@ -228,7 +237,7 @@ func TestProvider_Detect(t *testing.T) {
processReq: true,
},
{
name: "issue comment Event with retest",
name: "issue comment Event with cancel comment ",
event: github.IssueCommentEvent{
Action: github.String("created"),
Issue: &github.Issue{
Expand All @@ -246,6 +255,45 @@ func TestProvider_Detect(t *testing.T) {
isGH: true,
processReq: true,
},
{
name: "commit comment event with cancel comment",
event: github.CommitCommentEvent{
Action: github.String("created"),
Installation: &github.Installation{
ID: github.Int64(123),
},
Comment: &github.RepositoryComment{Body: github.String("/cancel")},
},
eventType: "commit_comment",
isGH: true,
processReq: true,
},
{
name: "commit comment Event with retest",
event: github.CommitCommentEvent{
Action: github.String("created"),
Installation: &github.Installation{
ID: github.Int64(123),
},
Comment: &github.RepositoryComment{Body: github.String("/retest")},
},
eventType: "commit_comment",
isGH: true,
processReq: true,
},
{
name: "commit comment Event with test",
event: github.CommitCommentEvent{
Action: github.String("created"),
Installation: &github.Installation{
ID: github.Int64(123),
},
Comment: &github.RepositoryComment{Body: github.String("/test")},
},
eventType: "commit_comment",
isGH: true,
processReq: true,
},
}

for _, tt := range tests {
Expand Down
17 changes: 17 additions & 0 deletions pkg/provider/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,20 @@ func uniqueRepositoryID(repoIDs []int64, id int64) []int64 {
}
return r
}

// isBranchContainsCommit checks whether provided branch has sha or not.
func (v *Provider) isBranchContainsCommit(ctx context.Context, runevent *info.Event, branchName string) error {
if v.Client == nil {
return fmt.Errorf("no github client has been initialized, " +
"exiting... (hint: did you forget setting a secret on your repo?)")
}

branchInfo, _, err := v.Client.Repositories.GetBranch(ctx, runevent.Organization, runevent.Repository, branchName, true)
if err != nil {
return err
}
if branchInfo.Commit.GetSHA() == runevent.SHA {
return nil
}
return fmt.Errorf("provided branch %s does not contains sha %s", branchName, runevent.SHA)
}
Loading

0 comments on commit f2db9f7

Please sign in to comment.