publish-apk 0.0.1-alpha.13 → 0.0.1-alpha.15
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 +13 -3
- package/package.json +2 -1
- package/src/huawei-signing.js +19 -1
- package/src/keystore.js +24 -7
package/README.md
CHANGED
|
@@ -192,14 +192,16 @@ ANDROID_KEYSTORE_BASE64=... ANDROID_KEYSTORE_PASSWORD=... publish-apk keystore
|
|
|
192
192
|
|
|
193
193
|
### keystore-env(导出 Android keystore 的 CI 变量)
|
|
194
194
|
|
|
195
|
-
把一份 keystore 文件导出成 CI
|
|
195
|
+
把一份 keystore 文件导出成 CI 可直接配置的变量。默认输出四个:
|
|
196
196
|
|
|
197
197
|
| 变量 | 内容 |
|
|
198
198
|
| --- | --- |
|
|
199
|
-
| `ANDROID_KEYSTORE_BASE64` | keystore 文件的单行 BASE64 |
|
|
199
|
+
| `ANDROID_KEYSTORE_BASE64` | keystore 文件的单行 BASE64;加 `--no-base64` 可去掉 |
|
|
200
200
|
| `ANDROID_KEYSTORE_PASSWORD` | keystore 明文口令 |
|
|
201
201
|
| `ANDROID_KEY_ALIAS` | 私钥别名(不传 `--key-alias` 时由 keytool 自动识别) |
|
|
202
202
|
| `ANDROID_KEY_PASSWORD` | 私钥明文口令(默认与 keystore 口令相同) |
|
|
203
|
+
| `ANDROID_KEYSTORE_FILE` | 可选;加 `--include-file` 输出 keystore 的绝对路径,给本地 `signing.env` 用 |
|
|
204
|
+
|
|
203
205
|
|
|
204
206
|
```bash
|
|
205
207
|
# 默认 env 格式:KEY=value,一行一个,适合逐项复制到 CI 变量
|
|
@@ -210,11 +212,17 @@ ANDROID_KEYSTORE_PASSWORD=<口令> publish-apk keystore-env --file ./release.p12
|
|
|
210
212
|
|
|
211
213
|
# JSON 格式
|
|
212
214
|
ANDROID_KEYSTORE_PASSWORD=<口令> publish-apk keystore-env --file ./release.p12 --format json > keystore.json
|
|
215
|
+
|
|
216
|
+
# 生成可直接 source 的本地签名环境(要文件路径,不要 BASE64)
|
|
217
|
+
ANDROID_KEYSTORE_PASSWORD=<口令> publish-apk keystore-env --file ./release.p12 \
|
|
218
|
+
--format shell --include-file --no-base64 > .signing/android.env
|
|
213
219
|
```
|
|
214
220
|
|
|
215
221
|
- 生成变量前会用 keytool 校验 keystore 口令、别名与私钥口令,校验失败不会输出变量。
|
|
216
222
|
- `--key-alias` / `ANDROID_KEY_ALIAS` 不传时自动识别;`--key-password` / `ANDROID_KEY_PASSWORD`
|
|
217
223
|
不传时使用 keystore 口令。
|
|
224
|
+
- `--include-file` 额外输出 `ANDROID_KEYSTORE_FILE`;`--no-base64` 去掉 `ANDROID_KEYSTORE_BASE64`。
|
|
225
|
+
两者一起用适合生成 `.signing/android.env`,避免把整份 BASE64 再塞进本地环境。
|
|
218
226
|
- `env` 格式不额外加引号,适合把 `=` 后面的值逐项复制到 CI 变量;`shell` 格式适合本地
|
|
219
227
|
`source`;`json` 格式适合脚本解析。
|
|
220
228
|
- **警告:输出包含明文口令**,不要写入日志、提交仓库或公开分享;`stdout` 只有变量,
|
|
@@ -480,7 +488,7 @@ HARMONY_CERTPATH_BASE64=... \
|
|
|
480
488
|
HARMONY_PROFILE_BASE64=... \
|
|
481
489
|
HARMONY_STORE_PASSWORD=<p12口令> \
|
|
482
490
|
publish-apk huawei signing-material-env \
|
|
483
|
-
--config ./build-profile.json5 --name default
|
|
491
|
+
--config ./build-profile.json5 --name default --require-all
|
|
484
492
|
```
|
|
485
493
|
|
|
486
494
|
- 支持的 `HARMONY_*` 变量:
|
|
@@ -493,6 +501,8 @@ publish-apk huawei signing-material-env \
|
|
|
493
501
|
- `HARMONY_*_OUT` 控制 BASE64 / 内容落盘位置
|
|
494
502
|
- 先校验证书 / Profile / p12 内容;有口令时还会用 `keytool` 自检;全部通过后才写回。
|
|
495
503
|
- 没有提供的变量保持原值;只替换提供的字段。
|
|
504
|
+
- `--require-all` 要求 store / cert / profile / 口令齐全,缺一项直接失败;CI 用这个开关保证
|
|
505
|
+
不会拿半套材料继续打包。
|
|
496
506
|
- 口令通过 `.p12` 同级 `material/` 加密;material 不存在时自动生成,`--new-material` 可重造。
|
|
497
507
|
- 写回前备份到 `.signing/backup/`,写后回读校验。
|
|
498
508
|
- 只给 `HARMONY_KEY_PASSWORD` 时还需要 `HARMONY_STORE_PASSWORD` 才能校验 / 加密。
|
package/package.json
CHANGED
package/src/huawei-signing.js
CHANGED
|
@@ -63,6 +63,8 @@ const OPTION_PRODUCT = '--product'
|
|
|
63
63
|
const OPTION_WRITE = '--write'
|
|
64
64
|
const OPTION_NEW_MATERIAL = '--new-material'
|
|
65
65
|
const OPTION_NO_KEYTOOL = '--no-keytool'
|
|
66
|
+
/** signing-material-env:要求 store / cert / profile / 口令齐全 */
|
|
67
|
+
const OPTION_REQUIRE_ALL = '--require-all'
|
|
66
68
|
const OPTION_VERBOSE = '--verbose'
|
|
67
69
|
|
|
68
70
|
const SIGNING_OPTIONS = new Set([
|
|
@@ -119,8 +121,9 @@ const MATERIAL_ENV_OPTIONS = new Set([
|
|
|
119
121
|
OPTION_PRODUCT,
|
|
120
122
|
OPTION_NO_KEYTOOL,
|
|
121
123
|
OPTION_NEW_MATERIAL,
|
|
124
|
+
OPTION_REQUIRE_ALL,
|
|
122
125
|
])
|
|
123
|
-
const MATERIAL_ENV_FLAGS = new Set([OPTION_NO_KEYTOOL, OPTION_NEW_MATERIAL])
|
|
126
|
+
const MATERIAL_ENV_FLAGS = new Set([OPTION_NO_KEYTOOL, OPTION_NEW_MATERIAL, OPTION_REQUIRE_ALL])
|
|
124
127
|
|
|
125
128
|
const ENV_STORE_FILE = 'HARMONY_STORE_FILE'
|
|
126
129
|
const ENV_STORE_FILE_BASE64 = 'HARMONY_STORE_FILE_BASE64'
|
|
@@ -646,6 +649,7 @@ function renderSigningMaterialEnvHelp() {
|
|
|
646
649
|
[`${OPTION_PRODUCT} <产品>`, `按 products[].name 找到它挂的 signingConfig(可用 ${ENV_PRODUCT} 补齐)`],
|
|
647
650
|
[OPTION_NO_KEYTOOL, '跳过 keytool 口令自检(仍会校验证书 / Profile / p12 内容)'],
|
|
648
651
|
[OPTION_NEW_MATERIAL, 'material 已存在也重造一套(旧的挪成 material.bak-<时间戳>)'],
|
|
652
|
+
[OPTION_REQUIRE_ALL, '要求 store / cert / profile / 口令齐全;缺一项直接失败(CI 用)'],
|
|
649
653
|
['-h, --help', '显示帮助信息'],
|
|
650
654
|
],
|
|
651
655
|
},
|
|
@@ -1766,6 +1770,20 @@ export async function runHuaweiSigningMaterialEnv(argv, env) {
|
|
|
1766
1770
|
const storePasswordEnv = readEnv(env, ENV_STORE_PASSWORD)
|
|
1767
1771
|
const keyPasswordEnv = readEnv(env, ENV_KEY_PASSWORD)
|
|
1768
1772
|
|
|
1773
|
+
if (options.get(OPTION_REQUIRE_ALL) === true) {
|
|
1774
|
+
const missing = []
|
|
1775
|
+
if (storeValues.length === 0) missing.push(`${ENV_STORE_FILE} / ${ENV_STORE_FILE_BASE64}`)
|
|
1776
|
+
if (certValues.length === 0) missing.push(`${ENV_CERTPATH} / ${ENV_CERTPATH_BASE64}`)
|
|
1777
|
+
if (profileValues.length === 0) missing.push(`${ENV_PROFILE} / ${ENV_PROFILE_BASE64}`)
|
|
1778
|
+
if (storePasswordEnv === undefined) missing.push(ENV_STORE_PASSWORD)
|
|
1779
|
+
if (missing.length > 0) {
|
|
1780
|
+
throw new UsageError(
|
|
1781
|
+
`${OPTION_REQUIRE_ALL} 缺少:${missing.join('、')}`,
|
|
1782
|
+
renderSigningMaterialEnvHelp(),
|
|
1783
|
+
)
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1769
1787
|
const configStoreFileValue = stringField(entry.text, 'storeFile')
|
|
1770
1788
|
let storeFile =
|
|
1771
1789
|
configStoreFileValue === undefined || configStoreFileValue.trim() === ''
|
package/src/keystore.js
CHANGED
|
@@ -71,6 +71,10 @@ const OPTION_VALIDITY = '--validity'
|
|
|
71
71
|
const OPTION_DNAME = '--dname'
|
|
72
72
|
const OPTION_FORCE = '--force'
|
|
73
73
|
const OPTION_FORMAT = '--format'
|
|
74
|
+
/** keystore-env:额外输出 ANDROID_KEYSTORE_FILE(绝对路径) */
|
|
75
|
+
const OPTION_INCLUDE_FILE = '--include-file'
|
|
76
|
+
/** keystore-env:不输出 ANDROID_KEYSTORE_BASE64 */
|
|
77
|
+
const OPTION_NO_BASE64 = '--no-base64'
|
|
74
78
|
|
|
75
79
|
const KEYSTORE_OPTIONS = new Set([
|
|
76
80
|
OPTION_FILE,
|
|
@@ -100,8 +104,10 @@ const ENV_OPTIONS = new Set([
|
|
|
100
104
|
OPTION_KEY_ALIAS,
|
|
101
105
|
OPTION_KEY_PASSWORD,
|
|
102
106
|
OPTION_FORMAT,
|
|
107
|
+
OPTION_INCLUDE_FILE,
|
|
108
|
+
OPTION_NO_BASE64,
|
|
103
109
|
])
|
|
104
|
-
const ENV_FLAGS = new Set()
|
|
110
|
+
const ENV_FLAGS = new Set([OPTION_INCLUDE_FILE, OPTION_NO_BASE64])
|
|
105
111
|
|
|
106
112
|
/** 密钥库路径,等价于 --file(也可用 ANDROID_KEYSTORE 补) */
|
|
107
113
|
const ENV_FILE = 'ANDROID_KEYSTORE_FILE'
|
|
@@ -884,6 +890,8 @@ function renderKeystoreEnvHelp() {
|
|
|
884
890
|
`${OPTION_FORMAT} <env|shell|json>`,
|
|
885
891
|
'输出格式,默认 env(KEY=value,一行一个);shell 输出 export KEY=...;json 输出对象',
|
|
886
892
|
],
|
|
893
|
+
[OPTION_INCLUDE_FILE, '额外输出 ANDROID_KEYSTORE_FILE(绝对路径)'],
|
|
894
|
+
[OPTION_NO_BASE64, '不输出 ANDROID_KEYSTORE_BASE64(本地 signing.env 用)'],
|
|
887
895
|
['-h, --help', '显示帮助信息'],
|
|
888
896
|
],
|
|
889
897
|
},
|
|
@@ -902,7 +910,7 @@ function renderKeystoreEnvHelp() {
|
|
|
902
910
|
entries: [
|
|
903
911
|
[
|
|
904
912
|
'stdout',
|
|
905
|
-
'ANDROID_KEYSTORE_BASE64 /
|
|
913
|
+
'默认 ANDROID_KEYSTORE_BASE64 / PASSWORD / ALIAS / KEY_PASSWORD;加 --include-file 输出 ANDROID_KEYSTORE_FILE,加 --no-base64 去掉 BASE64',
|
|
906
914
|
],
|
|
907
915
|
['stderr', '明文口令警告与错误信息'],
|
|
908
916
|
],
|
|
@@ -920,6 +928,7 @@ function renderKeystoreEnvHelp() {
|
|
|
920
928
|
` ${PROGRAM} ${ENV_COMMAND_NAME} --file ./release.p12`,
|
|
921
929
|
` ANDROID_KEYSTORE_PASSWORD=<口令> ${PROGRAM} ${ENV_COMMAND_NAME} --file ./release.p12 --format shell`,
|
|
922
930
|
` ${PROGRAM} ${ENV_COMMAND_NAME} --file ./release.p12 --format json > keystore.json`,
|
|
931
|
+
` ${PROGRAM} ${ENV_COMMAND_NAME} --file ./release.p12 --format shell --include-file --no-base64 > signing.env`,
|
|
923
932
|
'',
|
|
924
933
|
'警告: 输出包含明文口令,请勿写入日志、提交仓库或公开分享',
|
|
925
934
|
'说明: 生成前会用 keytool 校验 keystore 口令、别名与私钥口令',
|
|
@@ -929,13 +938,19 @@ function renderKeystoreEnvHelp() {
|
|
|
929
938
|
})
|
|
930
939
|
}
|
|
931
940
|
|
|
932
|
-
function renderKeystoreEnvVariables(buffer, alias, storePassword, keyPassword, format, help) {
|
|
933
|
-
const values = [
|
|
934
|
-
|
|
941
|
+
function renderKeystoreEnvVariables(absolute, buffer, alias, storePassword, keyPassword, format, options, help) {
|
|
942
|
+
const values = []
|
|
943
|
+
if (!options.get(OPTION_NO_BASE64)) {
|
|
944
|
+
values.push(['ANDROID_KEYSTORE_BASE64', buffer.toString('base64')])
|
|
945
|
+
}
|
|
946
|
+
if (options.get(OPTION_INCLUDE_FILE)) {
|
|
947
|
+
values.push(['ANDROID_KEYSTORE_FILE', absolute])
|
|
948
|
+
}
|
|
949
|
+
values.push(
|
|
935
950
|
['ANDROID_KEYSTORE_PASSWORD', storePassword],
|
|
936
951
|
['ANDROID_KEY_ALIAS', alias],
|
|
937
952
|
['ANDROID_KEY_PASSWORD', keyPassword],
|
|
938
|
-
|
|
953
|
+
)
|
|
939
954
|
if (format === 'env') {
|
|
940
955
|
return values.map(([name, value]) => `${name}=${value}`).join('\n')
|
|
941
956
|
}
|
|
@@ -994,7 +1009,9 @@ async function runKeystoreEnv(argv, env) {
|
|
|
994
1009
|
})
|
|
995
1010
|
stderr('警告: 输出包含明文口令,请勿写入日志、提交仓库或公开分享')
|
|
996
1011
|
stdout(
|
|
997
|
-
renderKeystoreEnvVariables(
|
|
1012
|
+
renderKeystoreEnvVariables(
|
|
1013
|
+
absolute, buffer, info.alias, storePassword, keyPassword, format, options, renderKeystoreEnvHelp(),
|
|
1014
|
+
),
|
|
998
1015
|
)
|
|
999
1016
|
return EXIT_OK
|
|
1000
1017
|
}
|