Skip to content

Commit 74c1550

Browse files
committed
feat: ✨ added compare and merge functionality for branches with unit test cases [CS-36688]
A new branch is created for the feature as the prev branch `CS-36487-branch-compare-merge` encountered many merge conflicts.
1 parent d4a6899 commit 74c1550

File tree

8 files changed

+478
-4
lines changed

8 files changed

+478
-4
lines changed

lib/entity.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,25 @@ export function parseData (response, stackHeaders, contentTypeUID) {
267267
}
268268
return data
269269
}
270+
271+
export async function get (http, url, params, data) {
272+
const headers = {
273+
params: {
274+
...cloneDeep(data.branches),
275+
...cloneDeep(params)
276+
},
277+
headers: {
278+
...cloneDeep(this.stackHeaders)
279+
}
280+
} || {}
281+
try {
282+
const response = await http.get(url, headers)
283+
if (response.data) {
284+
return response.data
285+
} else {
286+
throw error(response)
287+
}
288+
} catch (err) {
289+
throw error(err)
290+
}
291+
}

lib/stack/branch/compare.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { get } from '../../entity'
2+
3+
/**
4+
*
5+
* @namespace Branch
6+
*/
7+
export function Compare (http, data = {}) {
8+
this.stackHeaders = data.stackHeaders
9+
this.urlPath = `/stacks/branches/compare`
10+
11+
/**
12+
* @description List of content types and global fields that exist in only one branch or are different between the two branches.
13+
* @memberof Compare
14+
* @func all
15+
* @returns {Promise<Response>} Promise for response.
16+
* @example
17+
* import * as contentstack from '@contentstack/management'
18+
* const client = contentstack.client()
19+
*
20+
* client.stack({ api_key: 'api_key'}).branch('branch_uid').compare('compare_branch_uid').all({skip: 0, limit: 100})
21+
* .then(response)
22+
* .catch(error)
23+
*
24+
*/
25+
this.all = async (params = {}) => {
26+
return await get(http, this.urlPath, params, data)
27+
}
28+
29+
/**
30+
* @description List of all or specific content types that exist in only one branch or are different between the two branches.
31+
* @memberof Compare
32+
* @func contentTypes
33+
* @param {string} params.uid Optional uid for Content Type to compare.
34+
* @returns {Promise<Response>} Promise for response.
35+
* @example
36+
* import * as contentstack from '@contentstack/management'
37+
* const client = contentstack.client()
38+
*
39+
* client.stack({ api_key: 'api_key'}).branch('branch_uid').compare().all({skip: 0, limit: 100})
40+
* .then(response)
41+
* .catch(error)
42+
*
43+
*/
44+
this.contentTypes = async (params = {}) => {
45+
let url = `${this.urlPath}/content_types`
46+
if (params.uid) {
47+
url = `${url}/${params.uid}`
48+
delete params.uid
49+
}
50+
return await get(http, url, params, data)
51+
}
52+
53+
/**
54+
* @description Compare allows you compare any or specific ContentType or GlobalFields.
55+
* @memberof Compare
56+
* @func globalFields
57+
* @param {string} params.uid Optional uid for Global Field to compare.
58+
* @returns {Promise<Response>} Promise for response.
59+
* @example
60+
* import * as contentstack from '@contentstack/management'
61+
* const client = contentstack.client()
62+
*
63+
* client.stack({ api_key: 'api_key'}).branch('branch_uid').compare().all({skip: 0, limit: 100})
64+
* .then(response)
65+
* .catch(error)
66+
*
67+
*/
68+
this.globalFields = async (params = {}) => {
69+
let url = `${this.urlPath}/global_fields`
70+
if (params.uid) {
71+
url = `${url}/${params.uid}`
72+
delete params.uid
73+
}
74+
return await get(http, url, params, data)
75+
}
76+
77+
return this
78+
}

lib/stack/branch/index.js

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import cloneDeep from 'lodash/cloneDeep'
22
import { create, query, fetch, deleteEntity } from '../../entity'
3+
import { Compare } from './compare'
4+
import { MergeQueue } from './mergeQueue'
5+
import error from '../../core/contentstackError'
36

