@lynxship/cli 0.1.3 → 0.1.4
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/README.md +15 -0
- package/dist/android-build.d.ts.map +1 -1
- package/dist/android-build.js +61 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -97,6 +97,21 @@ Progress percentages are shown only when LynxShip has a real measurement. Long
|
|
|
97
97
|
Rspeedy, Gradle and Xcode operations remain visible in the event journal until
|
|
98
98
|
their completion checkpoint is known; no timer-based percentage is invented.
|
|
99
99
|
|
|
100
|
+
### Project-safe Android signing
|
|
101
|
+
|
|
102
|
+
LynxShip does not require every project to contain a LynxShip-specific signing
|
|
103
|
+
helper. During a real Android build it creates a temporary Gradle init script,
|
|
104
|
+
passes it with Gradle's `--init-script` option, and removes it when the build
|
|
105
|
+
finishes. The script reads only the already configured machine credentials and
|
|
106
|
+
uses the Android Components `finalizeDsl` hook to configure the standard
|
|
107
|
+
`release` build type. The project's Gradle files are left unchanged.
|
|
108
|
+
|
|
109
|
+
This supports normal Android Gradle Plugin application projects using either
|
|
110
|
+
Groovy or Kotlin DSL. Projects with custom flavor tasks, non-standard signing
|
|
111
|
+
plugins, or no Android `release` build type must expose their signing contract
|
|
112
|
+
explicitly; LynxShip fails with a clear diagnostic rather than producing an
|
|
113
|
+
unverified artifact.
|
|
114
|
+
|
|
100
115
|
## Main commands
|
|
101
116
|
|
|
102
117
|
```text
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"android-build.d.ts","sourceRoot":"","sources":["../src/android-build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"android-build.d.ts","sourceRoot":"","sources":["../src/android-build.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWhD,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AA0LD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAa7D;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsCpE;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CAgKnB"}
|
package/dist/android-build.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { access, copyFile, cp, mkdir, readFile, readdir, } from "node:fs/promises";
|
|
1
|
+
import { access, chmod, copyFile, cp, mkdir, mkdtemp, readFile, readdir, rm, writeFile, } from "node:fs/promises";
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { constants as fsConstants, existsSync, readdirSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
4
5
|
import { join } from "node:path";
|
|
5
6
|
import { assert, sha256 } from "@lynxship/contracts";
|
|
6
7
|
import { transitionBuild } from "@lynxship/build-orchestrator";
|
|
@@ -33,6 +34,56 @@ async function signingEnvironment(root) {
|
|
|
33
34
|
assert(missing.length === 0, "BUILD_SIGNING_REQUIRED", `Signed Android builds require configuration. Missing: ${missing.join(", ")}. Run \`lynxship android configure\`.`);
|
|
34
35
|
return { ...process.env, ...values };
|
|
35
36
|
}
|
|
37
|
+
async function createSigningInitScript() {
|
|
38
|
+
const directory = await mkdtemp(join(tmpdir(), "lynxship-gradle-"));
|
|
39
|
+
const file = join(directory, "android-signing.init.gradle");
|
|
40
|
+
const script = `
|
|
41
|
+
def keystorePath = System.getenv("LYNXSHIP_KEYSTORE_PATH")
|
|
42
|
+
def keyAlias = System.getenv("LYNXSHIP_KEY_ALIAS")
|
|
43
|
+
def keystorePassword = System.getenv("LYNXSHIP_KEYSTORE_PASSWORD")
|
|
44
|
+
def keyPassword = System.getenv("LYNXSHIP_KEY_PASSWORD")
|
|
45
|
+
|
|
46
|
+
gradle.allprojects { project ->
|
|
47
|
+
project.plugins.withId("com.android.application") {
|
|
48
|
+
def configureSigning = { android ->
|
|
49
|
+
def signing = android.signingConfigs.findByName("release")
|
|
50
|
+
if (signing == null) {
|
|
51
|
+
signing = android.signingConfigs.create("lynxshipRelease")
|
|
52
|
+
}
|
|
53
|
+
signing.storeFile = project.file(keystorePath)
|
|
54
|
+
signing.storePassword = keystorePassword
|
|
55
|
+
signing.keyAlias = keyAlias
|
|
56
|
+
signing.keyPassword = keyPassword
|
|
57
|
+
|
|
58
|
+
def release = android.buildTypes.findByName("release")
|
|
59
|
+
if (release == null) {
|
|
60
|
+
throw new GradleException(
|
|
61
|
+
"LynxShip requires an Android release build type"
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
release.signingConfig = signing
|
|
65
|
+
project.logger.lifecycle(
|
|
66
|
+
"[LynxShip] Applied machine signing credentials to \${project.path}:release"
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
def androidComponents = project.extensions.findByName("androidComponents")
|
|
71
|
+
if (androidComponents != null) {
|
|
72
|
+
androidComponents.finalizeDsl { android ->
|
|
73
|
+
configureSigning(android)
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
project.afterEvaluate {
|
|
77
|
+
configureSigning(project.extensions.findByName("android"))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
await writeFile(file, script, "utf8");
|
|
84
|
+
await chmod(file, 0o600).catch(() => undefined);
|
|
85
|
+
return { directory, file };
|
|
86
|
+
}
|
|
36
87
|
async function verifySignedArtifact(root, artifactPath, options) {
|
|
37
88
|
if (artifactPath.endsWith(".apk")) {
|
|
38
89
|
const apksigner = androidTool("apksigner");
|
|
@@ -161,6 +212,7 @@ export async function runRealAndroidBuild(job, options) {
|
|
|
161
212
|
quiet: options.quiet ?? false,
|
|
162
213
|
onOutput: options.onEvent,
|
|
163
214
|
};
|
|
215
|
+
let signingInitDirectory;
|
|
164
216
|
try {
|
|
165
217
|
transitionBuild(job, "uploading_source", "local Android source prepared");
|
|
166
218
|
job.logs.push({
|
|
@@ -189,7 +241,10 @@ export async function runRealAndroidBuild(job, options) {
|
|
|
189
241
|
step("Android host synchronized", 40);
|
|
190
242
|
transitionBuild(job, "building", `Gradle ${artifact.task}`);
|
|
191
243
|
step(`Running real Gradle task ${artifact.task}…`);
|
|
192
|
-
|
|
244
|
+
step("Applying temporary LynxShip Android signing adapter…");
|
|
245
|
+
const signingInitScript = await createSigningInitScript();
|
|
246
|
+
signingInitDirectory = signingInitScript.directory;
|
|
247
|
+
const gradleArgs = ["--init-script", signingInitScript.file, artifact.task];
|
|
193
248
|
if (process.env.CI)
|
|
194
249
|
gradleArgs.push("--stacktrace");
|
|
195
250
|
await runProcess(wrapper, gradleArgs, {
|
|
@@ -258,4 +313,8 @@ export async function runRealAndroidBuild(job, options) {
|
|
|
258
313
|
});
|
|
259
314
|
throw error;
|
|
260
315
|
}
|
|
316
|
+
finally {
|
|
317
|
+
if (signingInitDirectory)
|
|
318
|
+
await rm(signingInitDirectory, { recursive: true, force: true });
|
|
319
|
+
}
|
|
261
320
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynxship/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Build, sign, store, submit and update LynxJS applications from the terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -67,10 +67,10 @@
|
|
|
67
67
|
"cli-progress": "3.12.0",
|
|
68
68
|
"ora": "8.2.0",
|
|
69
69
|
"qrcode-terminal": "0.12.0",
|
|
70
|
-
"@lynxship/db": "0.1.0",
|
|
71
70
|
"@lynxship/build-orchestrator": "0.1.0",
|
|
72
|
-
"@lynxship/
|
|
71
|
+
"@lynxship/db": "0.1.0",
|
|
73
72
|
"@lynxship/contracts": "0.1.0",
|
|
73
|
+
"@lynxship/signing": "0.1.0",
|
|
74
74
|
"@lynxship/submit": "0.1.0"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|