@cmflow/cli 3.0.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/install-state.gz +0 -0
- package/package.json +2 -1
- package/src/common/back/directus/directus-flow.js +4 -0
- package/src/common/back/http/http-request.js +46 -34
- package/src/common/back/http/http-request.spec.js +17 -15
- package/src/common/back/jira/jira-request.js +5 -1
- package/src/common/back/jira/jira-request.spec.js +13 -7
- package/src/common/back/jira/jira-search.spec.js +1 -0
- package/src/common/get-config.js +2 -0
- package/src/semantic/core/verify-conditions.js +3 -2
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmflow/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "An awesome Git Flow",
|
|
5
5
|
"author": "camfou",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"any-observable": "0.5.1",
|
|
33
33
|
"axios": "1.8.2",
|
|
34
|
+
"axios-retry": "^4.5.0",
|
|
34
35
|
"chalk": "^4.1.0",
|
|
35
36
|
"commander": "5.1.0",
|
|
36
37
|
"execa": "5.1.1",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import axiosRetry from "axios-retry";
|
|
2
|
+
|
|
1
3
|
import { getConfig } from "../../get-config.js";
|
|
2
4
|
import { httpRequest } from "../http/http-request.js";
|
|
3
5
|
|
|
@@ -25,6 +27,8 @@ export async function triggerDirectusFlow(projectId, versions, opts = {}) {
|
|
|
25
27
|
projectId,
|
|
26
28
|
versions
|
|
27
29
|
},
|
|
30
|
+
retries: 3,
|
|
31
|
+
retryDelay: axiosRetry.exponentialDelay,
|
|
28
32
|
...opts
|
|
29
33
|
};
|
|
30
34
|
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import axiosRetry from "axios-retry";
|
|
2
3
|
|
|
3
4
|
import { getHttpProxy } from "./http-proxy.js";
|
|
4
5
|
|
|
5
|
-
// export type HttpRequestOptions = {
|
|
6
|
-
// rejectUnauthorized?: boolean;
|
|
7
|
-
// callee?: string;
|
|
8
|
-
// params?: Record<string, string>;
|
|
9
|
-
// } & fetch.RequestInit;
|
|
10
6
|
/**
|
|
11
|
-
* @typedef {Object
|
|
7
|
+
* @typedef {Object} RetryOptions
|
|
8
|
+
* @property {number} [retries=3] - Number of retry attempts
|
|
9
|
+
* @property {number} [retryDelay=1000] - Delay between retries in ms
|
|
10
|
+
* @property {boolean} [retryOnNetworkError=true] - Retry on network errors
|
|
11
|
+
* @property {boolean} [retryOnIdempotentRequests=true] - Retry on 5xx for idempotent requests
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} HttpRequestOptions
|
|
12
16
|
* @property {boolean} [rejectUnauthorized] - Whether to reject unauthorized SSL certificates
|
|
13
17
|
* @property {string} [callee] - The name of the caller
|
|
14
18
|
* @property {Record<string, string>} [params] - Query parameters to be included in the request
|
|
15
19
|
* @property {string} [method] - HTTP method (default: 'get')
|
|
16
20
|
* @property {Record<string, string>} [headers] - Custom headers to be included in the request
|
|
21
|
+
* @property {RetryOptions|boolean} [retry] - Retry configuration (true for defaults, or custom config)
|
|
17
22
|
*/
|
|
18
23
|
|
|
19
24
|
/**
|
|
@@ -23,43 +28,50 @@ import { getHttpProxy } from "./http-proxy.js";
|
|
|
23
28
|
* @return {Promise<*>}
|
|
24
29
|
*/
|
|
25
30
|
export async function httpRequest(endpoint, options = {}) {
|
|
26
|
-
const { callee, headers, method = "get", params = {}, rejectUnauthorized } = options;
|
|
27
|
-
const
|
|
31
|
+
const { callee, headers, method = "get", params = {}, rejectUnauthorized, ...rest } = options;
|
|
32
|
+
const httpsAgent = getHttpProxy({
|
|
28
33
|
rejectUnauthorized,
|
|
29
34
|
callee
|
|
30
35
|
});
|
|
31
36
|
|
|
32
|
-
const
|
|
33
|
-
const url = `${endpoint}${queryParams.size ? "?" + queryParams : ""}`;
|
|
37
|
+
const instance = axios.create();
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
axiosRetry(instance, options);
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const response = await instance({
|
|
43
|
+
url: endpoint,
|
|
44
|
+
method,
|
|
45
|
+
params,
|
|
46
|
+
headers: {
|
|
47
|
+
...headers,
|
|
48
|
+
"Content-Type": "application/json"
|
|
49
|
+
},
|
|
50
|
+
httpsAgent,
|
|
51
|
+
...rest
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.info({
|
|
55
|
+
message: `Successfully retrieved data from ${callee}`,
|
|
56
|
+
url: endpoint,
|
|
57
|
+
method: method.toUpperCase(),
|
|
58
|
+
status: response.status
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return response.data;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const status = error.response?.status;
|
|
64
|
+
const responseData = error.response?.data;
|
|
44
65
|
|
|
45
|
-
if (!response.ok) {
|
|
46
66
|
console.error({
|
|
47
67
|
...options,
|
|
48
68
|
message: `Fail to retrieved data from ${callee}`,
|
|
49
|
-
url,
|
|
69
|
+
url: endpoint,
|
|
50
70
|
method: method.toUpperCase(),
|
|
51
|
-
status
|
|
52
|
-
response:
|
|
71
|
+
status,
|
|
72
|
+
response: responseData
|
|
53
73
|
});
|
|
54
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
55
|
-
}
|
|
56
74
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
url,
|
|
60
|
-
method: method.toUpperCase(),
|
|
61
|
-
status: response.status
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
return response.json();
|
|
75
|
+
throw new Error(`HTTP error! status: ${status}`);
|
|
76
|
+
}
|
|
65
77
|
}
|
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import axiosRetry from "axios-retry";
|
|
2
3
|
|
|
3
4
|
import { getHttpProxy } from "./http-proxy.js";
|
|
4
5
|
import { httpRequest } from "./http-request.js";
|
|
5
6
|
|
|
6
|
-
vi.mock("
|
|
7
|
+
vi.mock("axios");
|
|
8
|
+
vi.mock("axios-retry");
|
|
7
9
|
vi.mock("./http-proxy.js");
|
|
8
10
|
|
|
9
11
|
describe("httpRequest", () => {
|
|
12
|
+
let mockInstance;
|
|
13
|
+
|
|
10
14
|
beforeEach(() => {
|
|
11
15
|
vi.clearAllMocks();
|
|
16
|
+
mockInstance = vi.fn();
|
|
17
|
+
vi.mocked(axios.create).mockReturnValue(mockInstance);
|
|
12
18
|
});
|
|
13
19
|
|
|
14
20
|
it("should create an agent in production with proxy", async () => {
|
|
15
|
-
|
|
21
|
+
mockInstance.mockResolvedValue({
|
|
16
22
|
status: 200,
|
|
17
|
-
|
|
18
|
-
ok: true,
|
|
19
|
-
async json() {
|
|
20
|
-
return { data: "test" };
|
|
21
|
-
}
|
|
23
|
+
data: { data: "test" }
|
|
22
24
|
});
|
|
23
25
|
|
|
24
26
|
const result = await httpRequest("http://example.com/test-endpoint", {
|
|
@@ -29,18 +31,18 @@ describe("httpRequest", () => {
|
|
|
29
31
|
rejectUnauthorized: undefined,
|
|
30
32
|
callee: "test"
|
|
31
33
|
});
|
|
34
|
+
expect(axios.create).toHaveBeenCalled();
|
|
35
|
+
expect(axiosRetry).toHaveBeenCalled();
|
|
32
36
|
expect(result).toEqual({ data: "test" });
|
|
33
37
|
});
|
|
34
38
|
|
|
35
39
|
it("should throw an error if the response is not ok", async () => {
|
|
36
|
-
|
|
40
|
+
const axiosError = new Error("Request failed");
|
|
41
|
+
axiosError.response = {
|
|
37
42
|
status: 500,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return { data: "test" };
|
|
42
|
-
}
|
|
43
|
-
});
|
|
43
|
+
data: { error: "Internal server error" }
|
|
44
|
+
};
|
|
45
|
+
mockInstance.mockRejectedValue(axiosError);
|
|
44
46
|
|
|
45
47
|
await expect(httpRequest("http://example.com/test-endpoint", { callee: "test" })).rejects.toThrow("HTTP error! status: 500");
|
|
46
48
|
});
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import axiosRetry from "axios-retry";
|
|
2
|
+
|
|
1
3
|
import { getConfig } from "../../get-config.js";
|
|
2
4
|
import { httpRequest } from "../http/http-request.js";
|
|
3
5
|
|
|
@@ -16,6 +18,8 @@ export async function jiraRequest(endpoint, opts = {}) {
|
|
|
16
18
|
headers: {
|
|
17
19
|
...opts.headers,
|
|
18
20
|
Authorization: `Basic ${auth}`
|
|
19
|
-
}
|
|
21
|
+
},
|
|
22
|
+
retries: 3,
|
|
23
|
+
retryDelay: axiosRetry.exponentialDelay
|
|
20
24
|
});
|
|
21
25
|
}
|
|
@@ -2,6 +2,7 @@ import { httpRequest } from "../http/http-request.js";
|
|
|
2
2
|
import { jiraRequest } from "./jira-request.js";
|
|
3
3
|
|
|
4
4
|
vi.mock("../http/http-request.js");
|
|
5
|
+
vi.mock("axios-retry");
|
|
5
6
|
|
|
6
7
|
describe("jiraRequest", () => {
|
|
7
8
|
beforeEach(() => {
|
|
@@ -34,14 +35,19 @@ describe("jiraRequest", () => {
|
|
|
34
35
|
params: { key: "value" }
|
|
35
36
|
});
|
|
36
37
|
|
|
37
|
-
expect(httpRequest).toHaveBeenCalledWith(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
expect(httpRequest).toHaveBeenCalledWith(
|
|
39
|
+
expect.stringContaining("/test-endpoint"),
|
|
40
|
+
expect.objectContaining({
|
|
41
|
+
callee: "JIRA",
|
|
42
|
+
method: "post",
|
|
43
|
+
params: { key: "value" },
|
|
44
|
+
headers: expect.objectContaining({
|
|
45
|
+
Authorization: expect.stringContaining("Basic ")
|
|
46
|
+
}),
|
|
47
|
+
retries: 3,
|
|
48
|
+
retryDelay: expect.any(Function)
|
|
43
49
|
})
|
|
44
|
-
|
|
50
|
+
);
|
|
45
51
|
expect(result).toEqual(mockResponse);
|
|
46
52
|
});
|
|
47
53
|
|
package/src/common/get-config.js
CHANGED
|
@@ -87,6 +87,7 @@ export function getConfig() {
|
|
|
87
87
|
GIT_USER_EMAIL,
|
|
88
88
|
GITLAB_USER_EMAIL,
|
|
89
89
|
GITLAB_USER_NAME,
|
|
90
|
+
GIT_FETCH_MAX_DEPTH,
|
|
90
91
|
JIRA_API,
|
|
91
92
|
JIRA_EMAIL,
|
|
92
93
|
JIRA_TOKEN,
|
|
@@ -137,6 +138,7 @@ export function getConfig() {
|
|
|
137
138
|
REPOSITORY_URL: get(pkg, "repository.url", get(pkg, "repository", REPOSITORY_URL)),
|
|
138
139
|
GIT_USER_NAME: GIT_USER_NAME || GITLAB_USER_NAME,
|
|
139
140
|
GIT_USER_EMAIL: GIT_USER_EMAIL || GITLAB_USER_EMAIL,
|
|
141
|
+
GIT_FETCH_MAX_DEPTH,
|
|
140
142
|
GIT_DISABLE_SSL,
|
|
141
143
|
BUMP_METHOD,
|
|
142
144
|
JIRA_API,
|
|
@@ -10,7 +10,7 @@ export function verifyConditions(pluginConfig, context) {
|
|
|
10
10
|
context.config = getConfig();
|
|
11
11
|
const {
|
|
12
12
|
branch,
|
|
13
|
-
config: { USER, EMAIL, ORIGIN }
|
|
13
|
+
config: { USER, EMAIL, ORIGIN, GIT_FETCH_MAX_DEPTH }
|
|
14
14
|
} = context;
|
|
15
15
|
|
|
16
16
|
if (USER && EMAIL) {
|
|
@@ -26,7 +26,8 @@ export function verifyConditions(pluginConfig, context) {
|
|
|
26
26
|
process.exit(1);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
git.fetch().sync();
|
|
29
|
+
GIT_FETCH_MAX_DEPTH ? git.fetch(`--depth=${GIT_FETCH_MAX_DEPTH}`).sync() : git.fetch().sync();
|
|
30
|
+
|
|
30
31
|
git.checkout(branch.name).sync();
|
|
31
32
|
git.branch(`--set-upstream-to=${ORIGIN}/${branch.name}`, branch.name).sync();
|
|
32
33
|
}
|