platformatic 0.20.1 → 0.21.0
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/cli.js +2 -0
- package/help/deploy.txt +22 -0
- package/help/help.txt +1 -0
- package/lib/deploy.js +143 -0
- package/package.json +11 -8
- package/test/deploy.test.js +174 -0
- package/test/fixtures/app-to-deploy/.env +2 -0
- package/test/fixtures/app-to-deploy/.secrets.env +2 -0
- package/test/fixtures/app-to-deploy/package.json +7 -0
- package/test/fixtures/app-to-deploy/platformatic.db.json +17 -0
- package/test/helper.js +55 -1
package/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import { isColorSupported } from 'colorette'
|
|
|
12
12
|
import helpMe from 'help-me'
|
|
13
13
|
import { upgrade } from './lib/upgrade.js'
|
|
14
14
|
import { gh } from './lib/gh.js'
|
|
15
|
+
import { deploy } from './lib/deploy.js'
|
|
15
16
|
|
|
16
17
|
import { logo } from './lib/ascii.js'
|
|
17
18
|
|
|
@@ -44,6 +45,7 @@ program.register('help db', async (args) => runDB(['help', ...args]))
|
|
|
44
45
|
program.register('help service', async (args) => runService(['help', ...args]))
|
|
45
46
|
program.register({ command: 'login', strict: true }, login)
|
|
46
47
|
program.register('gh', gh)
|
|
48
|
+
program.register('deploy', deploy)
|
|
47
49
|
|
|
48
50
|
const args = minimist(process.argv.slice(2), {
|
|
49
51
|
boolean: ['help', 'version'],
|
package/help/deploy.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Deploys a Platformatic application to the cloud
|
|
2
|
+
|
|
3
|
+
``` bash
|
|
4
|
+
$ platformatic deploy
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Options:
|
|
8
|
+
|
|
9
|
+
-t, --type static/dynamic The type of the workspace.
|
|
10
|
+
-c, --config FILE Specify a configuration file to use
|
|
11
|
+
-l --label TEXT The deploy label. Only for dynamic workspaces.
|
|
12
|
+
-e --env FILE The environment file to use. Default: ".env"
|
|
13
|
+
-s --secrets FILE The secrets file to use. Default: ".secrets.env"
|
|
14
|
+
--workspace-id uuid The workspace id where the application will be deployed
|
|
15
|
+
--workspace-key TEXT The workspace key where the application will be deployed
|
|
16
|
+
|
|
17
|
+
To deploy a Platformatic application to the cloud you should go to the
|
|
18
|
+
Platformatic cloud dashboard and create a workspace. Then you can get your
|
|
19
|
+
workspace id and key from the workspace settings page.
|
|
20
|
+
|
|
21
|
+
Tp deploy an application to a dynamic workspace, you will need to specify the
|
|
22
|
+
deploy label. You can get it in you cloud dashboard or specify a new one.
|
package/help/help.txt
CHANGED
|
@@ -6,3 +6,4 @@ Welcome to Platformatic. Available commands are:
|
|
|
6
6
|
* service - start Platformatic Service; type `platformatic service help` to know more.
|
|
7
7
|
* upgrade - upgrade the Platformatic configuration to the latest version.
|
|
8
8
|
* gh - creates a new gh action for Platformatic deployments
|
|
9
|
+
* deploy - deploy a Platformatic application to the cloud
|
package/lib/deploy.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { isAbsolute, dirname, relative } from 'path'
|
|
4
|
+
|
|
5
|
+
import pino from 'pino'
|
|
6
|
+
import pretty from 'pino-pretty'
|
|
7
|
+
import inquirer from 'inquirer'
|
|
8
|
+
import parseArgs from 'minimist'
|
|
9
|
+
import deployClient from '@platformatic/deploy-client'
|
|
10
|
+
|
|
11
|
+
export const DEPLOY_SERVICE_HOST = 'https://plt-production-deploy-service.fly.dev'
|
|
12
|
+
|
|
13
|
+
const WORKSPACE_TYPES = ['static', 'dynamic']
|
|
14
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
15
|
+
|
|
16
|
+
const logger = pino(pretty({
|
|
17
|
+
translateTime: 'SYS:HH:MM:ss',
|
|
18
|
+
ignore: 'hostname,pid'
|
|
19
|
+
}))
|
|
20
|
+
|
|
21
|
+
export async function deploy (argv) {
|
|
22
|
+
try {
|
|
23
|
+
const args = parseArgs(argv, {
|
|
24
|
+
alias: {
|
|
25
|
+
config: 'c',
|
|
26
|
+
type: 't',
|
|
27
|
+
label: 'l',
|
|
28
|
+
env: 'e',
|
|
29
|
+
secrets: 's'
|
|
30
|
+
},
|
|
31
|
+
string: [
|
|
32
|
+
'type',
|
|
33
|
+
'label',
|
|
34
|
+
'workspace-id',
|
|
35
|
+
'workspace-key',
|
|
36
|
+
'env',
|
|
37
|
+
'secrets',
|
|
38
|
+
'deploy-service-host'
|
|
39
|
+
],
|
|
40
|
+
default: {
|
|
41
|
+
'deploy-service-host': DEPLOY_SERVICE_HOST
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
let workspaceType = args.type
|
|
46
|
+
/* c8 ignore next 9 */
|
|
47
|
+
if (!workspaceType) {
|
|
48
|
+
const answer = await inquirer.prompt({
|
|
49
|
+
type: 'list',
|
|
50
|
+
name: 'workspaceType',
|
|
51
|
+
message: 'Select workspace type:',
|
|
52
|
+
choices: WORKSPACE_TYPES
|
|
53
|
+
})
|
|
54
|
+
workspaceType = answer.workspaceType
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!WORKSPACE_TYPES.includes(workspaceType)) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
`Invalid workspace type provided: "${workspaceType}". ` +
|
|
60
|
+
`Type must be one of: ${WORKSPACE_TYPES.join(', ')}.`
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let workspaceId = args['workspace-id']
|
|
65
|
+
/* c8 ignore next 8 */
|
|
66
|
+
if (!workspaceId) {
|
|
67
|
+
const answer = await inquirer.prompt({
|
|
68
|
+
type: 'input',
|
|
69
|
+
name: 'workspaceId',
|
|
70
|
+
message: 'Enter workspace id:'
|
|
71
|
+
})
|
|
72
|
+
workspaceId = answer.workspaceId
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!UUID_REGEX.test(workspaceId)) {
|
|
76
|
+
throw new Error('Invalid workspace id provided. Workspace id must be a valid uuid.')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let workspaceKey = args['workspace-key']
|
|
80
|
+
/* c8 ignore next 9 */
|
|
81
|
+
if (!workspaceKey) {
|
|
82
|
+
const answer = await inquirer.prompt({
|
|
83
|
+
type: 'password',
|
|
84
|
+
name: 'workspaceKey',
|
|
85
|
+
message: 'Enter workspace key:',
|
|
86
|
+
mask: '*'
|
|
87
|
+
})
|
|
88
|
+
workspaceKey = answer.workspaceKey
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let label = args.label
|
|
92
|
+
if (workspaceType === 'dynamic') {
|
|
93
|
+
/* c8 ignore next 9 */
|
|
94
|
+
if (!label) {
|
|
95
|
+
const answer = await inquirer.prompt({
|
|
96
|
+
type: 'input',
|
|
97
|
+
name: 'label',
|
|
98
|
+
message: 'Enter deploy label:',
|
|
99
|
+
default: 'cli:deploy-1'
|
|
100
|
+
})
|
|
101
|
+
label = answer.label
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const labelPrefix = label.split(':')[0]
|
|
105
|
+
const labelPrefixes = ['cli', 'github-pr']
|
|
106
|
+
if (!labelPrefix || !labelPrefixes.includes(labelPrefix)) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`Invalid deploy label provided: "${label}". ` +
|
|
109
|
+
`Label must be prefixed with one of: ${labelPrefixes.join(', ')}.`
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let pathToConfig = args.config
|
|
115
|
+
let pathToProject = process.cwd()
|
|
116
|
+
|
|
117
|
+
if (pathToConfig && isAbsolute(pathToConfig)) {
|
|
118
|
+
pathToProject = dirname(pathToConfig)
|
|
119
|
+
pathToConfig = relative(pathToProject, pathToConfig)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const pathToEnvFile = args.env || '.env'
|
|
123
|
+
const pathToSecretsFile = args.secrets || '.secrets.env'
|
|
124
|
+
const deployServiceHost = args['deploy-service-host']
|
|
125
|
+
|
|
126
|
+
await deployClient.deploy({
|
|
127
|
+
deployServiceHost,
|
|
128
|
+
workspaceId,
|
|
129
|
+
workspaceKey,
|
|
130
|
+
pathToProject,
|
|
131
|
+
pathToConfig,
|
|
132
|
+
pathToEnvFile,
|
|
133
|
+
pathToSecretsFile,
|
|
134
|
+
secrets: {},
|
|
135
|
+
variables: {},
|
|
136
|
+
label,
|
|
137
|
+
logger
|
|
138
|
+
})
|
|
139
|
+
} catch (err) {
|
|
140
|
+
logger.error(err.message)
|
|
141
|
+
process.exit(1)
|
|
142
|
+
}
|
|
143
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "platformatic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Platformatic CLI",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -35,9 +35,11 @@
|
|
|
35
35
|
"split2": "^4.1.0",
|
|
36
36
|
"standard": "^17.0.0",
|
|
37
37
|
"tap": "^16.3.4",
|
|
38
|
-
"undici": "^5.20.0"
|
|
38
|
+
"undici": "^5.20.0",
|
|
39
|
+
"fastify": "^4.13.0"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
42
|
+
"@platformatic/deploy-client": "^0.1.1",
|
|
41
43
|
"colorette": "^2.0.19",
|
|
42
44
|
"commist": "^3.2.0",
|
|
43
45
|
"desm": "^1.3.0",
|
|
@@ -45,12 +47,13 @@
|
|
|
45
47
|
"minimist": "^1.2.8",
|
|
46
48
|
"pino": "^8.11.0",
|
|
47
49
|
"pino-pretty": "^10.0.0",
|
|
48
|
-
"
|
|
49
|
-
"@platformatic/
|
|
50
|
-
"@platformatic/
|
|
51
|
-
"@platformatic/
|
|
52
|
-
"@platformatic/
|
|
53
|
-
"
|
|
50
|
+
"inquirer": "^9.1.4",
|
|
51
|
+
"@platformatic/authenticate": "0.21.0",
|
|
52
|
+
"@platformatic/db": "0.21.0",
|
|
53
|
+
"@platformatic/metaconfig": "0.21.0",
|
|
54
|
+
"@platformatic/service": "0.21.0",
|
|
55
|
+
"@platformatic/client-cli": "0.21.0",
|
|
56
|
+
"create-platformatic": "0.21.0"
|
|
54
57
|
},
|
|
55
58
|
"scripts": {
|
|
56
59
|
"test": "standard | snazzy && c8 --100 tap --no-coverage test/*.test.js",
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { test } from 'tap'
|
|
2
|
+
import { join } from 'desm'
|
|
3
|
+
import { execa } from 'execa'
|
|
4
|
+
|
|
5
|
+
import { cliPath, startDeployService, startMachine } from './helper.js'
|
|
6
|
+
|
|
7
|
+
test('should deploy to a static workspace to the cloud', async (t) => {
|
|
8
|
+
const workspaceType = 'static'
|
|
9
|
+
const workspaceId = 'b3d7f7e0-8c03-11e8-9eb6-529269fb1459'
|
|
10
|
+
const workspaceKey = 'b3d7f7e08c0311e89eb6529269fb1459'
|
|
11
|
+
const pathToConfig = join(import.meta.url, './fixtures/app-to-deploy/platformatic.db.json')
|
|
12
|
+
|
|
13
|
+
const machineHost = await startMachine(t)
|
|
14
|
+
const deployServiceHost = await startDeployService(t, {
|
|
15
|
+
createBundleCallback: (request, reply) => {
|
|
16
|
+
t.equal(request.headers['x-platformatic-workspace-id'], workspaceId)
|
|
17
|
+
t.equal(request.headers['x-platformatic-api-key'], workspaceKey)
|
|
18
|
+
t.match(request.body, {
|
|
19
|
+
bundle: {
|
|
20
|
+
appType: 'db',
|
|
21
|
+
configPath: 'platformatic.db.json'
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
t.ok(request.body.bundle.checksum)
|
|
25
|
+
},
|
|
26
|
+
createDeploymentCallback: (request, reply) => {
|
|
27
|
+
t.equal(request.headers['x-platformatic-workspace-id'], workspaceId)
|
|
28
|
+
t.equal(request.headers['x-platformatic-api-key'], workspaceKey)
|
|
29
|
+
t.same(
|
|
30
|
+
request.body,
|
|
31
|
+
{
|
|
32
|
+
variables: {
|
|
33
|
+
PLT_ENV_VARIABLE1: 'platformatic_variable1',
|
|
34
|
+
PLT_ENV_VARIABLE2: 'platformatic_variable2'
|
|
35
|
+
},
|
|
36
|
+
secrets: {
|
|
37
|
+
PLT_SECRET_1: 'platformatic_secret_1',
|
|
38
|
+
PLT_SECRET_2: 'platformatic_secret_2'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
reply.code(200).send({ entryPointUrl: machineHost })
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
await execa('node', [
|
|
47
|
+
cliPath, 'deploy',
|
|
48
|
+
'--type', workspaceType,
|
|
49
|
+
'--config', pathToConfig,
|
|
50
|
+
'--workspace-id', workspaceId,
|
|
51
|
+
'--workspace-key', workspaceKey,
|
|
52
|
+
'--deploy-service-host', deployServiceHost
|
|
53
|
+
])
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('should deploy to a dynamic workspace to the cloud', async (t) => {
|
|
57
|
+
const workspaceType = 'dynamic'
|
|
58
|
+
const workspaceId = 'b3d7f7e0-8c03-11e8-9eb6-529269fb1459'
|
|
59
|
+
const workspaceKey = 'b3d7f7e08c0311e89eb6529269fb1459'
|
|
60
|
+
const pathToConfig = join(import.meta.url, './fixtures/app-to-deploy/platformatic.db.json')
|
|
61
|
+
const label = 'cli:deploy-2'
|
|
62
|
+
|
|
63
|
+
const machineHost = await startMachine(t)
|
|
64
|
+
const deployServiceHost = await startDeployService(t, {
|
|
65
|
+
createBundleCallback: (request, reply) => {
|
|
66
|
+
t.equal(request.headers['x-platformatic-workspace-id'], workspaceId)
|
|
67
|
+
t.equal(request.headers['x-platformatic-api-key'], workspaceKey)
|
|
68
|
+
t.match(request.body, {
|
|
69
|
+
bundle: {
|
|
70
|
+
appType: 'db',
|
|
71
|
+
configPath: 'platformatic.db.json'
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
t.ok(request.body.bundle.checksum)
|
|
75
|
+
},
|
|
76
|
+
createDeploymentCallback: (request, reply) => {
|
|
77
|
+
t.equal(request.headers['x-platformatic-workspace-id'], workspaceId)
|
|
78
|
+
t.equal(request.headers['x-platformatic-api-key'], workspaceKey)
|
|
79
|
+
t.same(
|
|
80
|
+
request.body,
|
|
81
|
+
{
|
|
82
|
+
label,
|
|
83
|
+
variables: {
|
|
84
|
+
PLT_ENV_VARIABLE1: 'platformatic_variable1',
|
|
85
|
+
PLT_ENV_VARIABLE2: 'platformatic_variable2'
|
|
86
|
+
},
|
|
87
|
+
secrets: {
|
|
88
|
+
PLT_SECRET_1: 'platformatic_secret_1',
|
|
89
|
+
PLT_SECRET_2: 'platformatic_secret_2'
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
reply.code(200).send({ entryPointUrl: machineHost })
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
await execa('node', [
|
|
98
|
+
cliPath, 'deploy',
|
|
99
|
+
'--type', workspaceType,
|
|
100
|
+
'--label', label,
|
|
101
|
+
'--config', pathToConfig,
|
|
102
|
+
'--workspace-id', workspaceId,
|
|
103
|
+
'--workspace-key', workspaceKey,
|
|
104
|
+
'--deploy-service-host', deployServiceHost
|
|
105
|
+
])
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test('should fail if workspace id is not a uuid', async (t) => {
|
|
109
|
+
const workspaceType = 'static'
|
|
110
|
+
const workspaceId = 'not-a-uuid'
|
|
111
|
+
const workspaceKey = 'b3d7f7e08c0311e89eb6529269fb1459'
|
|
112
|
+
const pathToConfig = join(import.meta.url, './fixtures/app-to-deploy/platformatic.db.json')
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
await execa('node', [
|
|
116
|
+
cliPath, 'deploy',
|
|
117
|
+
'--type', workspaceType,
|
|
118
|
+
'--config', pathToConfig,
|
|
119
|
+
'--workspace-id', workspaceId,
|
|
120
|
+
'--workspace-key', workspaceKey,
|
|
121
|
+
'--deploy-service-host', 'http://localhost:5555'
|
|
122
|
+
])
|
|
123
|
+
t.fail('should have failed')
|
|
124
|
+
} catch (err) {
|
|
125
|
+
t.ok(err.message.includes('Invalid workspace id provided. Workspace id must be a valid uuid.'))
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('should fail if invalid workspace type provided', async (t) => {
|
|
130
|
+
const workspaceType = 'wrong'
|
|
131
|
+
const workspaceId = 'b3d7f7e0-8c03-11e8-9eb6-529269fb1459'
|
|
132
|
+
const workspaceKey = 'b3d7f7e08c0311e89eb6529269fb1459'
|
|
133
|
+
const pathToConfig = join(import.meta.url, './fixtures/app-to-deploy/platformatic.db.json')
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
await execa('node', [
|
|
137
|
+
cliPath, 'deploy',
|
|
138
|
+
'--type', workspaceType,
|
|
139
|
+
'--config', pathToConfig,
|
|
140
|
+
'--workspace-id', workspaceId,
|
|
141
|
+
'--workspace-key', workspaceKey,
|
|
142
|
+
'--deploy-service-host', 'http://localhost:5555'
|
|
143
|
+
])
|
|
144
|
+
t.fail('should have failed')
|
|
145
|
+
} catch (err) {
|
|
146
|
+
t.ok(err.message.includes('Invalid workspace type provided'))
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('should fail if deploy label does not start with a "cli:" prefix', async (t) => {
|
|
151
|
+
const workspaceType = 'dynamic'
|
|
152
|
+
const workspaceId = 'b3d7f7e0-8c03-11e8-9eb6-529269fb1459'
|
|
153
|
+
const workspaceKey = 'b3d7f7e08c0311e89eb6529269fb1459'
|
|
154
|
+
const pathToConfig = join(import.meta.url, './fixtures/app-to-deploy/platformatic.db.json')
|
|
155
|
+
const label = 'my label'
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
await execa('node', [
|
|
159
|
+
cliPath, 'deploy',
|
|
160
|
+
'--type', workspaceType,
|
|
161
|
+
'--label', label,
|
|
162
|
+
'--config', pathToConfig,
|
|
163
|
+
'--workspace-id', workspaceId,
|
|
164
|
+
'--workspace-key', workspaceKey,
|
|
165
|
+
'--deploy-service-host', 'http://localhost:5555'
|
|
166
|
+
])
|
|
167
|
+
t.fail('should have failed')
|
|
168
|
+
} catch (err) {
|
|
169
|
+
t.ok(err.message.includes(
|
|
170
|
+
`Invalid deploy label provided: "${label}". ` +
|
|
171
|
+
'Label must be prefixed with one of: cli, github-pr.'
|
|
172
|
+
))
|
|
173
|
+
}
|
|
174
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"server": {
|
|
3
|
+
"hostname": "127.0.0.1",
|
|
4
|
+
"port": 3042
|
|
5
|
+
},
|
|
6
|
+
"core": {
|
|
7
|
+
"connectionString": "sqlite://db.sqlite",
|
|
8
|
+
"graphql": true,
|
|
9
|
+
"ignore": {
|
|
10
|
+
"versions": true
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"migrations": {
|
|
14
|
+
"dir": "migrations",
|
|
15
|
+
"table": "versions"
|
|
16
|
+
}
|
|
17
|
+
}
|
package/test/helper.js
CHANGED
|
@@ -1,7 +1,61 @@
|
|
|
1
1
|
import { join } from 'desm'
|
|
2
|
+
import fastify from 'fastify'
|
|
2
3
|
|
|
3
4
|
const cliPath = join(import.meta.url, '..', 'cli.js')
|
|
4
5
|
|
|
6
|
+
async function startDeployService (t, options = {}) {
|
|
7
|
+
const deployService = fastify({ keepAliveTimeout: 1 })
|
|
8
|
+
|
|
9
|
+
deployService.post('/bundles', async (request, reply) => {
|
|
10
|
+
const createBundleCallback = options.createBundleCallback || (() => {})
|
|
11
|
+
await createBundleCallback(request, reply)
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
id: 'default-bundle-id',
|
|
15
|
+
token: 'default-upload-token',
|
|
16
|
+
isBundleUploaded: false
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
deployService.post('/deployments', async (request, reply) => {
|
|
21
|
+
const createDeploymentCallback = options.createDeploymentCallback || (() => {})
|
|
22
|
+
await createDeploymentCallback(request, reply)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
deployService.addContentTypeParser(
|
|
26
|
+
'application/x-tar',
|
|
27
|
+
{ bodyLimit: 1024 * 1024 * 1024 },
|
|
28
|
+
(request, payload, done) => done()
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
deployService.put('/upload', async (request, reply) => {
|
|
32
|
+
const uploadCallback = options.uploadCallback || (() => {})
|
|
33
|
+
await uploadCallback(request, reply)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
t.teardown(async () => {
|
|
37
|
+
await deployService.close()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return deployService.listen({ port: 3042 })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function startMachine (t, callback = () => {}) {
|
|
44
|
+
const machine = fastify({ keepAliveTimeout: 1 })
|
|
45
|
+
|
|
46
|
+
machine.get('/', async (request, reply) => {
|
|
47
|
+
await callback(request, reply)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
t.teardown(async () => {
|
|
51
|
+
await machine.close()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return machine.listen({ port: 0 })
|
|
55
|
+
}
|
|
56
|
+
|
|
5
57
|
export {
|
|
6
|
-
cliPath
|
|
58
|
+
cliPath,
|
|
59
|
+
startDeployService,
|
|
60
|
+
startMachine
|
|
7
61
|
}
|