47
/**
58
*
@@ -44,6 +47,29 @@ export function Branch (http, data = {}) {
4447
*
4548
*/
4649
this.fetch = fetch(http, 'branch')
50+
51+
/**
52+
* @description Compare allows you compare any or specific ContentType or GlobalFields.
53+
* @memberof Branch
54+
* @func compare
55+
* @returns {Compare} Instance of Compare.
56+
* @example
57+
* import * as contentstack from '@contentstack/management'
58+
* const client = contentstack.client()
59+
*
60+
* client.stack({ api_key: 'api_key'}).branch('branch_uid').compare()
61+
*
62+
*/
63+
this.compare = (compareBranchUid) => {
64+
const compareData = { stackHeaders: this.stackHeaders }
65+
if (compareBranchUid) {
66+
compareData.branches = {
67+
base_branch: this.uid,
68+
compare_branch: compareBranchUid
69+
}
70+
}
71+
return new Compare(http, compareData)
72+
}
4773
} else {
4874
/**
4975
* @description The Create a Branch call creates a new branch in a particular stack of your Contentstack account.
@@ -54,7 +80,7 @@ export function Branch (http, data = {}) {
5480
* @example
5581
* import * as contentstack from '@contentstack/management'
5682
* const client = contentstack.client()
57-
* const branch = {
83+
* const branch = {
5884
* name: 'branch_name',
5985
* source: 'master'
6086
* }
@@ -77,6 +103,63 @@ export function Branch (http, data = {}) {
77103
* .then((collection) => { console.log(collection) })
78104
*/
79105
this.query = query({ http, wrapperCollection: BranchCollection })
106+
107+
/**
108+
* @description Merge allows user to merge branches in a Stack.
109+
* @memberof Branch
110+
* @func merge
111+
* @returns {Object} Response Object
112+
*
113+
* @example
114+
* import * as contentstack from '@contentstack/management'
115+
* const client = contentstack.client()
116+
*
117+
* client.stack({ api_key: 'api_key'}).branch().merge({
118+
* base_branch: "main",
119+
* compare_branch: "dev",
120+
* default_merge_strategy: "merge_prefer_base",
121+
* item_merge_strategies: [
122+
* {
123+
* uid: "global_field_uid",
124+
* type: "global_field",
125+
* merge_strategy: "merge_prefer_base"
126+
* }
127+
* ],
128+
* merge_comment: "Merging dev into main",
129+
* no_revert: true
130+
* })
131+
*/
132+
this.merge = async (mergeObj) => {
133+
const url = '/stacks/branches/merge';
134+
const header = {
135+
headers: { ...cloneDeep(this.stackHeaders)},
136+
}
137+
try {
138+
const response = await http.post(url, mergeObj, header);
139+
if (response.data) return response.data;
140+
else throw error(response)
141+
} catch (e) {
142+
throw error(e);
143+
}
144+
}
145+
146+
/**
147+
* @description Merge Queue provides list of all recent merge jobs in a Stack.
148+
* @memberof Branch
149+
* @func mergeQueue
150+
* @returns {MergeQueue} Instance of MergeQueue
151+
*
152+
* @example
153+
* import * as contentstack from '@contentstack/management'
154+
* const client = contentstack.client()
155+
*
156+
* client.stack({ api_key: 'api_key'}).branch().mergeQueue()
157+
*
158+
*/
159+
this.mergeQueue = (uid) => {
160+
const mergeData = { stackHeaders: this.stackHeaders, uid }
161+
return new MergeQueue(http, mergeData)
162+
}
80163
}
81164
return this
82165
}
@@ -86,4 +169,4 @@ export function BranchCollection (http, data) {
86169
return obj.map((branchData) => {
87170
return new Branch(http, { branch: branchData, stackHeaders: data.stackHeaders })
88171
})
89-
}
172+
}

lib/stack/branch/mergeQueue.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { get } from '../../entity'
2+
3+
export function MergeQueue (http, data = {}) {
4+
this.stackHeaders = data.stackHeaders
5+
this.urlPath = `/stacks/branches/merge-queue`
6+
7+
if (data.uid) {
8+
/**
9+
* @description Fetch function gets the status of a merge job and it's configuration details.
10+
* @memberof MergeQueue
11+
* @func fetch
12+
* @returns {Promise<Response>} Promise for response.
13+
* @example
14+
* import * as contentstack from '@contentstack/management'
15+
* const client = contentstack.client()
16+
*
17+
* client.stack({ api_key: 'api_key'}).branch().mergeQueue('UID').fetch()
18+
* .then(response)
19+
* .catch(error)
20+
*
21+
*/
22+
this.fetch = async () => {
23+
const url = `${this.urlPath}/${data.uid}`
24+
return await get(http, url, {}, data)
25+
}
26+
} else {
27+
/**
28+
* @description Find function lists all recent merge jobs.
29+
* @memberof MergeQueue
30+
* @func find
31+
* @returns {Promise<Response>} Promise for response.
32+
* @example
33+
* import * as contentstack from '@contentstack/management'
34+
* const client = contentstack.client()
35+
*
36+
* client.stack({ api_key: 'api_key'}).branch().mergeQueue().find()
37+
* .then(response)
38+
* .catch(error)
39+
*
40+
*/
41+
this.find = async (params = {}) => {
42+
return await get(http, this.urlPath, params, data)
43+
}
44+
}
45+
46+
return this
47+
}

0 commit comments

Comments
 (0)