platformatic 1.49.1 → 1.51.8
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 +0 -6
- package/help/help.txt +0 -1
- package/package.json +12 -14
- package/help/gh.txt +0 -26
- package/help/login.txt +0 -10
- package/lib/deploy.js +0 -566
- package/lib/gh.js +0 -81
package/cli.js
CHANGED
|
@@ -7,15 +7,12 @@ import { run as runRuntime, compile } from '@platformatic/runtime/runtime.mjs'
|
|
|
7
7
|
import { startCommand } from '@platformatic/runtime'
|
|
8
8
|
import { runService } from '@platformatic/service/service.mjs'
|
|
9
9
|
import { runComposer } from '@platformatic/composer/composer.mjs'
|
|
10
|
-
import { login } from '@platformatic/authenticate/authenticate.js'
|
|
11
10
|
import { command as client } from '@platformatic/client-cli'
|
|
12
11
|
import { readFile } from 'fs/promises'
|
|
13
12
|
import { join } from 'desm'
|
|
14
13
|
import { isColorSupported } from 'colorette'
|
|
15
14
|
import helpMe from 'help-me'
|
|
16
15
|
import { upgrade } from './lib/upgrade.js'
|
|
17
|
-
import { gh } from './lib/gh.js'
|
|
18
|
-
import { deploy } from './lib/deploy.js'
|
|
19
16
|
import { logo } from './lib/ascii.js'
|
|
20
17
|
import {
|
|
21
18
|
runControl,
|
|
@@ -61,9 +58,6 @@ program.register('help db', async (args) => runDB(['help', ...args]))
|
|
|
61
58
|
program.register('help client', () => client([]))
|
|
62
59
|
program.register('help runtime', async (args) => runRuntime(['help', ...args]))
|
|
63
60
|
program.register('help service', async (args) => runService(['help', ...args]))
|
|
64
|
-
program.register({ command: 'login', strict: true }, login)
|
|
65
|
-
program.register('gh', gh)
|
|
66
|
-
program.register('deploy', deploy)
|
|
67
61
|
|
|
68
62
|
const args = minimist(process.argv.slice(2), {
|
|
69
63
|
boolean: ['help', 'version'],
|
package/help/help.txt
CHANGED
|
@@ -8,7 +8,6 @@ Welcome to Platformatic. Available commands are:
|
|
|
8
8
|
* `gh` - create a new gh action for Platformatic deployments.
|
|
9
9
|
* `runtime` - start Platformatic Runtime; type `platformatic runtime help` to know more.
|
|
10
10
|
* `start` - start a Platformatic application.
|
|
11
|
-
* `login` - generate a Platformatic login api key.
|
|
12
11
|
* `client` - generate a Platformatic client.
|
|
13
12
|
* `ps` - list all Platformatic runtime applications.
|
|
14
13
|
* `logs` - stream logs for a Platformatic runtime application.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "platformatic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.51.8",
|
|
4
4
|
"description": "Platformatic CLI",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"mercurius"
|
|
28
28
|
],
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"borp": "^0.
|
|
30
|
+
"borp": "^0.16.0",
|
|
31
31
|
"c8": "^10.0.0",
|
|
32
32
|
"fastify": "^4.26.2",
|
|
33
33
|
"license-checker": "^25.0.1",
|
|
@@ -51,18 +51,16 @@
|
|
|
51
51
|
"pino": "^8.19.0",
|
|
52
52
|
"pino-pretty": "^11.0.0",
|
|
53
53
|
"undici": "^6.9.0",
|
|
54
|
-
"@platformatic/
|
|
55
|
-
"@platformatic/
|
|
56
|
-
"@platformatic/composer": "1.
|
|
57
|
-
"@platformatic/
|
|
58
|
-
"@platformatic/
|
|
59
|
-
"@platformatic/db": "1.
|
|
60
|
-
"@platformatic/
|
|
61
|
-
"@platformatic/
|
|
62
|
-
"
|
|
63
|
-
"@platformatic/service": "1.
|
|
64
|
-
"@platformatic/utils": "1.49.1",
|
|
65
|
-
"create-platformatic": "1.49.1"
|
|
54
|
+
"@platformatic/client-cli": "1.51.8",
|
|
55
|
+
"@platformatic/config": "1.51.8",
|
|
56
|
+
"@platformatic/composer": "1.51.8",
|
|
57
|
+
"@platformatic/control": "1.51.8",
|
|
58
|
+
"@platformatic/frontend-template": "1.51.8",
|
|
59
|
+
"@platformatic/db": "1.51.8",
|
|
60
|
+
"@platformatic/runtime": "1.51.8",
|
|
61
|
+
"@platformatic/utils": "1.51.8",
|
|
62
|
+
"create-platformatic": "1.51.8",
|
|
63
|
+
"@platformatic/service": "1.51.8"
|
|
66
64
|
},
|
|
67
65
|
"scripts": {
|
|
68
66
|
"test": "pnpm run lint && borp --timeout 120000 --concurrency 1",
|
package/help/gh.txt
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
Creates a gh action to deploy platformatic services on workspaces.
|
|
2
|
-
|
|
3
|
-
``` bash
|
|
4
|
-
$ platformatic gh -t dynamic
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
Options:
|
|
8
|
-
|
|
9
|
-
* `-w --workspace ID` - The workspace ID where the service will be deployed.
|
|
10
|
-
* `-t, --type static/dynamic` - The type of the workspace. Defaults to static.
|
|
11
|
-
* `-c, --config FILE` - Specify a configuration file to use.
|
|
12
|
-
* `-b, --build` - Build the service before deploying (`npm run build`).
|
|
13
|
-
|
|
14
|
-
If not specified, the configuration will be loaded from any of the following, in the current directory.
|
|
15
|
-
|
|
16
|
-
* `platformatic.json`, or
|
|
17
|
-
* `platformatic.yml`, or
|
|
18
|
-
* `platformatic.tml`, or
|
|
19
|
-
* `platformatic.json`, or
|
|
20
|
-
* `platformatic.yml`, or
|
|
21
|
-
* `platformatic.tml`
|
|
22
|
-
|
|
23
|
-
You can find more details about the configuration format here:
|
|
24
|
-
* [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
|
|
25
|
-
* [Platformatic Service Configuration](https://docs.platformatic.dev/docs/service/configuration)
|
|
26
|
-
|
package/help/login.txt
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
Generate a Platformatic login api key.
|
|
2
|
-
|
|
3
|
-
``` bash
|
|
4
|
-
$ platformatic deploy
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
Options:
|
|
8
|
-
|
|
9
|
-
* `-c, --config FILE` - Specify a path to a global Platformatic config file. Defaults to `~/.platformatic/config.json`.
|
|
10
|
-
* `--browser` - Automatically open default browser. If process stdout is a TTY, the default is `true`. Otherwise, the default is `false`.
|
package/lib/deploy.js
DELETED
|
@@ -1,566 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { isAbsolute, dirname, relative, join } from 'path'
|
|
4
|
-
import { readFile } from 'fs/promises'
|
|
5
|
-
|
|
6
|
-
import { request } from 'undici'
|
|
7
|
-
import { bold, green } from 'colorette'
|
|
8
|
-
import pino from 'pino'
|
|
9
|
-
import pretty from 'pino-pretty'
|
|
10
|
-
import dotenv from 'dotenv'
|
|
11
|
-
import inquirer from 'inquirer'
|
|
12
|
-
import parseArgs from 'minimist'
|
|
13
|
-
import deployClient from '@platformatic/deploy-client'
|
|
14
|
-
import { getUserApiKey } from '@platformatic/authenticate'
|
|
15
|
-
import errors from './errors.js'
|
|
16
|
-
|
|
17
|
-
export const DEPLOY_SERVICE_HOST = 'https://deploy.platformatic.cloud'
|
|
18
|
-
|
|
19
|
-
const WORKSPACE_TYPES = ['static', 'dynamic']
|
|
20
|
-
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
21
|
-
|
|
22
|
-
const CREATE_NEW_WORKSPACE_CHOICE = Symbol('CREATE_NEW_WORKSPACE_CHOICE')
|
|
23
|
-
const CREATE_NEW_APPLICATION_CHOICE = Symbol('CREATE_NEW_APPLICATION_CHOICE')
|
|
24
|
-
|
|
25
|
-
async function askMissingWorkspaceDetails (
|
|
26
|
-
workspaceType,
|
|
27
|
-
workspaceId,
|
|
28
|
-
workspaceKey,
|
|
29
|
-
userApiKey
|
|
30
|
-
) {
|
|
31
|
-
/* c8 ignore next 9 */
|
|
32
|
-
if (!workspaceType) {
|
|
33
|
-
const answer = await inquirer.prompt({
|
|
34
|
-
type: 'list',
|
|
35
|
-
name: 'workspaceType',
|
|
36
|
-
message: 'Select workspace type:',
|
|
37
|
-
choices: WORKSPACE_TYPES
|
|
38
|
-
})
|
|
39
|
-
workspaceType = answer.workspaceType
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (!WORKSPACE_TYPES.includes(workspaceType)) {
|
|
43
|
-
throw new errors.InvalidWorkspaceTypeError(workspaceType, WORKSPACE_TYPES.join(', '))
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/* c8 ignore next 8 */
|
|
47
|
-
if (!workspaceId) {
|
|
48
|
-
const answer = await inquirer.prompt({
|
|
49
|
-
type: 'input',
|
|
50
|
-
name: 'workspaceId',
|
|
51
|
-
message: 'Enter workspace id:'
|
|
52
|
-
})
|
|
53
|
-
workspaceId = answer.workspaceId
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (!UUID_REGEX.test(workspaceId)) {
|
|
57
|
-
throw new errors.InvalidWorkspaceIdError()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/* c8 ignore next 9 */
|
|
61
|
-
if (!workspaceKey && !userApiKey) {
|
|
62
|
-
const answer = await inquirer.prompt({
|
|
63
|
-
type: 'password',
|
|
64
|
-
name: 'workspaceKey',
|
|
65
|
-
message: 'Enter workspace key:',
|
|
66
|
-
mask: '*'
|
|
67
|
-
})
|
|
68
|
-
workspaceKey = answer.workspaceKey
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
workspaceType,
|
|
73
|
-
workspaceId,
|
|
74
|
-
workspaceKey
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/* c8 ignore next 27 */
|
|
79
|
-
async function askToChooseApplication (applications) {
|
|
80
|
-
const applicationChoices = applications.map((application) => {
|
|
81
|
-
return {
|
|
82
|
-
name: application.name,
|
|
83
|
-
value: application
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
applicationChoices.push({
|
|
87
|
-
name: bold('Create new application'),
|
|
88
|
-
value: CREATE_NEW_APPLICATION_CHOICE
|
|
89
|
-
})
|
|
90
|
-
applicationChoices.push({
|
|
91
|
-
name: bold('Deploy to another application'),
|
|
92
|
-
value: null
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
const answer = await inquirer.prompt({
|
|
96
|
-
type: 'list',
|
|
97
|
-
name: 'application',
|
|
98
|
-
message: 'Select application to deploy:',
|
|
99
|
-
choices: applicationChoices,
|
|
100
|
-
loop: false
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
const chosenApplication = answer.application
|
|
104
|
-
return chosenApplication
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/* c8 ignore next 27 */
|
|
108
|
-
async function askToChooseWorkspace (workspaces) {
|
|
109
|
-
const workspaceChoices = workspaces.map((workspace) => {
|
|
110
|
-
return {
|
|
111
|
-
name: `${workspace.name} (${workspace.type})`,
|
|
112
|
-
value: workspace
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
workspaceChoices.push({
|
|
116
|
-
name: bold('Create new workspace'),
|
|
117
|
-
value: CREATE_NEW_WORKSPACE_CHOICE
|
|
118
|
-
})
|
|
119
|
-
workspaceChoices.push({
|
|
120
|
-
name: bold('Deploy to another workspace'),
|
|
121
|
-
value: null
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
const answer = await inquirer.prompt({
|
|
125
|
-
type: 'list',
|
|
126
|
-
name: 'workspace',
|
|
127
|
-
message: 'Select workspace to deploy:',
|
|
128
|
-
choices: workspaceChoices,
|
|
129
|
-
loop: false
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
const chosenWorkspace = answer.workspace
|
|
133
|
-
return chosenWorkspace
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/* c8 ignore next 14 */
|
|
137
|
-
async function askToChooseOrg (orgs) {
|
|
138
|
-
const orgsChoices = orgs.map((org) => {
|
|
139
|
-
return { name: org.name, value: org.id }
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
const answer = await inquirer.prompt({
|
|
143
|
-
type: 'list',
|
|
144
|
-
name: 'orgId',
|
|
145
|
-
message: 'Select organisation to publish to:',
|
|
146
|
-
choices: orgsChoices
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
return answer.orgId
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/* c8 ignore next 21 */
|
|
153
|
-
async function askNewWorkspaceDetails () {
|
|
154
|
-
const answer = await inquirer.prompt([
|
|
155
|
-
{
|
|
156
|
-
type: 'input',
|
|
157
|
-
name: 'workspaceName',
|
|
158
|
-
message: 'Enter workspace name:'
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
type: 'list',
|
|
162
|
-
name: 'workspaceType',
|
|
163
|
-
message: 'Select workspace type:',
|
|
164
|
-
choices: WORKSPACE_TYPES
|
|
165
|
-
}
|
|
166
|
-
])
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
workspaceName: answer.workspaceName,
|
|
170
|
-
workspaceType: answer.workspaceType
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/* c8 ignore next 12 */
|
|
175
|
-
async function askNewApplicationDetails () {
|
|
176
|
-
const answer = await inquirer.prompt({
|
|
177
|
-
type: 'input',
|
|
178
|
-
name: 'applicationName',
|
|
179
|
-
message: 'Enter application name:'
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
applicationName: answer.applicationName
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/* c8 ignore next 19 */
|
|
188
|
-
async function askToChooseDeployLabel (labels) {
|
|
189
|
-
const entryPointChoices = labels.map((label) => {
|
|
190
|
-
return { name: label, value: label }
|
|
191
|
-
})
|
|
192
|
-
entryPointChoices.push({
|
|
193
|
-
name: 'Deploy to another label',
|
|
194
|
-
value: null
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
const answer = await inquirer.prompt({
|
|
198
|
-
type: 'list',
|
|
199
|
-
name: 'entryPoint',
|
|
200
|
-
message: 'Select entry point to deploy:',
|
|
201
|
-
choices: entryPointChoices
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
return answer.entryPoint
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/* c8 ignore next 10 */
|
|
208
|
-
async function askToEnterDeployLabel () {
|
|
209
|
-
const answer = await inquirer.prompt({
|
|
210
|
-
type: 'input',
|
|
211
|
-
name: 'label',
|
|
212
|
-
message: 'Enter deploy label:',
|
|
213
|
-
default: 'cli:deploy-1'
|
|
214
|
-
})
|
|
215
|
-
return answer.label
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
async function readWorkspaceDetails (workspaceKeysPath) {
|
|
219
|
-
/* c8 ignore next 3 */
|
|
220
|
-
if (!isAbsolute(workspaceKeysPath)) {
|
|
221
|
-
workspaceKeysPath = join(process.cwd(), workspaceKeysPath)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const workspaceFile = await readFile(workspaceKeysPath, 'utf8')
|
|
225
|
-
const workspaceEnvVars = dotenv.parse(workspaceFile)
|
|
226
|
-
|
|
227
|
-
if (
|
|
228
|
-
workspaceEnvVars.PLATFORMATIC_DYNAMIC_WORKSPACE_ID &&
|
|
229
|
-
workspaceEnvVars.PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY
|
|
230
|
-
) {
|
|
231
|
-
return {
|
|
232
|
-
workspaceType: 'dynamic',
|
|
233
|
-
workspaceId: workspaceEnvVars.PLATFORMATIC_DYNAMIC_WORKSPACE_ID,
|
|
234
|
-
workspaceKey: workspaceEnvVars.PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (
|
|
239
|
-
workspaceEnvVars.PLATFORMATIC_STATIC_WORKSPACE_ID &&
|
|
240
|
-
workspaceEnvVars.PLATFORMATIC_STATIC_WORKSPACE_API_KEY
|
|
241
|
-
) {
|
|
242
|
-
return {
|
|
243
|
-
workspaceType: 'static',
|
|
244
|
-
workspaceId: workspaceEnvVars.PLATFORMATIC_STATIC_WORKSPACE_ID,
|
|
245
|
-
workspaceKey: workspaceEnvVars.PLATFORMATIC_STATIC_WORKSPACE_API_KEY
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
throw new errors.CouldNotFindWorkspaceKeysError()
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/* c8 ignore next 18 */
|
|
253
|
-
async function getUserApplications (deployServiceHost, userApiKey) {
|
|
254
|
-
const { statusCode, body } = await request(`${deployServiceHost}/applications`, {
|
|
255
|
-
headers: {
|
|
256
|
-
'Content-Type': 'application/json',
|
|
257
|
-
'x-platformatic-user-api-key': userApiKey
|
|
258
|
-
}
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
if (statusCode !== 200) {
|
|
262
|
-
const error = await body.text()
|
|
263
|
-
console.error(error)
|
|
264
|
-
throw new errors.CouldNotFetchUserApplicationsError()
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const { applications } = await body.json()
|
|
268
|
-
return applications
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/* c8 ignore next 18 */
|
|
272
|
-
async function getUserOrgs (deployServiceHost, userApiKey) {
|
|
273
|
-
const url = deployServiceHost + '/organisations'
|
|
274
|
-
const { statusCode, body } = await request(url, {
|
|
275
|
-
method: 'GET',
|
|
276
|
-
headers: {
|
|
277
|
-
'content-type': 'application/json',
|
|
278
|
-
'x-platformatic-user-api-key': userApiKey
|
|
279
|
-
}
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
if (statusCode !== 200) {
|
|
283
|
-
throw new errors.CouldNotFetchUserOrgsError()
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const { orgs } = await body.json()
|
|
287
|
-
return orgs
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/* c8 ignore next 18 */
|
|
291
|
-
async function getWorkspaceLabels (deployServiceHost, workspaceId, userApiKey) {
|
|
292
|
-
const { statusCode, body } = await request(`${deployServiceHost}/entrypoints`, {
|
|
293
|
-
headers: {
|
|
294
|
-
'Content-Type': 'application/json',
|
|
295
|
-
'x-platformatic-workspace-id': workspaceId,
|
|
296
|
-
'x-platformatic-user-api-key': userApiKey
|
|
297
|
-
}
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
if (statusCode !== 200) {
|
|
301
|
-
const error = await body.text()
|
|
302
|
-
console.error(error)
|
|
303
|
-
throw new errors.CouldNotFetchDeployLabelsError()
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const { entryPoints } = await body.json()
|
|
307
|
-
return entryPoints.map((entryPoint) => entryPoint.label)
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/* c8 ignore next 30 */
|
|
311
|
-
async function createWorkspace (
|
|
312
|
-
deployServiceHost,
|
|
313
|
-
userApiKey,
|
|
314
|
-
appId,
|
|
315
|
-
workspaceName,
|
|
316
|
-
workspaceType
|
|
317
|
-
) {
|
|
318
|
-
const { statusCode, body } = await request(`${deployServiceHost}/workspaces`, {
|
|
319
|
-
method: 'POST',
|
|
320
|
-
headers: {
|
|
321
|
-
'Content-Type': 'application/json',
|
|
322
|
-
'x-platformatic-user-api-key': userApiKey
|
|
323
|
-
},
|
|
324
|
-
body: JSON.stringify({
|
|
325
|
-
appId,
|
|
326
|
-
name: workspaceName,
|
|
327
|
-
type: workspaceType
|
|
328
|
-
})
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
if (statusCode !== 200) {
|
|
332
|
-
const error = await body.text()
|
|
333
|
-
console.error(error)
|
|
334
|
-
throw new errors.CouldNotCreateWorkspaceError()
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const { id: workspaceId } = await body.json()
|
|
338
|
-
return workspaceId
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/* c8 ignore next 25 */
|
|
342
|
-
async function createApplication (
|
|
343
|
-
deployServiceHost,
|
|
344
|
-
userApiKey,
|
|
345
|
-
orgId,
|
|
346
|
-
applicationName
|
|
347
|
-
) {
|
|
348
|
-
const { statusCode, body } = await request(`${deployServiceHost}/applications`, {
|
|
349
|
-
method: 'POST',
|
|
350
|
-
headers: {
|
|
351
|
-
'Content-Type': 'application/json',
|
|
352
|
-
'x-platformatic-user-api-key': userApiKey
|
|
353
|
-
},
|
|
354
|
-
body: JSON.stringify({ orgId, name: applicationName })
|
|
355
|
-
})
|
|
356
|
-
|
|
357
|
-
if (statusCode !== 200) {
|
|
358
|
-
const error = await body.text()
|
|
359
|
-
console.error(error)
|
|
360
|
-
throw new errors.CouldNotCreateApplicationError()
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const { id: applicationId } = await body.json()
|
|
364
|
-
return applicationId
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/* c8 ignore next 16 */
|
|
368
|
-
async function getUserOrgDetails (deployServiceHost, userApiKey) {
|
|
369
|
-
const userOrgs = await getUserOrgs(deployServiceHost, userApiKey)
|
|
370
|
-
if (userOrgs.length === 0) {
|
|
371
|
-
throw new errors.NoUserOrgsError()
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
let orgId = null
|
|
375
|
-
if (userOrgs.length === 1) {
|
|
376
|
-
orgId = userOrgs[0].id
|
|
377
|
-
} else {
|
|
378
|
-
orgId = await askToChooseOrg(userOrgs)
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return { id: orgId }
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/* c8 ignore next 26 */
|
|
385
|
-
async function getUserApplicationDetails (deployServiceHost, userApiKey) {
|
|
386
|
-
const applications = await getUserApplications(deployServiceHost, userApiKey)
|
|
387
|
-
if (applications.length === 0) return null
|
|
388
|
-
|
|
389
|
-
const application = await askToChooseApplication(applications)
|
|
390
|
-
if (application === null) return null
|
|
391
|
-
|
|
392
|
-
if (application === CREATE_NEW_APPLICATION_CHOICE) {
|
|
393
|
-
const { id: orgId } = await getUserOrgDetails(deployServiceHost, userApiKey)
|
|
394
|
-
const { applicationName } = await askNewApplicationDetails()
|
|
395
|
-
const applicationId = await createApplication(
|
|
396
|
-
deployServiceHost,
|
|
397
|
-
userApiKey,
|
|
398
|
-
orgId,
|
|
399
|
-
applicationName
|
|
400
|
-
)
|
|
401
|
-
return { id: applicationId, name: applicationName, workspaces: [] }
|
|
402
|
-
}
|
|
403
|
-
return {
|
|
404
|
-
id: application.id,
|
|
405
|
-
name: application.name,
|
|
406
|
-
workspaces: application.workspaces
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/* c8 ignore next 24 */
|
|
411
|
-
async function getUserWorkspaceDetails (deployServiceHost, userApiKey) {
|
|
412
|
-
const application = await getUserApplicationDetails(deployServiceHost, userApiKey)
|
|
413
|
-
if (application === null) return null
|
|
414
|
-
|
|
415
|
-
const workspaceDetails = await askToChooseWorkspace(application.workspaces)
|
|
416
|
-
if (workspaceDetails === null) return null
|
|
417
|
-
|
|
418
|
-
if (workspaceDetails === CREATE_NEW_WORKSPACE_CHOICE) {
|
|
419
|
-
const { workspaceName, workspaceType } = await askNewWorkspaceDetails()
|
|
420
|
-
const workspaceId = await createWorkspace(
|
|
421
|
-
deployServiceHost,
|
|
422
|
-
userApiKey,
|
|
423
|
-
application.id,
|
|
424
|
-
workspaceName,
|
|
425
|
-
workspaceType
|
|
426
|
-
)
|
|
427
|
-
return { workspaceId, workspaceType }
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return {
|
|
431
|
-
workspaceId: workspaceDetails.id,
|
|
432
|
-
workspaceType: workspaceDetails.type
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
export async function deploy (argv) {
|
|
437
|
-
const logger = pino(pretty({
|
|
438
|
-
translateTime: 'SYS:HH:MM:ss',
|
|
439
|
-
ignore: 'hostname,pid'
|
|
440
|
-
}))
|
|
441
|
-
|
|
442
|
-
logger.info('This application will be deployed to ' + bold(green('Platformatic Cloud')) + '. To change the target use the --deploy-service-host flag')
|
|
443
|
-
|
|
444
|
-
try {
|
|
445
|
-
const args = parseArgs(argv, {
|
|
446
|
-
alias: {
|
|
447
|
-
config: 'c',
|
|
448
|
-
keys: 'k',
|
|
449
|
-
type: 't',
|
|
450
|
-
label: 'l',
|
|
451
|
-
env: 'e',
|
|
452
|
-
secrets: 's',
|
|
453
|
-
compileTypescript: ['compile', 'C']
|
|
454
|
-
},
|
|
455
|
-
boolean: ['compileTypescript'],
|
|
456
|
-
string: [
|
|
457
|
-
'type',
|
|
458
|
-
'label',
|
|
459
|
-
'workspace-id',
|
|
460
|
-
'workspace-key',
|
|
461
|
-
'env',
|
|
462
|
-
'secrets',
|
|
463
|
-
'deploy-service-host'
|
|
464
|
-
],
|
|
465
|
-
default: {
|
|
466
|
-
'deploy-service-host': DEPLOY_SERVICE_HOST,
|
|
467
|
-
compileTypescript: true
|
|
468
|
-
}
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
const deployServiceHost = args['deploy-service-host']
|
|
472
|
-
|
|
473
|
-
let workspaceId = args['workspace-id']
|
|
474
|
-
let workspaceType = args.type
|
|
475
|
-
|
|
476
|
-
let workspaceKey = args['workspace-key']
|
|
477
|
-
let userApiKey = null
|
|
478
|
-
|
|
479
|
-
if (!workspaceId) {
|
|
480
|
-
if (args.keys) {
|
|
481
|
-
const workspaceDetails = await readWorkspaceDetails(args.keys)
|
|
482
|
-
workspaceId = workspaceDetails.workspaceId
|
|
483
|
-
workspaceType = workspaceDetails.workspaceType
|
|
484
|
-
workspaceKey = workspaceDetails.workspaceKey
|
|
485
|
-
/* c8 ignore next 10 */
|
|
486
|
-
} else {
|
|
487
|
-
userApiKey = await getUserApiKey().catch(() => {})
|
|
488
|
-
if (userApiKey) {
|
|
489
|
-
const workspaceDetails = await getUserWorkspaceDetails(deployServiceHost, userApiKey)
|
|
490
|
-
if (workspaceDetails) {
|
|
491
|
-
workspaceId = workspaceDetails.workspaceId
|
|
492
|
-
workspaceType = workspaceDetails.workspaceType
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
const workspaceDetails = await askMissingWorkspaceDetails(
|
|
499
|
-
workspaceType,
|
|
500
|
-
workspaceId,
|
|
501
|
-
workspaceKey,
|
|
502
|
-
userApiKey
|
|
503
|
-
)
|
|
504
|
-
workspaceId = workspaceDetails.workspaceId
|
|
505
|
-
workspaceType = workspaceDetails.workspaceType
|
|
506
|
-
workspaceKey = workspaceDetails.workspaceKey
|
|
507
|
-
|
|
508
|
-
let label = args.label
|
|
509
|
-
|
|
510
|
-
if (workspaceType === 'dynamic') {
|
|
511
|
-
/* c8 ignore next 17 */
|
|
512
|
-
if (!label) {
|
|
513
|
-
userApiKey = userApiKey || await getUserApiKey().catch(() => {})
|
|
514
|
-
|
|
515
|
-
if (userApiKey) {
|
|
516
|
-
const workspaceLabels = await getWorkspaceLabels(
|
|
517
|
-
deployServiceHost,
|
|
518
|
-
workspaceId,
|
|
519
|
-
userApiKey
|
|
520
|
-
)
|
|
521
|
-
if (workspaceLabels.length !== 0) {
|
|
522
|
-
label = await askToChooseDeployLabel(workspaceLabels)
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
if (!label) {
|
|
526
|
-
label = await askToEnterDeployLabel()
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
const labelPrefix = label.split(':')[0]
|
|
531
|
-
const labelPrefixes = ['cli', 'github-pr']
|
|
532
|
-
if (!labelPrefix || !labelPrefixes.includes(labelPrefix)) {
|
|
533
|
-
label = `cli:${label}`
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
let pathToConfig = args.config
|
|
538
|
-
let pathToProject = process.cwd()
|
|
539
|
-
|
|
540
|
-
if (pathToConfig && isAbsolute(pathToConfig)) {
|
|
541
|
-
pathToProject = dirname(pathToConfig)
|
|
542
|
-
pathToConfig = relative(pathToProject, pathToConfig)
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
const pathToEnvFile = args.env || '.env'
|
|
546
|
-
const pathToSecretsFile = args.secrets || '.secrets.env'
|
|
547
|
-
|
|
548
|
-
await deployClient.deploy({
|
|
549
|
-
deployServiceHost,
|
|
550
|
-
workspaceId,
|
|
551
|
-
workspaceKey,
|
|
552
|
-
userApiKey,
|
|
553
|
-
pathToProject,
|
|
554
|
-
pathToConfig,
|
|
555
|
-
pathToEnvFile,
|
|
556
|
-
pathToSecretsFile,
|
|
557
|
-
secrets: {},
|
|
558
|
-
variables: {},
|
|
559
|
-
label,
|
|
560
|
-
logger
|
|
561
|
-
})
|
|
562
|
-
} catch (err) {
|
|
563
|
-
logger.error(err.message)
|
|
564
|
-
process.exit(1)
|
|
565
|
-
}
|
|
566
|
-
}
|
package/lib/gh.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createStaticWorkspaceGHAction,
|
|
3
|
-
createDynamicWorkspaceGHAction
|
|
4
|
-
} from 'create-platformatic'
|
|
5
|
-
|
|
6
|
-
import parseArgs from 'minimist'
|
|
7
|
-
import { access } from 'fs/promises'
|
|
8
|
-
import pino from 'pino'
|
|
9
|
-
import pretty from 'pino-pretty'
|
|
10
|
-
import ConfigManager from '@platformatic/config'
|
|
11
|
-
|
|
12
|
-
export const createGHAction = async (logger, env, config, buildTS, type, projectDir = process.cwd()) => {
|
|
13
|
-
if (type === 'static') {
|
|
14
|
-
await createStaticWorkspaceGHAction(logger, env, config, projectDir, buildTS)
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
await createDynamicWorkspaceGHAction(logger, env, config, projectDir, buildTS)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const logger = pino(pretty({
|
|
21
|
-
translateTime: 'SYS:HH:MM:ss',
|
|
22
|
-
ignore: 'hostname,pid'
|
|
23
|
-
}))
|
|
24
|
-
|
|
25
|
-
const configFileNames = ConfigManager.listConfigFiles()
|
|
26
|
-
|
|
27
|
-
async function isFileAccessible (filename) {
|
|
28
|
-
try {
|
|
29
|
-
await access(filename)
|
|
30
|
-
return true
|
|
31
|
-
} catch (err) {
|
|
32
|
-
return false
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const gh = async (argv) => {
|
|
37
|
-
const args = parseArgs(argv, {
|
|
38
|
-
default: {
|
|
39
|
-
type: 'static',
|
|
40
|
-
build: false
|
|
41
|
-
},
|
|
42
|
-
alias: {
|
|
43
|
-
config: 'c',
|
|
44
|
-
type: 't',
|
|
45
|
-
help: 'h',
|
|
46
|
-
build: 'b'
|
|
47
|
-
},
|
|
48
|
-
boolean: ['build']
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
if (!['static', 'dynamic'].includes(args.type)) {
|
|
52
|
-
logger.error(`Invalid type: [${args.type}]. Type must be either static or dynamic`)
|
|
53
|
-
process.exit(1)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
let configFilename = args.config
|
|
57
|
-
if (!configFilename) {
|
|
58
|
-
const configFilesAccessibility = await Promise.all(configFileNames.map((fileName) => isFileAccessible(fileName)))
|
|
59
|
-
configFilename = configFileNames.find((value, index) => configFilesAccessibility[index])
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!configFilename) {
|
|
63
|
-
logger.error('No config file found')
|
|
64
|
-
process.exit(1)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (await isFileAccessible('.env')) {
|
|
68
|
-
// We cannot add this automatically, because there might be credentials .env file
|
|
69
|
-
logger.info('Found .env file. If you need these variables in your GitHub Action, please add them to env: in "Deploy Project" step')
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const env = {
|
|
73
|
-
plt_custom_variable: 'change-me',
|
|
74
|
-
custom_variable1: 'change-me'
|
|
75
|
-
}
|
|
76
|
-
await createGHAction(logger, env, configFilename, args.build, args.type)
|
|
77
|
-
|
|
78
|
-
const workspaceName = args.type === 'static' ? 'PLATFORMATIC_STATIC_WORKSPACE_ID ' : 'PLATFORMATIC_DYNAMIC_WORKSPACE_ID'
|
|
79
|
-
const secretName = args.type === 'static' ? 'PLATFORMATIC_STATIC_WORKSPACE_API_KEY' : 'PLATFORMATIC_DYNAMIC_WORKSPACE_API_KEY'
|
|
80
|
-
logger.info(`Github action successfully created please add ${workspaceName} and ${secretName} as repository secrets.`)
|
|
81
|
-
}
|