@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.
@@ -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
+ }