@squiz/component-cli-lib 1.2.1-alpha.106 → 1.2.1-alpha.17
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/CHANGELOG.md +0 -730
- package/jest.config.ts +3 -8
- package/lib/index.d.ts +1 -2
- package/lib/index.js +79 -5
- package/lib/index.js.map +1 -1
- package/lib/{component-dev.spec.d.ts → test.d.ts} +0 -0
- package/lib/test.js +12 -0
- package/lib/test.js.map +1 -0
- package/lib/utils/zipDirectory.d.ts +1 -0
- package/lib/utils/zipDirectory.js +32 -0
- package/lib/utils/zipDirectory.js.map +1 -0
- package/package.json +16 -22
- package/src/index.ts +90 -2
- package/src/test.ts +9 -0
- package/src/utils/zipDirectory.ts +31 -0
- package/tsconfig.json +1 -6
- package/tsconfig.tsbuildinfo +1 -1
- package/.gitlab-ci.yml +0 -118
- package/jest.integration.config.ts +0 -17
- package/lib/component-dev.d.ts +0 -13
- package/lib/component-dev.js +0 -40
- package/lib/component-dev.js.map +0 -1
- package/lib/component-dev.spec.js +0 -91
- package/lib/component-dev.spec.js.map +0 -1
- package/lib/integration-tests/__components__/big-package/manifest.json +0 -32
- package/lib/integration-tests/__components__/cmp-static-file-test/manifest.json +0 -36
- package/lib/integration-tests/__components__/invalid-manifest/manifest.json +0 -24
- package/lib/integration-tests/helper.d.ts +0 -18
- package/lib/integration-tests/helper.js +0 -70
- package/lib/integration-tests/helper.js.map +0 -1
- package/lib/integration-tests/service-deployment.spec.d.ts +0 -1
- package/lib/integration-tests/service-deployment.spec.js +0 -16
- package/lib/integration-tests/service-deployment.spec.js.map +0 -1
- package/lib/integration-tests/test-setup.d.ts +0 -0
- package/lib/integration-tests/test-setup.js +0 -3
- package/lib/integration-tests/test-setup.js.map +0 -1
- package/lib/integration-tests/upload-and-render-component.spec.d.ts +0 -1
- package/lib/integration-tests/upload-and-render-component.spec.js +0 -136
- package/lib/integration-tests/upload-and-render-component.spec.js.map +0 -1
- package/lib/upload-component-folder.d.ts +0 -3
- package/lib/upload-component-folder.js +0 -128
- package/lib/upload-component-folder.js.map +0 -1
- package/src/component-dev.spec.ts +0 -111
- package/src/component-dev.ts +0 -34
- package/src/integration-tests/__components__/big-package/manifest.json +0 -33
- package/src/integration-tests/__components__/big-package/render-json.js +0 -5
- package/src/integration-tests/__components__/cmp-static-file-test/main.js +0 -10
- package/src/integration-tests/__components__/cmp-static-file-test/manifest.json +0 -40
- package/src/integration-tests/__components__/cmp-static-file-test/public/static-library-file.js +0 -1
- package/src/integration-tests/__components__/invalid-manifest/main.js +0 -7
- package/src/integration-tests/__components__/invalid-manifest/manifest.json +0 -26
- package/src/integration-tests/__components__/invalid-upload/main.js +0 -7
- package/src/integration-tests/helper.ts +0 -75
- package/src/integration-tests/service-deployment.spec.ts +0 -21
- package/src/integration-tests/test-setup.ts +0 -1
- package/src/integration-tests/upload-and-render-component.spec.ts +0 -141
- package/src/upload-component-folder.ts +0 -137
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { renderService, managementService, ci_buildVersion, ci_buildBranch } from './helper';
|
|
2
|
-
|
|
3
|
-
interface HealthInfo {
|
|
4
|
-
status: string;
|
|
5
|
-
buildVersion: string;
|
|
6
|
-
buildBranch: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
describe('Verify latest services deployments', () => {
|
|
10
|
-
it('Should have latest Management API service', async () => {
|
|
11
|
-
const response: HealthInfo = (await managementService.get('/health')).data;
|
|
12
|
-
expect(response.buildVersion).toBe(ci_buildVersion);
|
|
13
|
-
expect(response.buildBranch).toBe(ci_buildBranch);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('Should have latest Render Runtime service', async () => {
|
|
17
|
-
const response: HealthInfo = (await renderService.get('/health')).data;
|
|
18
|
-
expect(response.buildVersion).toBe(ci_buildVersion);
|
|
19
|
-
expect(response.buildBranch).toBe(ci_buildBranch);
|
|
20
|
-
});
|
|
21
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
jest.setTimeout(60_000);
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { uploadComponentFolder } from '../index';
|
|
2
|
-
import configObj, {
|
|
3
|
-
renderService,
|
|
4
|
-
managementService,
|
|
5
|
-
getTestComponents,
|
|
6
|
-
createFile,
|
|
7
|
-
removeFile,
|
|
8
|
-
addComponentSet,
|
|
9
|
-
deleteComponentSet,
|
|
10
|
-
} from './helper';
|
|
11
|
-
import color from 'cli-color';
|
|
12
|
-
import path from 'path';
|
|
13
|
-
import supertest from 'supertest';
|
|
14
|
-
import { logger } from '../upload-component-folder';
|
|
15
|
-
import { ComponentSetWebModel } from '@squiz/component-lib';
|
|
16
|
-
|
|
17
|
-
const mockConsoleError = jest.fn();
|
|
18
|
-
const mockConsoleLog = jest.fn();
|
|
19
|
-
|
|
20
|
-
const orgConsoleError = console.error;
|
|
21
|
-
const webPath = 'set';
|
|
22
|
-
|
|
23
|
-
afterAll(async () => {
|
|
24
|
-
// clean up the component added by the test
|
|
25
|
-
await deleteComponentSet(webPath);
|
|
26
|
-
|
|
27
|
-
for (const componentName of getTestComponents()) {
|
|
28
|
-
try {
|
|
29
|
-
await managementService.delete(`/component/${componentName}`);
|
|
30
|
-
} catch {
|
|
31
|
-
// no op
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('Test isolated test cases', () => {
|
|
37
|
-
beforeEach(() => {
|
|
38
|
-
jest.spyOn(logger, 'error').mockImplementation(mockConsoleError);
|
|
39
|
-
jest.spyOn(logger, 'info').mockImplementation(mockConsoleLog);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('Should fail uploading a component without manifest.json', async () => {
|
|
43
|
-
mockConsoleError.mockClear();
|
|
44
|
-
const componentPath = path.join(__dirname, '/__components__/invalid-upload');
|
|
45
|
-
await uploadComponentFolder(componentPath, configObj.managementServiceUrl, configObj.renderServiceUrl);
|
|
46
|
-
expect(mockConsoleError.mock.calls[0][0]).toEqual(color.red('manifest could not be found'));
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('Should fail uploading a component that has invalid manifest.json', async () => {
|
|
50
|
-
mockConsoleError.mockClear();
|
|
51
|
-
const componentPath = path.join(__dirname, '/__components__/invalid-manifest');
|
|
52
|
-
await uploadComponentFolder(componentPath, configObj.managementServiceUrl, configObj.renderServiceUrl);
|
|
53
|
-
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
54
|
-
color.red('/name: pattern must match pattern "^[a-zA-Z0-9_\\-]+$"'),
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('Should fail uploading the component that has size more than 100MB', async () => {
|
|
59
|
-
mockConsoleError.mockClear();
|
|
60
|
-
const componentPath = path.join(__dirname, '/__components__/big-package');
|
|
61
|
-
const filePath = `${componentPath}/105mb-file`;
|
|
62
|
-
await createFile(filePath, 105); // Higher limit has been used because compression reduces the size if you use closer to 100MB
|
|
63
|
-
await uploadComponentFolder(componentPath, configObj.managementServiceUrl, configObj.renderServiceUrl);
|
|
64
|
-
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
65
|
-
color.red(['File size exceeds the maximum limit of 100MB'].join('')),
|
|
66
|
-
);
|
|
67
|
-
removeFile(filePath);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('Deploy basic component having a static file', () => {
|
|
72
|
-
// component to deploy for this test
|
|
73
|
-
const componentPath = path.join(__dirname, '/__components__/cmp-static-file-test');
|
|
74
|
-
|
|
75
|
-
beforeAll(async () => {
|
|
76
|
-
await deleteComponentSet(webPath);
|
|
77
|
-
for (const componentName of getTestComponents()) {
|
|
78
|
-
try {
|
|
79
|
-
await managementService.delete(`/component/${componentName}`);
|
|
80
|
-
} catch {
|
|
81
|
-
// no op
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
beforeEach(() => {
|
|
87
|
-
console.error = mockConsoleError;
|
|
88
|
-
console.log = mockConsoleLog;
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
afterEach(() => {
|
|
92
|
-
console.error = orgConsoleError;
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('Should upload the component and return a valid url to preview', async () => {
|
|
96
|
-
mockConsoleLog.mockClear();
|
|
97
|
-
console.log(configObj.managementServiceUrl, configObj.renderServiceUrl);
|
|
98
|
-
|
|
99
|
-
await uploadComponentFolder(componentPath, configObj.managementServiceUrl, configObj.renderServiceUrl);
|
|
100
|
-
|
|
101
|
-
const url = /uploaded location: (.*)/.exec(mockConsoleLog.mock.lastCall)?.[1] || '';
|
|
102
|
-
const uploadedComponent = '<a href="/r/set/cmp-static-file-test/1.0.0">1.0.0</a>';
|
|
103
|
-
const get = await supertest(url).get('/');
|
|
104
|
-
|
|
105
|
-
expect(get.status).toEqual(200);
|
|
106
|
-
expect((get as any)?.res?.text).toContain(uploadedComponent);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('Should fail upload the component with same version', async () => {
|
|
110
|
-
mockConsoleError.mockClear();
|
|
111
|
-
await uploadComponentFolder(componentPath, configObj.managementServiceUrl, configObj.renderServiceUrl);
|
|
112
|
-
expect(mockConsoleError.mock.calls[0][0]).toEqual(
|
|
113
|
-
color.red('Cannot upload component version, cmp-static-file-test 1.0.0 already exists'),
|
|
114
|
-
);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('Should render component', async () => {
|
|
118
|
-
const componentSet: ComponentSetWebModel = {
|
|
119
|
-
webPath,
|
|
120
|
-
displayName: 'Set',
|
|
121
|
-
description: 'Set description',
|
|
122
|
-
headers: {},
|
|
123
|
-
envVars: {},
|
|
124
|
-
components: {
|
|
125
|
-
'cmp-static-file-test': [{ envVars: {}, version: '1.0.0' }],
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
await addComponentSet(componentSet);
|
|
130
|
-
|
|
131
|
-
const response = await renderService.get('/r/set/cmp-static-file-test/1.0.0/?something=hello');
|
|
132
|
-
expect(response.status).toEqual(200);
|
|
133
|
-
expect(response.data).toEqual(
|
|
134
|
-
[
|
|
135
|
-
'<div>Input: hello</div>',
|
|
136
|
-
'<div>cmp-static-file-test 1.0.0 ',
|
|
137
|
-
`${configObj.renderServiceUrl}/s/cmp-static-file-test/1.0.0/birthday-cake.png</div>`,
|
|
138
|
-
].join(''),
|
|
139
|
-
);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { ScanStatus, uploadFile } from '@squiz/virus-scanner-lib';
|
|
2
|
-
import { loadManifest } from '@squiz/component-lib';
|
|
3
|
-
import { zipDirectory } from '@squiz/dx-common-lib';
|
|
4
|
-
import { V1 } from '@squiz/component-lib';
|
|
5
|
-
import fsp from 'fs/promises';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import axios, { AxiosResponse, AxiosError, AxiosInstance } from 'axios';
|
|
8
|
-
import color from 'cli-color';
|
|
9
|
-
import { getLogger, Logger } from '@squiz/dx-logger-lib';
|
|
10
|
-
|
|
11
|
-
export const logger: Logger = getLogger({ name: 'upload-component', format: 'human' });
|
|
12
|
-
|
|
13
|
-
export async function uploadComponentFolder(
|
|
14
|
-
folderPath: string,
|
|
15
|
-
componentServiceManagementUrl: string,
|
|
16
|
-
componentRenderServiceUrl: string,
|
|
17
|
-
): Promise<void> {
|
|
18
|
-
const tmpDir = path.resolve(await fsp.mkdtemp('cmp-upload'));
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
const axiosInstance = axios.create({
|
|
22
|
-
baseURL: componentServiceManagementUrl,
|
|
23
|
-
headers: {
|
|
24
|
-
'content-type': 'application/json',
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
await preUploadChecks(folderPath, componentRenderServiceUrl);
|
|
29
|
-
logger.info('Initial scanning');
|
|
30
|
-
const zip = await zipDirectory(folderPath, tmpDir);
|
|
31
|
-
|
|
32
|
-
const initialUpload = await handleResponse<any>(axiosInstance.post('upload-component'));
|
|
33
|
-
|
|
34
|
-
logger.info(`deployment id: ${initialUpload.id} status: transferring`);
|
|
35
|
-
await uploadFile(initialUpload, zip);
|
|
36
|
-
|
|
37
|
-
await watchAndWaitForUploadAndScanComplete(initialUpload.id, axiosInstance);
|
|
38
|
-
|
|
39
|
-
logger.info(`deployment id: ${initialUpload.id} status: deploying component folder`);
|
|
40
|
-
const result = await handleResponse<any>(axiosInstance.post(`upload-component/next/${initialUpload.id}`));
|
|
41
|
-
|
|
42
|
-
await fsp.rm(tmpDir, { force: true, recursive: true });
|
|
43
|
-
|
|
44
|
-
if (result.status === 'successful') {
|
|
45
|
-
logger.info(`deployment id: ${initialUpload.id} status: ${color.green('success')}`);
|
|
46
|
-
logger.info(`uploaded location: ${result.accessLink}`);
|
|
47
|
-
} else {
|
|
48
|
-
logger.error('failed for an unknown reason', color.red(result));
|
|
49
|
-
}
|
|
50
|
-
} catch (e) {
|
|
51
|
-
await fsp.rm(tmpDir, { force: true, recursive: true });
|
|
52
|
-
|
|
53
|
-
if (e instanceof Error) {
|
|
54
|
-
logger.error(color.red(e.message));
|
|
55
|
-
} else {
|
|
56
|
-
throw e;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function preUploadChecks(folderPath: string, renderService: string) {
|
|
62
|
-
const result = await loadManifest(path.join(folderPath, `manifest.json`));
|
|
63
|
-
if (await checkIfVersionExists(result, renderService)) {
|
|
64
|
-
throw new Error(`Cannot upload component version, ${result.name} ${result.version} already exists`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function checkIfVersionExists(inputManifest: V1, renderService: string) {
|
|
69
|
-
const axiosInstance = axios.create({
|
|
70
|
-
baseURL: renderService,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const response = await axiosInstance.get(`d/${inputManifest.name}/${inputManifest.version}/manifest.json`);
|
|
75
|
-
if (response.status === 200) {
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
throw new Error(`Unexpected response code ${response.status}`);
|
|
79
|
-
} catch (error) {
|
|
80
|
-
if (isAxiosError(error)) {
|
|
81
|
-
const { response } = error;
|
|
82
|
-
if (response?.status === 404) {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
throw error;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function watchAndWaitForUploadAndScanComplete(id: string, axiosInstance: AxiosInstance): Promise<void> {
|
|
91
|
-
const poll = () => handleResponse<ScanStatus>(axiosInstance.get('upload-component/status/' + id));
|
|
92
|
-
|
|
93
|
-
return new Promise((resolve, reject) => {
|
|
94
|
-
const recurse = () =>
|
|
95
|
-
poll().then(async (req) => {
|
|
96
|
-
if (req.status == 'Success') {
|
|
97
|
-
resolve();
|
|
98
|
-
} else if (req.status == 'Flagged') {
|
|
99
|
-
reject(new Error('upload has been flagged as a virus'));
|
|
100
|
-
} else if (req.status == 'Error') {
|
|
101
|
-
reject(new Error('there has been an error'));
|
|
102
|
-
} else {
|
|
103
|
-
setTimeout(async () => {
|
|
104
|
-
await recurse();
|
|
105
|
-
}, 1000);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
recurse();
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async function handleResponse<T>(axiosInstance: Promise<AxiosResponse<T>>): Promise<T> {
|
|
114
|
-
try {
|
|
115
|
-
const response = await axiosInstance;
|
|
116
|
-
return response.data;
|
|
117
|
-
} catch (error) {
|
|
118
|
-
throw handleError(error);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function handleError(error: any): Error {
|
|
123
|
-
const { response } = error;
|
|
124
|
-
if (!response || !isAxiosError(error)) {
|
|
125
|
-
return error;
|
|
126
|
-
}
|
|
127
|
-
const message = (response.data as any).message;
|
|
128
|
-
if (message) {
|
|
129
|
-
return new Error(`Unexpected response code ${response.status}. message: ${message}`);
|
|
130
|
-
} else {
|
|
131
|
-
return new Error(`Unexpected response code ${response.status}.`);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function isAxiosError(error: any): error is AxiosError {
|
|
136
|
-
return error && error.isAxiosError === true;
|
|
137
|
-
}
|