@metaplay/metaplay-auth 1.4.2 → 1.6.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/.prettierignore +2 -0
- package/CHANGELOG.md +69 -28
- package/dist/index.cjs +292 -0
- package/dist/sshcrypto-OMBCGRSN.node +0 -0
- package/eslint.config.js +3 -0
- package/index.ts +763 -437
- package/package.json +22 -21
- package/prettier.config.js +3 -0
- package/src/auth.ts +121 -80
- package/src/buildCommand.ts +267 -0
- package/src/config.ts +12 -0
- package/src/deployment.ts +285 -52
- package/src/logging.ts +4 -4
- package/src/secret_store.ts +10 -7
- package/src/stackapi.ts +5 -381
- package/src/targetenvironment.ts +311 -0
- package/src/utils.ts +162 -31
- package/src/version.ts +1 -0
- package/dist/index.js +0 -644
- package/dist/index.js.map +0 -1
- package/dist/src/auth.js +0 -373
- package/dist/src/auth.js.map +0 -1
- package/dist/src/deployment.js +0 -250
- package/dist/src/deployment.js.map +0 -1
- package/dist/src/logging.js +0 -18
- package/dist/src/logging.js.map +0 -1
- package/dist/src/secret_store.js +0 -79
- package/dist/src/secret_store.js.map +0 -1
- package/dist/src/stackapi.js +0 -302
- package/dist/src/stackapi.js.map +0 -1
- package/dist/src/utils.js +0 -62
- package/dist/src/utils.js.map +0 -1
- package/dist/tests/utils.spec.js +0 -18
- package/dist/tests/utils.spec.js.map +0 -1
- package/tests/utils.spec.ts +0 -20
- package/vitest.config.ts +0 -7
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { exit } from 'process'
|
|
3
|
+
import { existsSync } from 'fs'
|
|
4
|
+
import { pathJoin, executeCommand, ExecuteCommandResult } from './utils.js'
|
|
5
|
+
import { logger } from './logging.js'
|
|
6
|
+
import path from 'path'
|
|
7
|
+
|
|
8
|
+
function resolveBuildEngine(engine?: string): string {
|
|
9
|
+
const validBuildEngines = ['buildx', 'buildkit']
|
|
10
|
+
|
|
11
|
+
// If not specified, auto-detect
|
|
12
|
+
if (!engine) {
|
|
13
|
+
// Bitbucket does not support buildx, so use buildkit, otherwise default to buildx
|
|
14
|
+
if (process.env.BITBUCKET_PIPELINE_UUID) {
|
|
15
|
+
return 'buildkit'
|
|
16
|
+
} else {
|
|
17
|
+
return 'buildx'
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// If specified from outside, check validity
|
|
22
|
+
if (!validBuildEngines.includes(engine)) {
|
|
23
|
+
throw new Error(`Invalid Docker build engine '${engine}', must be one of: ${validBuildEngines.join(', ')}`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return engine
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function registerBuildCommand(program: Command): void {
|
|
30
|
+
program
|
|
31
|
+
.command('build-image [extraArgs...]')
|
|
32
|
+
.description('build the game server docker image')
|
|
33
|
+
.option('-t, --image-tag <image-tag>', 'tag for the output image, eg, "myserver:d08747679d"', 'gameserver:<timestamp>')
|
|
34
|
+
.option('--sdk-root <directory>', 'relative path to the MetaplaySDK directory', 'MetaplaySDK')
|
|
35
|
+
.option(
|
|
36
|
+
'--project-root <directory>',
|
|
37
|
+
'relative path to the project root (where Backend/ directory is located)',
|
|
38
|
+
'.'
|
|
39
|
+
)
|
|
40
|
+
.option('--backend-dir <directory>', '[for legacy projects] name of the Backend/ directory', 'Backend')
|
|
41
|
+
.option(
|
|
42
|
+
'--shared-code-dir <directory>',
|
|
43
|
+
'path to the shared code directory of the project, relative to --project-root',
|
|
44
|
+
'Assets/SharedCode'
|
|
45
|
+
)
|
|
46
|
+
.option(
|
|
47
|
+
'--engine <engine>',
|
|
48
|
+
'docker build engine to use (buildx or buildkit), auto-detected if not specified',
|
|
49
|
+
'buildx'
|
|
50
|
+
)
|
|
51
|
+
.option('--architecture <architecture>', 'target platform architecture (amd64 or arm64)', 'amd64')
|
|
52
|
+
.option('--build-number <build-number>', 'number of this build (eg, 153)')
|
|
53
|
+
.option('--commit-id <commit-id>', 'commit id of this build (eg, d08747679d1e7fc9c1c685b396636da689ae476d)')
|
|
54
|
+
.action(
|
|
55
|
+
async (
|
|
56
|
+
extraArgs: string[],
|
|
57
|
+
options: {
|
|
58
|
+
imageTag: string
|
|
59
|
+
sdkRoot: string
|
|
60
|
+
projectRoot: string
|
|
61
|
+
sharedCodeDir: string
|
|
62
|
+
backendDir: string
|
|
63
|
+
engine: string
|
|
64
|
+
architecture: string
|
|
65
|
+
buildNumber?: string
|
|
66
|
+
commitId?: string
|
|
67
|
+
}
|
|
68
|
+
) => {
|
|
69
|
+
// Resolve imageTag to use: fill in <timestamp> with current unix time
|
|
70
|
+
let imageTag = options.imageTag
|
|
71
|
+
imageTag = imageTag.replace('<timestamp>', Math.floor(+new Date() / 1000).toString())
|
|
72
|
+
console.log(`Building docker image '${imageTag}'..`)
|
|
73
|
+
|
|
74
|
+
if (imageTag.endsWith(':latest')) {
|
|
75
|
+
console.error('Building docker image with "latest" tag is not allowed as it won\'t update the cloud environments reliably. Use commit id like git sha or timestamp instead.')
|
|
76
|
+
exit(1)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (extraArgs.length !== 0) {
|
|
80
|
+
console.log(`Extra args to docker: ${JSON.stringify(extraArgs)}`)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Check that sdkRoot is a valid directory
|
|
84
|
+
const sdkRootPath = options.sdkRoot.replaceAll('\\', '/')
|
|
85
|
+
if (path.isAbsolute(sdkRootPath)) {
|
|
86
|
+
console.error(`The --sdk-root (${sdkRootPath}) is an absolute path, please specify a relative path instead`)
|
|
87
|
+
exit(2)
|
|
88
|
+
}
|
|
89
|
+
if (sdkRootPath.startsWith('..')) {
|
|
90
|
+
console.error(
|
|
91
|
+
`The --sdk-root (${sdkRootPath}) path cannot point outside the current directory (i.e., cannot start with '..')`
|
|
92
|
+
)
|
|
93
|
+
exit(2)
|
|
94
|
+
}
|
|
95
|
+
if (!existsSync(sdkRootPath)) {
|
|
96
|
+
console.error(
|
|
97
|
+
`The Metaplay SDK directory '${sdkRootPath}' does not exist, specify correct directory with --sdk-root!`
|
|
98
|
+
)
|
|
99
|
+
exit(2)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check that we can find Dockerfile.server in sdkRoot
|
|
103
|
+
const dockerFilePath = pathJoin(sdkRootPath, 'Dockerfile.server')
|
|
104
|
+
if (!existsSync(dockerFilePath)) {
|
|
105
|
+
console.error(
|
|
106
|
+
`Cannot locate Dockerfile.server at ${dockerFilePath} -- check that the --sdk-root path points to the MetaplaySDK directory!`
|
|
107
|
+
)
|
|
108
|
+
exit(2)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Check projectRoot directory
|
|
112
|
+
const projectRootPath = options.projectRoot.replaceAll('\\', '/')
|
|
113
|
+
if (path.isAbsolute(sdkRootPath)) {
|
|
114
|
+
console.error(
|
|
115
|
+
`The --project-root (${projectRootPath}) is an absolute path, please specify a relative path instead`
|
|
116
|
+
)
|
|
117
|
+
exit(2)
|
|
118
|
+
}
|
|
119
|
+
if (projectRootPath.startsWith('..')) {
|
|
120
|
+
console.error(
|
|
121
|
+
`The --project-root (${projectRootPath}) path cannot point outside the current directory (i.e., cannot start with '..')`
|
|
122
|
+
)
|
|
123
|
+
exit(2)
|
|
124
|
+
}
|
|
125
|
+
if (!existsSync(projectRootPath)) {
|
|
126
|
+
console.error(
|
|
127
|
+
`The project root directory '${projectRootPath}' does not exist, specify correct directory with --project-root`
|
|
128
|
+
)
|
|
129
|
+
exit(2)
|
|
130
|
+
}
|
|
131
|
+
const projectBackendDir = pathJoin(projectRootPath, options.backendDir)
|
|
132
|
+
if (!existsSync(projectBackendDir)) {
|
|
133
|
+
console.error(
|
|
134
|
+
`Unable to find project backend in '${projectBackendDir}', check that --project-root is correct!`
|
|
135
|
+
)
|
|
136
|
+
exit(2)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Resolve sharedCodePath
|
|
140
|
+
const sharedCodePath = pathJoin(projectRootPath, options.sharedCodeDir)
|
|
141
|
+
if (!existsSync(sharedCodePath)) {
|
|
142
|
+
console.error(
|
|
143
|
+
`The shared code directory (${sharedCodePath}) does not exist, make sure the --shared-code-dir points to the directory where shared source code is located!`
|
|
144
|
+
)
|
|
145
|
+
exit(2)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Resolve target platform from architecture
|
|
149
|
+
const validArchitetures = ['amd64', 'arm64']
|
|
150
|
+
if (!validArchitetures.includes(options.architecture)) {
|
|
151
|
+
console.error(
|
|
152
|
+
`Invalid architecture '${options.architecture}' specified, must be one of ${JSON.stringify(validArchitetures)}`
|
|
153
|
+
)
|
|
154
|
+
exit(2)
|
|
155
|
+
}
|
|
156
|
+
const platform = `linux/${options.architecture}` // \note Only linux is supported
|
|
157
|
+
|
|
158
|
+
// Auto-detect git commit id from well-known environment variables, if not defined.
|
|
159
|
+
// Use well-known CI-defined environment variables to detect the commit id instead
|
|
160
|
+
// of checking git state as that gives a more reliable result.
|
|
161
|
+
let commitId = options.commitId
|
|
162
|
+
if (!commitId) {
|
|
163
|
+
commitId =
|
|
164
|
+
process.env.GIT_COMMIT ?? // Jenkins
|
|
165
|
+
process.env.GITHUB_SHA ?? // GitHub Actions
|
|
166
|
+
process.env.CI_COMMIT_SHA ?? // GitLab CI
|
|
167
|
+
process.env.CIRCLE_SHA1 ?? // Circle CI
|
|
168
|
+
process.env.TRAVIS_COMMIT ?? // Travis CI
|
|
169
|
+
process.env.BUILD_SOURCEVERSION ?? // Azure DevOps
|
|
170
|
+
process.env.BITBUCKET_COMMIT ?? // Bitbucket Pipelines
|
|
171
|
+
process.env.BUILD_VCS_NUMBER ?? // TeamCity
|
|
172
|
+
process.env.BUILDKITE_COMMIT ?? // Buildkite
|
|
173
|
+
process.env.DRONE_COMMIT_SHA ?? // Drone CI
|
|
174
|
+
process.env.SEMAPHORE_GIT_SHA // Semaphore CI
|
|
175
|
+
if (commitId) {
|
|
176
|
+
console.log(`Using auto-detected commit id: ${commitId}`)
|
|
177
|
+
} else {
|
|
178
|
+
console.warn('Failed to auto-detect commit id, please specify with "--commit-id <git-sha>"')
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Auto-detect build number from well-known environment variables, if not defined.
|
|
183
|
+
// Use well-known CI-defined environment variables to detect the build number.
|
|
184
|
+
let buildNumber = options.buildNumber
|
|
185
|
+
if (!buildNumber) {
|
|
186
|
+
buildNumber =
|
|
187
|
+
process.env.BUILD_NUMBER ?? // Jenkins
|
|
188
|
+
process.env.GITHUB_RUN_NUMBER ?? // GitHub Actions
|
|
189
|
+
process.env.CI_PIPELINE_IID ?? // GitLab CI
|
|
190
|
+
process.env.CIRCLE_BUILD_NUM ?? // Circle CI
|
|
191
|
+
process.env.TRAVIS_BUILD_NUMBER ?? // Travis CI
|
|
192
|
+
process.env.BUILD_BUILDNUMBER ?? // Azure Pipelines
|
|
193
|
+
process.env.BITBUCKET_BUILD_NUMBER ?? // Bitbucket Pipelines
|
|
194
|
+
process.env.BUILD_NUMBER ?? // TeamCity
|
|
195
|
+
process.env.BUILDKITE_BUILD_NUMBER ?? // Buildkite
|
|
196
|
+
process.env.DRONE_BUILD_NUMBER ?? // Drone CI
|
|
197
|
+
process.env.SEMAPHORE_BUILD_NUMBER // Semaphore CI
|
|
198
|
+
if (buildNumber) {
|
|
199
|
+
console.log(`Using auto-detected build number: ${buildNumber}`)
|
|
200
|
+
} else {
|
|
201
|
+
console.warn('Failed to auto-detect build number, please specify with "--build-number <build-number>"')
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Resolve build engine to use
|
|
206
|
+
let buildEngine = resolveBuildEngine(options.engine)
|
|
207
|
+
logger.debug(`Using docker build engine: ${buildEngine}`)
|
|
208
|
+
|
|
209
|
+
// Check that docker is installed and running
|
|
210
|
+
const checkDockerResult = await executeCommand('docker', ['ps'], { inheritStdio: false, env: {} })
|
|
211
|
+
if (checkDockerResult.exitCode !== 0) {
|
|
212
|
+
console.error('Failed to invoke docker, please make sure that docker is installed and running')
|
|
213
|
+
exit(1)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// If buildx engine specified, check that it works
|
|
217
|
+
if (buildEngine === 'buildx') {
|
|
218
|
+
const checkBuildxResult = await executeCommand('docker', ['buildx', 'version'], {
|
|
219
|
+
inheritStdio: false,
|
|
220
|
+
env: {},
|
|
221
|
+
})
|
|
222
|
+
if (checkBuildxResult.exitCode !== 0) {
|
|
223
|
+
console.warn('Docker buildx is not supported on this machine, falling back to --engine=buildkit')
|
|
224
|
+
buildEngine = 'buildkit'
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Resolve build engine args
|
|
229
|
+
const dockerEnv = buildEngine === 'buildkit' ? { DOCKER_BUILDKIT: '1' } : {}
|
|
230
|
+
const buildEngineArgs = buildEngine === 'buildx' ? ['buildx', 'build', '--load'] : ['build']
|
|
231
|
+
|
|
232
|
+
// Resolve final build invocation
|
|
233
|
+
const dockerArgs = buildEngineArgs
|
|
234
|
+
// .concat(['--progress=plain'])
|
|
235
|
+
.concat(['--pull']) // make sure we have latest versions of images where version isn't fully pinned
|
|
236
|
+
.concat(['-t', imageTag])
|
|
237
|
+
.concat(['-f', dockerFilePath])
|
|
238
|
+
.concat(['--platform', platform]) // target platform(s)
|
|
239
|
+
.concat(options.buildNumber ? ['--build-arg', `BUILD_NUMBER=${options.buildNumber}`] : [])
|
|
240
|
+
.concat(options.commitId ? ['--build-arg', `COMMIT_ID=${options.commitId}`] : [])
|
|
241
|
+
.concat(['--build-arg', `SDK_ROOT=${sdkRootPath}`])
|
|
242
|
+
.concat(['--build-arg', `PROJECT_ROOT=${projectRootPath}`])
|
|
243
|
+
.concat(['--build-arg', `SHARED_CODE_DIR=${options.sharedCodeDir.replaceAll('\\', '/')}`]) // pass relative-to-project-root dir
|
|
244
|
+
.concat(['--build-arg', `BACKEND_DIR=${options.backendDir.replaceAll('\\', '/')}`])
|
|
245
|
+
.concat(extraArgs) // pass extraArgs directly to docker
|
|
246
|
+
.concat(['.'])
|
|
247
|
+
console.log(`Execute: docker ${dockerArgs.join(' ')}`)
|
|
248
|
+
|
|
249
|
+
// Execute docker build
|
|
250
|
+
let buildResult: ExecuteCommandResult
|
|
251
|
+
try {
|
|
252
|
+
buildResult = await executeCommand('docker', dockerArgs, {
|
|
253
|
+
inheritStdio: true,
|
|
254
|
+
env: { ...process.env, ...dockerEnv, DOCKER_CLI_HINTS: 'false' },
|
|
255
|
+
})
|
|
256
|
+
if (buildResult.exitCode !== 0) {
|
|
257
|
+
console.error(`Docker build failed with exit code ${buildResult.exitCode}`)
|
|
258
|
+
exit(buildResult.exitCode)
|
|
259
|
+
}
|
|
260
|
+
console.log(`Successfully built docker image '${imageTag}'!`)
|
|
261
|
+
} catch (err) {
|
|
262
|
+
console.error(`Failed to invoke docker build: ${err instanceof Error ? err.message : String(err)}`)
|
|
263
|
+
exit(1)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base URL to the Metaplay developer portal. Override with global flag --portal-base-url.
|
|
3
|
+
*/
|
|
4
|
+
export let portalBaseUrl = 'https://portal.metaplay.dev'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Set the base URL to the Metaplay developer portal.
|
|
8
|
+
* @param url - The base URL to the Metaplay developer portal.
|
|
9
|
+
*/
|
|
10
|
+
export function setPortalBaseUrl(url: string): void {
|
|
11
|
+
portalBaseUrl = url
|
|
12
|
+
}
|