10000 Merge pull request #1504 from gsmet/workflow-run-approve · hub4j/github-api@f540664 · GitHub
[go: up one dir, main page]

Skip to content

Commit f540664

Browse files
authored
Merge pull request #1504 from gsmet/workflow-run-approve
Implement workflow run approval
2 parents e5fb0cd + de1345b commit f540664

12 files changed

+1900
-2
lines changed

src/main/java/org/kohsuke/github/GHWorkflowRun.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,16 @@ public void rerun() throws IOException {
299299
root().createRequest().method("POST").withUrlPath(getApiRoute(), "rerun").send();
300300
}
301301

302+
/**
303+
* Approve the workflow run.
304+
*
305+
* @throws IOException
306+
* the io exception
307+
*/
308+
public void approve() throws IOException {
309+
root().createRequest().method("POST").withUrlPath(getApiRoute(), "approve").send();
310+
}
311+
302312
/**
303313
* Lists the artifacts attached to this workflow run.
304314
*

src/main/java/org/kohsuke/github/GHWorkflowRunQueryBuilder.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.kohsuke.github;
22

3+
import org.kohsuke.github.GHWorkflowRun.Conclusion;
34
import org.kohsuke.github.GHWorkflowRun.Status;
45

56
/**
@@ -88,6 +89,20 @@ public GHWorkflowRunQueryBuilder status(Status status) {
8889
return this;
8990
}
9091

92+
/**
93+
* Conclusion workflow run query builder.
94+
* <p>
95+
* The GitHub API is also using the status field to search by conclusion.
96+
*
97+
* @param conclusion
98+
* the conclusion
99+
* @return the gh workflow run query builder
100+
*/
101+
public GHWorkflowRunQueryBuilder conclusion(Conclusion conclusion) {
102+
req.with("status", conclusion.toString());
103+
return this;
104+
}
105+
91106
@Override
92107
public PagedIterable<GHWorkflowRun> list() {
93108
return new GHWorkflowRunsIterable(repo, req.withUrlPath(repo.getApiTailUrl("actions/runs")));

src/test/java/org/kohsuke/github/GHWorkflowRunTest.java

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.awaitility.Awaitility;
44
import org.junit.Before;
55
import org.junit.Test;
6+
import org.kohsuke.github.GHPullRequestQueryBuilder.Sort;
67
import org.kohsuke.github.GHWorkflowJob.Step;
78
import org.kohsuke.github.GHWorkflowRun.Conclusion;
89
import org.kohsuke.github.GHWorkflowRun.Status;
@@ -362,18 +363,57 @@ public void testJobs() throws IOException {
362363
assertThat(allJobs.size(), greaterThanOrEqualTo(2));
363364
}
364365

365-
private void await(Function<GHRepository, Boolean> condition) throws IOException {
366+
@Test
367+
public void testApproval() throws IOException {
368+
List<GHPullRequest> pullRequests = repo.queryPullRequests()
369+
.base(MAIN_BRANCH)
370+
.sort(Sort.CREATED)
371+
.direction(GHDirection.DESC)
372+
.state(GHIssueState.OPEN)
373+
.list()
374+
.toList();
375+
376+
assertThat(pullRequests.size(), greaterThanOrEqualTo(1));
377+
GHPullRequest pullRequest = pullRequests.get(0);
378+
379+
await("Waiting for workflow run to be pending",
380+
(nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo,
381+
FAST_WORKFLOW_NAME,
382+
MAIN_BRANCH,
383+
Conclusion.ACTION_REQUIRED).isPresent());
384+
385+
GHWorkflowRun workflowRun = getWorkflowRun(FAST_WORKFLOW_NAME, MAIN_BRANCH, Conclusion.ACTION_REQUIRED)
386+
.orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here"));
387+
388+
workflowRun.approve();
389+
390+
await("Waiting for workflow run to be approved",
391+
(nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo,
392+
FAST_WORKFLOW_NAME,
393+
pullRequest.getHead().getRef(),
394+
Conclusion.SUCCESS).isPresent());
395+
396+
workflowRun = repo.getWorkflowRun(workflowRun.getId());
397+
398+
assertThat(workflowRun.getConclusion(), is(Conclusion.SUCCESS));
399+
}
400+
401+
private void await(String alias, Function<GHRepository, Boolean> condition) throws IOException {
366402
if (!mockGitHub.isUseProxy()) {
367403
return;
368404
}
369405

370406
GHRepository nonRecordingRepo = getNonRecordingGitHub().getRepository(REPO_NAME);
371407

372-
Awaitility.await().pollInterval(Duration.ofSeconds(5)).atMost(Duration.ofSeconds(60)).until(() -> {
408+
Awaitility.await(alias).pollInterval(Duration.ofSeconds(5)).atMost(Duration.ofSeconds(60)).until(() -> {
373409
return condition.apply(nonRecordingRepo);
374410
});
375411
}
376412

413+
private void await(Function<GHRepository, Boolean> condition) throws IOException {
414+
await(null, condition);
415+
}
416+
377417
private long getLatestPreexistingWorkflowRunId() {
378418
return repo.queryWorkflowRuns().list().withPageSize(1).iterator().next().getId();
379419
}
@@ -407,6 +447,31 @@ private Optional<GHWorkflowRun> getWorkflowRun(String workflowName,
407447
return getWorkflowRun(this.repo, workflowName, branch, status, latestPreexistingWorkflowRunId);
408448
}
409449

450+
private static Optional<GHWorkflowRun> getWorkflowRun(GHRepository repository,
451+
String workflowName,
452+
String branch,
453+
Conclusion conclusion) {
454+
List<GHWorkflowRun> workflowRuns = repository.queryWorkflowRuns()
455+
.branch(branch)
456+
.conclusion(conclusion)
457+
.event(GHEvent.PULL_REQUEST)
458+
.list()
459+
.withPageSize(20)
460+
.iterator()
461+
.nextPage();
462+
463+
for (GHWorkflowRun workflowRun : workflowRuns) {
464+
if (workflowRun.getName().equals(workflowName)) {
465+
return Optional.of(workflowRun);
466+
}
467+
}
468+
return Optional.empty();
469+
}
470+
471+
private Optional<GHWorkflowRun> getWorkflowRun(String workflowName, String branch, Conclusion conclusion) {
472+
return getWorkflowRun(this.repo, workflowName, branch, conclusion);
473+
}
474+
410475
private static Status getWorkflowRunStatus(GHRepository repository, long workflowRunId) {
411476
try {
412477
return repository.getWorkflowRun(workflowRunId).getStatus();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{
2+
"id": 348674220,
3+
"node_id": "MDEwOlJlcG9zaXRvcnkzNDg2NzQyMjA=",
4+
"name": "GHWorkflowRunTest",
5+
"full_name": "hub4j-test-org/GHWorkflowRunTest",
6+
"private": false,
7+
"owner": {
8+
"login": "hub4j-test-org",
9+
"id": 7544739,
10+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=",
11+
"avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4",
12+
"gravatar_id": "",
13+
"url": "https://api.github.com/users/hub4j-test-org",
14+
"html_url": "https://github.com/hub4j-test-org",
15+
"followers_url": "https://api.github.com/users/hub4j-test-org/followers",
16+
"following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}",
17+
"gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}",
18+
"starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}",
19+
"subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions",
20+
"organizations_url": "https://api.github.com/users/hub4j-test-org/orgs",
21+
"repos_url": "https://api.github.com/users/hub4j-test-org/repos",
22+
"events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}",
23+
"received_events_url": "https://api.github.com/users/hub4j-test-org/received_events",
24+
"type": "Organization",
25+
"site_admin": false
26+
},
27+
"html_url": "https://github.com/hub4j-test-org/GHWorkflowRunTest",
28+
"description": "Repository used by GHWorkflowRunTest",
29+
"fork": false,
30+
"url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest",
31+
"forks_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/forks",
32+
"keys_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/keys{/key_id}",
33+
"collaborators_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/collaborators{/collaborator}",
34+
"teams_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/teams",
35+
"hooks_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/hooks",
36+
"issue_events_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/issues/events{/number}",
37+
"events_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/events",
38+
"assignees_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/assignees{/user}",
39+
"branches_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/branches{/branch}",
40+
"tags_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/tags",
41+
"blobs_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/git/blobs{/sha}",
42+
"git_tags_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/git/tags{/sha}",
43+
"git_refs_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/git/refs{/sha}",
44+
"trees_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/git/trees{/sha}",
45+
"statuses_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/statuses/{sha}",
46+
"languages_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/languages",
47+
"stargazers_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/stargazers",
48+
"contributors_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/contributors",
49+
"subscribers_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/subscribers",
50+
"subscription_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/subscription",
51+
"commits_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/commits{/sha}",
52+
"git_commits_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/git/commits{/sha}",
53+
"comments_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/comments{/number}",
54+
"issue_comment_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/issues/comments{/number}",
55+
"contents_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/contents/{+path}",
56+
"compare_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/compare/{base}...{head}",
57+
"merges_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/merges",
58+
"archive_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/{archive_format}{/ref}",
59+
"downloads_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/downloads",
60+
"issues_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/issues{/number}",
61+
"pulls_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/pulls{/number}",
62+
"milestones_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/milestones{/number}",
63+
"notifications_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/notifications{?since,all,participating}",
64+
"labels_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/labels{/name}",
65+
"releases_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/releases{/id}",
66+
"deployments_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/deployments",
67+
"created_at": "2021-03-17T10:50:49Z",
68+
"updated_at": "2021-04-05T12:08:00Z",
69+
"pushed_at": "2022-08-17T10:55:33Z",
70+
"git_url": "git://github.com/hub4j-test-org/GHWorkflowRunTest.git",
71+
"ssh_url": "git@github.com:hub4j-test-org/GHWorkflowRunTest.git",
72+
"clone_url": "https://github.com/hub4j-test-org/GHWorkflowRunTest.git",
73+
"svn_url": "https://github.com/hub4j-test-org/GHWorkflowRunTest",
74+
"homepage": null,
75+
"size": 7,
76+
"stargazers_count": 0,
77+
"watchers_count": 0,
78+
"language": null,
79+
"has_issues": true,
80+
"has_projects": true,
81+
"has_downloads": true,
82+
"has_wiki": true,
83+
"has_pages": false,
84+
"forks_count": 1,
85+
"mirror_url": null,
86+
"archived": false,
87+
"disabled": false,
88+
"open_issues_count": 8,
89+
"license": null,
90+
"allow_forking": true,
91+
"is_template": false,
92+
"web_commit_signoff_required": false,
93+
"topics": [],
94+
"visibility": "public",
95+
"forks": 1,
96+
"open_issues": 8,
97+
"watchers": 0,
98+
"default_branch": "main",
99+
"permissions": {
100+
"admin": true,
101+
"maintain": true,
102+
"push": true,
103+
"triage": true,
104+
"pull": true
105+
},
106+
"temp_clone_token": "",
107+
"allow_squash_merge": true,
108+
"allow_merge_commit": true,
109+
"allow_rebase_merge": true,
110+
"allow_auto_merge": false,
111+
"delete_branch_on_merge": false,
112+
"allow_update_branch": false,
113+
"use_squash_pr_title_as_default": false,
114+
"squash_merge_commit_message": "COMMIT_MESSAGES",
115+
"squash_merge_commit_title": "COMMIT_OR_PR_TITLE",
116+
"merge_commit_message": "PR_TITLE",
117+
"merge_commit_title": "MERGE_MESSAGE",
118+
"organization": {
119+
"login": "hub4j-test-org",
120+
"id": 7544739,
121+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=",
122+
"avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4",
123+
"gravatar_id": "",
124+
"url": "https://api.github.com/users/hub4j-test-org",
125+
"html_url": "https://github.com/hub4j-test-org",
126+
"followers_url": "https://api.github.com/users/hub4j-test-org/followers",
127+
"following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}",
128+
"gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}",
129+
"starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}",
130+
"subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions",
131+
"organizations_url": "https://api.github.com/users/hub4j-test-org/orgs",
132+
"repos_url": "https://api.github.com/users/hub4j-test-org/repos",
133+
"events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}",
134+
"received_events_url": "https://api.github.com/users/hub4j-test-org/received_events",
135+
"type": "Organization",
136+
"site_admin": false
137+
},
138+
"network_count": 1,
139+
"subscribers_count": 10
140+
}

0 commit comments

Comments
 (0)
0