Skip to content

Commit

Permalink
Support FF merge strategy
Browse files Browse the repository at this point in the history
When the fast-forward merge strategy is used, there is no merge commit SHA. In this case, we use the last commit SHA as ref
Ref #34
  • Loading branch information
fbpe committed Oct 10, 2024
1 parent d673fc5 commit 3214bbd
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 16 deletions.
6 changes: 5 additions & 1 deletion _documentation/src/docs/tech-docs/20_endpoints.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ Since GitLab keeps the response obtained when delivering a webhook event and dis

=== Replay endpoint

An additional endpoint is available to trigger the process using some simplified input compared to the merge-request event body sent by the GitLab Webhook API.
An additional endpoint is available to trigger the process using some simplified input compared to the merge-request event body sent by the GitLab Webhook API. In this simplified input, the `start_commit_sha` may correspond to two different things in original merge-request event:

* To the `merge_commit_sha`, in case the merge created a merge commit
* To the `last_commit.id` in case the fast-forward merge strategy is used (no merge commit)


`POST <server url>/ucascade/replay`

Expand Down
2 changes: 1 addition & 1 deletion _documentation/src/docs/tech-docs/replay.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"source_branch" : "feature/1.3.x/some-change",
"target_branch" : "main/1.3.x",
"mr_state" : "merged",
"merge_commit_sha" : "0c6f9d312b924bff313f60db2f269b5f4901cd95",
"start_commit_sha" : "0c6f9d312b924bff313f60db2f269b5f4901cd95",
"mr_action" : "merge",
"gitlab_event_uuid" : "replay-394720"
}
22 changes: 11 additions & 11 deletions src/main/java/controller/model/MergeRequestSimple.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public class MergeRequestSimple {
private String targetBranch;
@JsonProperty("mr_state")
private String mrState;
@JsonProperty("merge_commit_sha")
private String mergeCommitSha;
@JsonProperty("start_commit_sha")
private String startCommitSha;
@JsonProperty("mr_action")
private String mrAction;

Expand All @@ -30,14 +30,14 @@ public MergeRequestSimple() {
super();
}

public MergeRequestSimple(Long projectId, Long mrNumber, Long userId, String sourceBranch, String targetBranch, String mrState, String mergeCommitSha, String mrAction, String gitlabEventUUID) {
public MergeRequestSimple(Long projectId, Long mrNumber, Long userId, String sourceBranch, String targetBranch, String mrState, String startCommitSha, String mrAction, String gitlabEventUUID) {
this.projectId = projectId;
this.mrNumber = mrNumber;
this.userId = userId;
this.sourceBranch = sourceBranch;
this.targetBranch = targetBranch;
this.mrState = mrState;
this.mergeCommitSha = mergeCommitSha;
this.startCommitSha = startCommitSha;
this.gitlabEventUUID = gitlabEventUUID;
this.mrAction = mrAction;
}
Expand Down Expand Up @@ -90,12 +90,12 @@ public void setMrState(String mrState) {
this.mrState = mrState;
}

public String getMergeCommitSha() {
return mergeCommitSha;
public String getStartCommitSha() {
return startCommitSha;
}

public void setMergeCommitSha(String mergeCommitSha) {
this.mergeCommitSha = mergeCommitSha;
public void setStartCommitSha(String startCommitSha) {
this.startCommitSha = startCommitSha;
}

public String getMrAction() {
Expand All @@ -116,7 +116,7 @@ public void setGitlabEventUUID(String gitlabEventUUID) {

@Override
public int hashCode() {
return Objects.hash(gitlabEventUUID, mergeCommitSha, mrAction, mrNumber, mrState, projectId, sourceBranch, targetBranch, userId);
return Objects.hash(gitlabEventUUID, startCommitSha, mrAction, mrNumber, mrState, projectId, sourceBranch, targetBranch, userId);
}

@Override
Expand All @@ -129,7 +129,7 @@ public boolean equals(Object obj) {
return false;
MergeRequestSimple other = (MergeRequestSimple) obj;
return Objects.equals(gitlabEventUUID, other.gitlabEventUUID) &&
Objects.equals(mergeCommitSha, other.mergeCommitSha) &&
Objects.equals(startCommitSha, other.startCommitSha) &&
Objects.equals(mrAction, other.mrAction) &&
Objects.equals(mrNumber, other.mrNumber) &&
Objects.equals(mrState, other.mrState) &&
Expand All @@ -141,7 +141,7 @@ public boolean equals(Object obj) {

@Override
public String toString() {
return "MergeRequestSimple [projectId=" + projectId + ", mrNumber=" + mrNumber + ", userId=" + userId + ", sourceBranch=" + sourceBranch + ", targetBranch=" + targetBranch + ", mrState=" + mrState + ", mergeCommitSha=" + mergeCommitSha + ", mrAction=" + mrAction + ", gitlabEventUUID=" + gitlabEventUUID + "]";
return "MergeRequestSimple [projectId=" + projectId + ", mrNumber=" + mrNumber + ", userId=" + userId + ", sourceBranch=" + sourceBranch + ", targetBranch=" + targetBranch + ", mrState=" + mrState + ", startCommitSha=" + startCommitSha + ", mrAction=" + mrAction + ", gitlabEventUUID=" + gitlabEventUUID + "]";
}

}
2 changes: 1 addition & 1 deletion src/main/java/service/GitLabService.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private void handleMrMergeEvent(MergeRequestSimple mrEvent, String gitlabEventUU
String sourceBranch = mrEvent.getSourceBranch();
String targetBranch = mrEvent.getTargetBranch();
Long mrNumber = mrEvent.getMrNumber();
String mergeSha = mrEvent.getMergeCommitSha();
String mergeSha = mrEvent.getStartCommitSha();
String prevSourceBranch = removeMrPrefixPattern(sourceBranch);

Log.infof("GitlabEvent: '%s' | Merge MR Event. Project: '%d', User: '%d', Target: '%s', MergeRequestNumber: '%d'",
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/util/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public static MergeRequestSimple toSimpleEvent(MergeRequestEvent mrEvent, String
result.setSourceBranch(objectAttributes.getSourceBranch());
result.setTargetBranch(objectAttributes.getTargetBranch());
result.setMrNumber(objectAttributes.getIid());
result.setMergeCommitSha(objectAttributes.getMergeCommitSha());
result.setStartCommitSha(objectAttributes.getMergeCommitSha() != null ? objectAttributes.getMergeCommitSha() : objectAttributes.getLastCommit().getId());
result.setMrState(objectAttributes.getState());
result.setMrAction(objectAttributes.getAction());

Expand Down
35 changes: 35 additions & 0 deletions src/test/java/com/unblu/ucascade/UcascadeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,41 @@ void testEndpointBlocking() throws Exception {
verifyRequests(13);
}

@Test
void testEndpointBlockingFFMergeStrategy() throws Exception {
// corresponds to the merge event of MR !100 feature branch targeting branch 'release/6.x.x'
// input is the GitLab event JSON
// expect to create an auto-merge request: !101
Long mrNumber = 101L;
String nextMainBranch = GitlabMockUtil.DEFAULT_TARGET_BRANCH;
String expectedTitle = "[ucascade-TEST] Auto MR: release/6.x.x -> " + nextMainBranch + " (!100)";
String expectedDescription = "Automatic cascade merge request: " + "`something` !" + (mrNumber - 1) + " --> `release/6.x.x` --> `main`";

setupDefaultStubs();

given().when()
.header("Content-Type", "application/json")
.header("X-Gitlab-Event-UUID", GitlabMockUtil.GITLAB_EVENT_UUID)
.body(GitlabMockUtil.get(GitlabAction.EVENT_MR_FF_MERGED, null))
.post("/ucascade/merge-request-blocking")
.then()
.statusCode(Response.Status.OK.getStatusCode())
.body(startsWith("{\n"))
.body(endsWith("\n}"))
.body("gitlab_event_uuid", equalTo(GitlabMockUtil.GITLAB_EVENT_UUID))
.body("build_commit", equalTo("6af21ad"))
.body("build_timestamp", equalTo("2022-01-01T07:21:58.378413Z"))
.body("created_auto_mr.title", equalTo(expectedTitle))
.body("created_auto_mr.description", equalTo(expectedDescription))
.body("created_auto_mr.mr_number", equalTo(mrNumber.intValue()))
.body("created_auto_mr.source_branch", equalTo("mr100_release/6.x.x"))
.body("created_auto_mr.target_branch", equalTo(nextMainBranch))
.body("created_auto_mr.ucascade_state", equalTo(MergeRequestUcascadeState.MERGED.name()))
.body("existing_branch_deleted", nullValue());

verifyRequests(13);
}

@Test
void testSuccessCaseMergeEvent() throws Exception {
// corresponds to the merge event of MR !100 feature branch targeting branch 'release/6.x.x'
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/com/unblu/ucascade/util/GitlabMockUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static enum GitlabAction {
// REST API
CREATE_BRANCH, CREATE_MR, ACCEPT_MR, APPROVE_MR, GET_APPROVALS, UPDATE_MR, GET_OPEN_MRS, GET_MR, GET_BRANCH, GET_FILE, LIST_MR_PIPELINES, COMPARE_DIFF_BRANCHES, COMPARE_NO_DIFF_BRANCHES, GET_USER,
// Webhook
EVENT_MR_MERGED;
EVENT_MR_MERGED, EVENT_MR_FF_MERGED;
}

private static final EnumMap<GitlabAction, String> jsonTemplatesLocation = initJsonTemplatesLocationMap();
Expand Down Expand Up @@ -73,6 +73,7 @@ private static EnumMap<GitlabAction, String> initJsonTemplatesLocationMap() {
templates.put(GitlabAction.COMPARE_NO_DIFF_BRANCHES, "/gitlab_template_json/api/compareNoDiffBranchesResponse.json");
templates.put(GitlabAction.GET_USER, "/gitlab_template_json/api/getUserResponse.json");
templates.put(GitlabAction.EVENT_MR_MERGED, "/gitlab_template_json/webhook/mergedMREvent.json");
templates.put(GitlabAction.EVENT_MR_FF_MERGED, "/gitlab_template_json/webhook/mergedFFMREvent.json");

return templates;
}
Expand Down
137 changes: 137 additions & 0 deletions src/test/resources/gitlab_template_json/webhook/mergedFFMREvent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"object_kind" : "merge_request",
"event_type" : "merge_request",
"user" : {
"id" : 1,
"name" : "Administrator",
"username" : "root",
"avatar_url" : "https://www.gravatar.com/avatar/e633807329b048c67a0431d8df47057e?s=80&d=identicon",
"email" : "[REDACTED]"
},
"project" : {
"id" : 1,
"name" : "test_project",
"description" : null,
"web_url" : "http://localhost:9080/root/test_project",
"avatar_url" : null,
"git_ssh_url" : "ssh://git@localhost:9022/root/test_project.git",
"git_http_url" : "http://localhost:9080/root/test_project.git",
"namespace" : "Administrator",
"visibility_level" : 20,
"path_with_namespace" : "root/test_project",
"default_branch" : "main",
"ci_config_path" : null,
"homepage" : "http://localhost:9080/root/test_project",
"url" : "ssh://git@localhost:9022/root/test_project.git",
"ssh_url" : "ssh://git@localhost:9022/root/test_project.git",
"http_url" : "http://localhost:9080/root/test_project.git"
},
"object_attributes" : {
"assignee_id" : null,
"author_id" : 1,
"created_at" : "2022-09-04 16:44:58 UTC",
"description" : "A dummy pr",
"head_pipeline_id" : null,
"id" : 1,
"iid" : 100,
"last_edited_at" : null,
"last_edited_by_id" : null,
"merge_commit_sha" : null,
"merge_error" : null,
"merge_params" : {
"force_remove_source_branch" : true
},
"merge_status" : "can_be_merged",
"detailed_merge_status" : "mergeable",
"merge_user_id" : null,
"merge_when_pipeline_succeeds" : false,
"milestone_id" : null,
"source_branch" : "some-feature",
"source_project_id" : 1,
"state_id" : 1,
"target_branch" : "release/6.x.x",
"target_project_id" : 1,
"time_estimate" : 0,
"title" : "Some feature",
"updated_at" : "2022-09-04 16:44:58 UTC",
"updated_by_id" : null,
"url" : "http://localhost:9080/root/test_project/-/merge_requests/100",
"source" : {
"id" : 1,
"name" : "test_project",
"description" : null,
"web_url" : "http://localhost:9080/root/test_project",
"avatar_url" : null,
"git_ssh_url" : "ssh://git@localhost:9022/root/test_project.git",
"git_http_url" : "http://localhost:9080/root/test_project.git",
"namespace" : "Administrator",
"visibility_level" : 20,
"path_with_namespace" : "root/test_project",
"default_branch" : "main",
"ci_config_path" : null,
"homepage" : "http://localhost:9080/root/test_project",
"url" : "ssh://git@localhost:9022/root/test_project.git",
"ssh_url" : "ssh://git@localhost:9022/root/test_project.git",
"http_url" : "http://localhost:9080/root/test_project.git"
},
"target" : {
"id" : 1,
"name" : "test_project",
"description" : null,
"web_url" : "http://localhost:9080/root/test_project",
"avatar_url" : null,
"git_ssh_url" : "ssh://git@localhost:9022/root/test_project.git",
"git_http_url" : "http://localhost:9080/root/test_project.git",
"namespace" : "Administrator",
"visibility_level" : 20,
"path_with_namespace" : "root/test_project",
"default_branch" : "main",
"ci_config_path" : null,
"homepage" : "http://localhost:9080/root/test_project",
"url" : "ssh://git@localhost:9022/root/test_project.git",
"ssh_url" : "ssh://git@localhost:9022/root/test_project.git",
"http_url" : "http://localhost:9080/root/test_project.git"
},
"last_commit" : {
"id" : "e819d39ed37c6d4b8e700b9e7f34c74c099c163b",
"message" : "My feature",
"title" : "My feature",
"timestamp" : "2022-09-04T16:44:58+00:00",
"url" : "http://localhost:9080/root/test_project/-/commit/3f46808aa9df132cb84b411e7c605642f6289005",
"author" : {
"name" : "Administrator",
"email" : "root@local"
}
},
"work_in_progress" : false,
"total_time_spent" : 0,
"time_change" : 0,
"human_total_time_spent" : null,
"human_time_change" : null,
"human_time_estimate" : null,
"assignee_ids" : [ ],
"reviewer_ids" : [ ],
"labels" : [ ],
"state" : "merged",
"blocking_discussions_resolved" : true,
"first_contribution" : false,
"action" : "merge"
},
"labels" : [ ],
"changes" : {
"state_id" : {
"previous" : 4,
"current" : 3
},
"updated_at" : {
"previous" : "2022-09-04 16:44:58 UTC",
"current" : "2022-09-04 16:44:58 UTC"
}
},
"repository" : {
"name" : "test_project",
"url" : "ssh://git@localhost:9022/root/test_project.git",
"description" : null,
"homepage" : "http://localhost:9080/root/test_project"
}
}

0 comments on commit 3214bbd

Please sign in to comment.