|
1 | | -import FormData from 'form-data'; |
2 | 1 | import fs from 'fs-extra'; |
3 | 2 | import path from 'path'; |
4 | 3 | import cliProgress from 'cli-progress'; |
5 | 4 | import { CommanderStatic } from 'commander'; |
| 5 | +import { AuthObject, CubeCloudClient, DeployController } from '@cubejs-backend/cloud'; |
| 6 | +import { ConfigCli } from '../config'; |
6 | 7 |
|
7 | | -import { DeployDirectory } from '../deploy'; |
8 | 8 | import { logStage, displayError, event } from '../utils'; |
9 | | -import { Config } from '../config'; |
10 | 9 |
|
11 | | -interface Hashes { |
12 | | - [key: string]: { |
13 | | - hash: string; |
14 | | - }; |
15 | | -} |
16 | | - |
17 | | -interface CloudReqResult { |
18 | | - transaction: string; |
19 | | - deploymentName: string; |
20 | | -} |
| 10 | +type DeployOptions = { |
| 11 | + directory: string, |
| 12 | + auth: AuthObject, |
| 13 | + uploadEnv: boolean, |
| 14 | + replaceEnv: boolean, |
| 15 | + token: string |
| 16 | +}; |
21 | 17 |
|
22 | | -const deploy = async ({ directory, auth, uploadEnv, token }: any) => { |
| 18 | +const deploy = async ({ directory, auth, uploadEnv, replaceEnv, token }: DeployOptions) => { |
23 | 19 | if (!(await fs.pathExists(path.join(process.cwd(), 'node_modules', '@cubejs-backend/server-core')))) { |
24 | 20 | await displayError( |
25 | 21 | '@cubejs-backend/server-core dependency not found. Please run deploy command from project root directory and ensure npm install has been run.' |
26 | 22 | ); |
27 | 23 | } |
28 | 24 |
|
| 25 | + const config = new ConfigCli(); |
29 | 26 | if (token) { |
30 | | - const config = new Config(); |
31 | 27 | await config.addAuthToken(token); |
32 | | - |
33 | | - await event({ |
34 | | - event: 'Cube Cloud CLI Authenticate' |
35 | | - }); |
36 | | - |
| 28 | + await event({ event: 'Cube Cloud CLI Authenticate' }); |
37 | 29 | console.log('Token successfully added!'); |
38 | 30 | } |
39 | 31 |
|
40 | | - const config = new Config(); |
41 | 32 | const bar = new cliProgress.SingleBar({ |
42 | 33 | format: '- Uploading files | {bar} | {percentage}% || {value} / {total} | {file}', |
43 | 34 | barCompleteChar: '\u2588', |
44 | 35 | barIncompleteChar: '\u2591', |
45 | 36 | hideCursor: true |
46 | 37 | }); |
47 | 38 |
|
48 | | - const deployDir = new DeployDirectory({ directory }); |
49 | | - const fileHashes: any = await deployDir.fileHashes(); |
50 | | - |
51 | | - const upstreamHashes: Hashes = await config.cloudReq({ |
52 | | - url: (deploymentId: string) => `build/deploy/${deploymentId}/files`, |
53 | | - method: 'GET', |
54 | | - auth |
55 | | - }); |
56 | | - |
57 | | - const { transaction, deploymentName }: CloudReqResult = await config.cloudReq({ |
58 | | - url: (deploymentId: string) => `build/deploy/${deploymentId}/start-upload`, |
59 | | - method: 'POST', |
60 | | - auth |
61 | | - }); |
62 | | - |
63 | | - if (uploadEnv) { |
64 | | - const envVariables = await config.envFile(`${directory}/.env`); |
65 | | - await config.cloudReq({ |
66 | | - url: (deploymentId) => `build/deploy/${deploymentId}/set-env`, |
67 | | - method: 'POST', |
68 | | - body: JSON.stringify({ |
69 | | - envVariables: JSON.stringify(envVariables), |
70 | | - }), |
71 | | - headers: { |
72 | | - 'Content-type': 'application/json' |
73 | | - }, |
74 | | - auth |
75 | | - }); |
76 | | - } |
77 | | - |
78 | | - await logStage(`Deploying ${deploymentName}...`, 'Cube Cloud CLI Deploy'); |
79 | | - |
80 | | - const files = Object.keys(fileHashes); |
81 | | - const fileHashesPosix = {}; |
82 | | - |
83 | | - bar.start(files.length, 0, { |
84 | | - file: '' |
85 | | - }); |
86 | | - |
87 | | - try { |
88 | | - for (let i = 0; i < files.length; i++) { |
89 | | - const file = files[i]; |
| 39 | + const envVariables = uploadEnv || replaceEnv ? await config.envFile(`${directory}/.env`) : {}; |
| 40 | + |
| 41 | + const cubeCloudClient = new CubeCloudClient(auth || (await config.deployAuthForCurrentDir())); |
| 42 | + const deployController = new DeployController(cubeCloudClient, { envVariables, replaceEnv }, { |
| 43 | + onStart: async (deploymentName, files) => { |
| 44 | + await logStage(`Deploying ${deploymentName}...`, 'Cube Cloud CLI Deploy'); |
| 45 | + bar.start(files.length, 0, { |
| 46 | + file: '' |
| 47 | + }); |
| 48 | + }, |
| 49 | + onUpdate: (i, { file }) => { |
90 | 50 | bar.update(i, { file }); |
91 | | - |
92 | | - const filePosix = file.split(path.sep).join(path.posix.sep); |
93 | | - fileHashesPosix[filePosix] = fileHashes[file]; |
94 | | - |
95 | | - if (!upstreamHashes[filePosix] || upstreamHashes[filePosix].hash !== fileHashes[file].hash) { |
96 | | - const formData = new FormData(); |
97 | | - formData.append('transaction', JSON.stringify(transaction)); |
98 | | - formData.append('fileName', filePosix); |
99 | | - formData.append('file', fs.createReadStream(path.join(directory, file)), { |
100 | | - filename: path.basename(file), |
101 | | - contentType: 'application/octet-stream' |
102 | | - }); |
103 | | - |
104 | | - await config.cloudReq({ |
105 | | - url: (deploymentId: string) => `build/deploy/${deploymentId}/upload-file`, |
106 | | - method: 'POST', |
107 | | - body: formData, |
108 | | - auth, |
109 | | - headers: formData.getHeaders() |
110 | | - }); |
111 | | - } |
| 51 | + }, |
| 52 | + onUpload: (files) => { |
| 53 | + bar.update(files.length, { file: 'Post processing...' }); |
| 54 | + }, |
| 55 | + onFinally: () => { |
| 56 | + bar.stop(); |
112 | 57 | } |
113 | | - bar.update(files.length, { file: 'Post processing...' }); |
114 | | - await config.cloudReq({ |
115 | | - url: (deploymentId: string) => `build/deploy/${deploymentId}/finish-upload`, |
116 | | - method: 'POST', |
117 | | - body: JSON.stringify({ |
118 | | - transaction, |
119 | | - files: fileHashesPosix |
120 | | - }), |
121 | | - headers: { 'Content-type': 'application/json' }, |
122 | | - auth |
123 | | - }); |
124 | | - } finally { |
125 | | - bar.stop(); |
126 | | - } |
| 58 | + }); |
127 | 59 |
|
| 60 | + await deployController.deploy(directory); |
128 | 61 | await logStage('Done 🎉', 'Cube Cloud CLI Deploy Success'); |
129 | 62 | }; |
130 | 63 |
|
131 | 64 | export function configureDeployCommand(program: CommanderStatic) { |
132 | 65 | program |
133 | 66 | .command('deploy') |
134 | 67 | .description('Deploy project to Cube Cloud') |
135 | | - .option('--upload-env', 'Upload .env file to CubeCloud') |
| 68 | + .option('--upload-env', 'Use .env file to populate environment variables in Cube Cloud. Only set them once during the very first upload for this deployment') |
| 69 | + .option('--replace-env', 'Use .env file to populate environment variables in Cube Cloud. Replace them with new ones during every upload for this deployment') |
136 | 70 | .option('--token <token>', 'Add auth token to CubeCloud') |
137 | 71 | .option('--directory [path]', 'Specify path to conf directory', './') |
138 | 72 | .action( |
|
0 commit comments