@makefully/adaptfully 4.0.0 → 4.2.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/CHANGELOG.md +20 -0
- package/README.md +29 -10
- package/docs/credentials/README.md +50 -0
- package/docs/credentials/android.md +124 -0
- package/docs/credentials/ios.md +182 -0
- package/docs/credentials/steam.md +99 -0
- package/lib/node/android-keystore.js +243 -0
- package/lib/node/apple-signing.js +392 -0
- package/lib/node/choreCrypto.js +197 -0
- package/lib/node/config.js +45 -4
- package/lib/node/deploy.js +239 -42
- package/lib/node/index.js +20 -0
- package/lib/node/pipeline.js +51 -14
- package/lib/node/publish-credentials.js +47 -1
- package/lib/node/wrapfullyDefaultPublicKey.js +17 -0
- package/package.json +2 -1
package/lib/node/pipeline.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { loadProjectConfig, resolveServerUrl } from './config.js';
|
|
2
|
+
import { loadProjectConfig, resolveServerUrl, resolveAccessToken, resolveEncryptFlag } from './config.js';
|
|
3
3
|
import { send } from './deploy.js';
|
|
4
4
|
import { resolveBuildArtifactDir } from './artifacts.js';
|
|
5
5
|
import { prebuildPlatform } from './prebuild.js';
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
import { steamPublishFromCli } from './steam-publish.js';
|
|
13
13
|
import { googlePublishFromCli } from './google-publish.js';
|
|
14
14
|
import { applePublishFromCli } from './apple-publish.js';
|
|
15
|
+
import { androidKeystoreFromCli } from './android-keystore.js';
|
|
16
|
+
import { appleSigningFromCli } from './apple-signing.js';
|
|
15
17
|
|
|
16
18
|
/** @typedef {'prebuild' | 'build' | 'deploy' | 'release'} AdaptfullyStage */
|
|
17
19
|
|
|
@@ -20,6 +22,8 @@ const PUBLISH_COMMANDS = {
|
|
|
20
22
|
'steam-publish': steamPublishFromCli,
|
|
21
23
|
'google-publish': googlePublishFromCli,
|
|
22
24
|
'apple-publish': applePublishFromCli,
|
|
25
|
+
'android-keystore': androidKeystoreFromCli,
|
|
26
|
+
'apple-signing': appleSigningFromCli,
|
|
23
27
|
};
|
|
24
28
|
|
|
25
29
|
/**
|
|
@@ -40,7 +44,7 @@ export function resolveWrapfullyRoute(buildSpec) {
|
|
|
40
44
|
/**
|
|
41
45
|
* @param {AdaptfullyStage} stage
|
|
42
46
|
* @param {string} platformKey
|
|
43
|
-
* @param {{ pkg: object, deployFolder: string, server?: string, mode?: string, deployment?: string, artifactPath?: string, log?: (message: string) => void, outputRoot?: string }} options
|
|
47
|
+
* @param {{ pkg: object, deployFolder: string, server?: string, mode?: string, deployment?: string, artifactPath?: string, log?: (message: string) => void, outputRoot?: string, accessToken?: string, encrypt?: boolean, encryptPublicKey?: string, wrapfullyConfig?: object }} options
|
|
44
48
|
*/
|
|
45
49
|
export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
46
50
|
if (!VALID_STAGES.has(stage)) {
|
|
@@ -99,7 +103,7 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
99
103
|
|
|
100
104
|
log(
|
|
101
105
|
`adaptfully: ${stage} ${platformKey} → ${buildSpec.family} `
|
|
102
|
-
+ `(${buildSpec.targets.join(', ')}) via
|
|
106
|
+
+ `(${buildSpec.targets.join(', ')}) via Yap /yap/wrapfully (route ${wrapfullyRoute}/release)`,
|
|
103
107
|
);
|
|
104
108
|
|
|
105
109
|
log(
|
|
@@ -121,6 +125,10 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
121
125
|
log,
|
|
122
126
|
platformKey,
|
|
123
127
|
deploymentDirs: deploymentDirs.map((dir) => path.resolve(dir)),
|
|
128
|
+
accessToken: options.accessToken,
|
|
129
|
+
encrypt: options.encrypt,
|
|
130
|
+
encryptPublicKey: options.encryptPublicKey,
|
|
131
|
+
wrapfullyConfig: options.wrapfullyConfig,
|
|
124
132
|
},
|
|
125
133
|
);
|
|
126
134
|
|
|
@@ -138,7 +146,7 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
138
146
|
log(
|
|
139
147
|
`adaptfully: ${stage} ${platformKey} → `
|
|
140
148
|
+ `${deploymentKey === 'zip' ? 'artifact zip' : `deployment "${deploymentKey}"`} `
|
|
141
|
-
+ `via
|
|
149
|
+
+ `via Yap /yap/wrapfully (route ${wrapfullyRoute}/${wrapStage}, ${buildSpec.family})`,
|
|
142
150
|
);
|
|
143
151
|
|
|
144
152
|
if (deploymentDirs.length) {
|
|
@@ -165,6 +173,10 @@ export async function runAdaptfullyStage(stage, platformKey, options) {
|
|
|
165
173
|
platformKey,
|
|
166
174
|
deploymentKey: wrapStage === 'deploy' ? deploymentKey : undefined,
|
|
167
175
|
artifactPath,
|
|
176
|
+
accessToken: options.accessToken,
|
|
177
|
+
encrypt: options.encrypt,
|
|
178
|
+
encryptPublicKey: options.encryptPublicKey,
|
|
179
|
+
wrapfullyConfig: options.wrapfullyConfig,
|
|
168
180
|
},
|
|
169
181
|
);
|
|
170
182
|
|
|
@@ -190,7 +202,7 @@ export async function adaptfullyFromCli(argv = process.argv) {
|
|
|
190
202
|
}
|
|
191
203
|
|
|
192
204
|
const stage = command;
|
|
193
|
-
const { positionals, deployment, artifactPath } = parseStageArgs(argv.slice(3));
|
|
205
|
+
const { positionals, deployment, artifactPath, encrypt, encryptPublicKey } = parseStageArgs(argv.slice(3));
|
|
194
206
|
const platformKey = positionals[0];
|
|
195
207
|
const cliServer = positionals[1];
|
|
196
208
|
const mode = positionals[2] ?? 'extract';
|
|
@@ -198,29 +210,42 @@ export async function adaptfullyFromCli(argv = process.argv) {
|
|
|
198
210
|
if (!stage || !platformKey) {
|
|
199
211
|
throw new Error(
|
|
200
212
|
'Usage:\n'
|
|
201
|
-
+ ' adaptfully <prebuild|build|deploy|release> <platform> [
|
|
213
|
+
+ ' adaptfully <prebuild|build|deploy|release> <platform> [showfullyServer] [mode]\n'
|
|
214
|
+
+ ' [--deployment <key>] [--artifact <path>] [--encrypt] [--encrypt-public-key <pem|path>]\n'
|
|
202
215
|
+ ' adaptfully steam-publish [--username U] [--password P] [--deployment steam] [--output path]\n'
|
|
203
216
|
+ ' adaptfully google-publish [--from service-account.json] [--deployment android] [--output path]\n'
|
|
204
217
|
+ ' adaptfully apple-publish [--deployment ios] [--category C] [--identity I] [--username U] [--password P]\n'
|
|
218
|
+
+ ' adaptfully android-keystore [--deployment android] [--debug-only] [--yes]\n'
|
|
219
|
+
+ ' adaptfully apple-signing [--deployment ios] [--kind development|distribution] [--csr-only] [--from-cer path] [--provision path]\n'
|
|
205
220
|
+ '\n'
|
|
206
221
|
+ 'Stages:\n'
|
|
207
222
|
+ ' prebuild Copy deploy/ and apply platform registrations → output/<platform>-prebuild/\n'
|
|
208
|
-
+ ' build prebuild + POST /
|
|
209
|
-
+ ' deploy
|
|
210
|
-
+ ' release
|
|
223
|
+
+ ' build prebuild + POST /yap/wrapfully (zip artifact only; Showfully PAT required)\n'
|
|
224
|
+
+ ' deploy Yap deploy chore with prior artifact + deployment credentials\n'
|
|
225
|
+
+ ' release Yap release chore (build + configured deployments)\n'
|
|
211
226
|
+ '\n'
|
|
212
227
|
+ ' --deployment <key> Target a single named deployment.\n'
|
|
213
228
|
+ ' --artifact <path> Prior build artifact directory (deploy only; default: ./output/ after build).\n'
|
|
229
|
+
+ ' --encrypt Envelope-encrypt chore to Wrapfully (optional; default key embedded).\n'
|
|
230
|
+
+ ' --encrypt-public-key <pem|path> Override Wrapfully public key when encrypting.\n'
|
|
231
|
+
+ '\n'
|
|
232
|
+
+ 'Auth / server (wrapfully.json or env):\n'
|
|
233
|
+
+ ' SHOWFULLY_PAT / accessToken required PAT from play.makefullystudios.com Settings\n'
|
|
234
|
+
+ ' SHOWFULLY_SERVER / server Showfully Yap base (default https://make.makefullystudios.com/)\n'
|
|
214
235
|
+ '\n'
|
|
215
236
|
+ 'Publish credential helpers (one-time local setup):\n'
|
|
216
|
-
+ ' steam-publish
|
|
217
|
-
+ ' google-publish
|
|
218
|
-
+ ' apple-publish
|
|
237
|
+
+ ' steam-publish Install steamcmd if needed, log in, write steam deployment steam.json\n'
|
|
238
|
+
+ ' google-publish Import a Play service-account JSON into the android deployment folder\n'
|
|
239
|
+
+ ' apple-publish Write App Store Connect credentials into the ios deployment folder\n'
|
|
240
|
+
+ ' android-keystore Generate debug/release keystores and write android build.json\n'
|
|
241
|
+
+ ' apple-signing Generate CSR, export .p12, place provisioning profiles under ios/apple/',
|
|
219
242
|
);
|
|
220
243
|
}
|
|
221
244
|
|
|
222
245
|
const { pkg, wrapfullyConfig } = await loadProjectConfig();
|
|
223
246
|
const server = resolveServerUrl(wrapfullyConfig, cliServer);
|
|
247
|
+
const accessToken = resolveAccessToken(wrapfullyConfig);
|
|
248
|
+
const encryptFlag = resolveEncryptFlag(wrapfullyConfig, encrypt);
|
|
224
249
|
const deployFolder = pkg.config?.deployFolder || 'deploy';
|
|
225
250
|
|
|
226
251
|
return runAdaptfullyStage(/** @type {AdaptfullyStage} */ (stage), platformKey, {
|
|
@@ -230,18 +255,24 @@ export async function adaptfullyFromCli(argv = process.argv) {
|
|
|
230
255
|
mode,
|
|
231
256
|
deployment,
|
|
232
257
|
artifactPath,
|
|
258
|
+
accessToken,
|
|
259
|
+
encrypt: encryptFlag,
|
|
260
|
+
encryptPublicKey,
|
|
261
|
+
wrapfullyConfig,
|
|
233
262
|
});
|
|
234
263
|
}
|
|
235
264
|
|
|
236
265
|
/**
|
|
237
266
|
* @param {string[]} args
|
|
238
|
-
* @returns {{ positionals: string[], deployment?: string, artifactPath?: string }}
|
|
267
|
+
* @returns {{ positionals: string[], deployment?: string, artifactPath?: string, encrypt?: boolean, encryptPublicKey?: string }}
|
|
239
268
|
*/
|
|
240
269
|
export function parseStageArgs(args) {
|
|
241
270
|
/** @type {string[]} */
|
|
242
271
|
const positionals = [];
|
|
243
272
|
let deployment;
|
|
244
273
|
let artifactPath;
|
|
274
|
+
let encrypt;
|
|
275
|
+
let encryptPublicKey;
|
|
245
276
|
|
|
246
277
|
for (let i = 0; i < args.length; i++) {
|
|
247
278
|
const arg = args[i];
|
|
@@ -254,10 +285,16 @@ export function parseStageArgs(args) {
|
|
|
254
285
|
artifactPath = args[++i];
|
|
255
286
|
} else if (arg.startsWith('--artifact=')) {
|
|
256
287
|
artifactPath = arg.slice('--artifact='.length);
|
|
288
|
+
} else if (arg === '--encrypt') {
|
|
289
|
+
encrypt = true;
|
|
290
|
+
} else if (arg === '--encrypt-public-key' && args[i + 1]) {
|
|
291
|
+
encryptPublicKey = args[++i];
|
|
292
|
+
} else if (arg.startsWith('--encrypt-public-key=')) {
|
|
293
|
+
encryptPublicKey = arg.slice('--encrypt-public-key='.length);
|
|
257
294
|
} else {
|
|
258
295
|
positionals.push(arg);
|
|
259
296
|
}
|
|
260
297
|
}
|
|
261
298
|
|
|
262
|
-
return { positionals, deployment, artifactPath };
|
|
299
|
+
return { positionals, deployment, artifactPath, encrypt, encryptPublicKey };
|
|
263
300
|
}
|
|
@@ -211,13 +211,33 @@ export async function promptRequired(prompt, existing) {
|
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
+
/**
|
|
215
|
+
* @param {string} prompt
|
|
216
|
+
* @param {boolean} [defaultYes=false]
|
|
217
|
+
* @returns {Promise<boolean>}
|
|
218
|
+
*/
|
|
219
|
+
export async function promptConfirm(prompt, defaultYes = false) {
|
|
220
|
+
const rl = readline.createInterface({ input, output });
|
|
221
|
+
const suffix = defaultYes ? ' [Y/n] ' : ' [y/N] ';
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
const answer = String(await rl.question(`${prompt}${suffix}`)).trim().toLowerCase();
|
|
225
|
+
if (!answer) {
|
|
226
|
+
return defaultYes;
|
|
227
|
+
}
|
|
228
|
+
return answer === 'y' || answer === 'yes';
|
|
229
|
+
} finally {
|
|
230
|
+
rl.close();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
214
234
|
/**
|
|
215
235
|
* Parse shared CLI flags used by publish credential helpers.
|
|
216
236
|
* @param {string[]} argv
|
|
217
237
|
* @param {number} [startIndex=3]
|
|
218
238
|
*/
|
|
219
239
|
export function parsePublishCredentialArgv(argv, startIndex = 3) {
|
|
220
|
-
/** @type {Record<string, string>} */
|
|
240
|
+
/** @type {Record<string, string | boolean>} */
|
|
221
241
|
const options = {
|
|
222
242
|
projectRoot: '.',
|
|
223
243
|
};
|
|
@@ -243,6 +263,32 @@ export function parsePublishCredentialArgv(argv, startIndex = 3) {
|
|
|
243
263
|
options.username = argv[++i];
|
|
244
264
|
} else if (arg === '--password' && argv[i + 1]) {
|
|
245
265
|
options.password = argv[++i];
|
|
266
|
+
} else if (arg === '--debug-only') {
|
|
267
|
+
options.debugOnly = true;
|
|
268
|
+
} else if (arg === '--csr-only') {
|
|
269
|
+
options.csrOnly = true;
|
|
270
|
+
} else if (arg === '--yes' || arg === '-y') {
|
|
271
|
+
options.yes = true;
|
|
272
|
+
} else if (arg === '--from-cer' && argv[i + 1]) {
|
|
273
|
+
options.fromCer = normalizeUserPath(argv[++i]);
|
|
274
|
+
} else if (arg === '--kind' && argv[i + 1]) {
|
|
275
|
+
options.kind = argv[++i];
|
|
276
|
+
} else if (arg === '--provision' && argv[i + 1]) {
|
|
277
|
+
options.provision = normalizeUserPath(argv[++i]);
|
|
278
|
+
} else if (arg === '--workdir' && argv[i + 1]) {
|
|
279
|
+
options.workdir = normalizeUserPath(argv[++i]);
|
|
280
|
+
} else if (arg === '--alias' && argv[i + 1]) {
|
|
281
|
+
options.alias = argv[++i];
|
|
282
|
+
} else if (arg === '--store-password' && argv[i + 1]) {
|
|
283
|
+
options.storePassword = argv[++i];
|
|
284
|
+
} else if (arg === '--key-password' && argv[i + 1]) {
|
|
285
|
+
options.keyPassword = argv[++i];
|
|
286
|
+
} else if (arg === '--p12-password' && argv[i + 1]) {
|
|
287
|
+
options.p12Password = argv[++i];
|
|
288
|
+
} else if (arg === '--cn' && argv[i + 1]) {
|
|
289
|
+
options.cn = argv[++i];
|
|
290
|
+
} else if (arg === '--email' && argv[i + 1]) {
|
|
291
|
+
options.email = argv[++i];
|
|
246
292
|
}
|
|
247
293
|
}
|
|
248
294
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Makefully Wrapfully fleet public key (kid: makefully-wrapfully-1).
|
|
3
|
+
* Private key lives only on Wrapfully workers (WRAPFULLY_PRIVATE_KEY / cred.json).
|
|
4
|
+
* Safe to embed in clients — used only to wrap chore AES keys when encrypt: true.
|
|
5
|
+
*/
|
|
6
|
+
export const WRAPFULLY_DEFAULT_KID = 'makefully-wrapfully-1';
|
|
7
|
+
|
|
8
|
+
export const WRAPFULLY_DEFAULT_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
9
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArbQGAXiX+XtnsdS0yUPj
|
|
10
|
+
dgM2Vt8lwDXPtLxzjYD45fr/NEOct0+ECsvr3jyIB/cVCjINpJJyKGEBvZk8woFj
|
|
11
|
+
FgyodSWjJrc1UsomeOz6IcOArWu6GnkFo0jn8R0FN8LOhEl1xjqT7VPzF4jd7/P5
|
|
12
|
+
4WBNeB+wjkY/XBmk5wsNLvGaREp8G4fFfMgDNPpTUy7RB8ezolTiWZH0KgiXZtM8
|
|
13
|
+
yUXk5YBPxTwI28wCB6Om5RGmwozWc66k29qZQRv5d4GRMSM18lMKh3gkjptZRhRD
|
|
14
|
+
D48bKDQwYPX8CWcpl/Q9qm2L0wtikjQWro1NsAreqa3r91wlrsYZ82stYIyKBYhW
|
|
15
|
+
LwIDAQAB
|
|
16
|
+
-----END PUBLIC KEY-----
|
|
17
|
+
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makefully/adaptfully",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Platform abstraction and Wrapfully deploy client for Makefully games",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/node/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"bin",
|
|
19
19
|
"lib",
|
|
20
|
+
"docs",
|
|
20
21
|
"CHANGELOG.md",
|
|
21
22
|
"LICENSE",
|
|
22
23
|
"README.md"
|