@applift/core 0.11.0 → 0.12.1
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/dist/{artifact-DbTqPUbk.mjs → artifact-D3BSnmqY.mjs} +107 -4
- package/dist/{frameworks-D0dZKGUL.d.mts → frameworks-B-t5Ywma.d.mts} +4 -0
- package/dist/index.d.mts +7 -1
- package/dist/index.mjs +36 -9
- package/dist/plugins/index.d.mts +17 -4
- package/dist/plugins/index.mjs +49 -9
- package/package.json +1 -1
|
@@ -1160,13 +1160,111 @@ function assertBetaVersionSupported(ctx) {
|
|
|
1160
1160
|
* 产物版本读取(只读不写——版本号变更属开发提交,发版工具只负责读版本防回退)。
|
|
1161
1161
|
* .hap/.app:pack.info 是纯 JSON,零依赖直接读;
|
|
1162
1162
|
* .apk:aapt2/aapt dump badging(ANDROID_HOME/SDK 探测,同 oppo 渠道逻辑);
|
|
1163
|
-
* .
|
|
1163
|
+
* .hap/.app 的 pushy 构建时间戳在包内 resources/rawfile/meta.json(pushy hvigor 插件写入),
|
|
1164
|
+
* 由 readArtifactBuildTime 读取——基线 buildTime 必须与设备上报精确一致(不匹配服务端封锁 6h)。
|
|
1164
1165
|
*/
|
|
1165
1166
|
function readArtifactVersion(artifactPath) {
|
|
1166
1167
|
const ext = path.extname(artifactPath).toLowerCase();
|
|
1167
1168
|
if (ext === ".hap" || ext === ".app") return fromPackInfo(artifactPath);
|
|
1168
1169
|
if (ext === ".apk") return fromAapt(artifactPath);
|
|
1169
1170
|
}
|
|
1171
|
+
/** 产物 pushy 构建时间戳读取(buildTime 与设备上报必须精确一致,读不出返回 undefined,
|
|
1172
|
+
* 由调用方决定拒绝上传而非猜测)。
|
|
1173
|
+
* .hap/.app:包内(.app 可能嵌套 hap)resources/rawfile/meta.json 的 pushy_build_time;
|
|
1174
|
+
* .apk:AndroidManifest meta-data pushy_build_time(aapt2/aapt xmltree);
|
|
1175
|
+
* .ipa:Payload/*.app/pushy_build_time.txt(官方 Xcode 构建 phase 产物)。 */
|
|
1176
|
+
function readArtifactBuildTime(artifactPath) {
|
|
1177
|
+
const ext = path.extname(artifactPath).toLowerCase();
|
|
1178
|
+
if (ext === ".hap" || ext === ".app") return harmonyBuildTime(artifactPath);
|
|
1179
|
+
if (ext === ".apk") return apkBuildTime(artifactPath);
|
|
1180
|
+
if (ext === ".ipa") return ipaBuildTime(artifactPath);
|
|
1181
|
+
}
|
|
1182
|
+
/** unzip 子进程 stdout(失败/超时返回 undefined,调用方按读不出处理) */
|
|
1183
|
+
function unzipStdout(args) {
|
|
1184
|
+
const r = spawnSync("unzip", args, {
|
|
1185
|
+
timeout: 2e4,
|
|
1186
|
+
encoding: "utf8",
|
|
1187
|
+
maxBuffer: 67108864
|
|
1188
|
+
});
|
|
1189
|
+
return !r.error && r.status === 0 ? r.stdout : void 0;
|
|
1190
|
+
}
|
|
1191
|
+
function metaJsonBuildTime(text) {
|
|
1192
|
+
if (!text) return void 0;
|
|
1193
|
+
let meta;
|
|
1194
|
+
try {
|
|
1195
|
+
meta = JSON.parse(text);
|
|
1196
|
+
} catch {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (meta && typeof meta === "object" && "pushy_build_time" in meta) {
|
|
1200
|
+
const v = meta.pushy_build_time;
|
|
1201
|
+
if (typeof v === "string" || typeof v === "number") return String(v);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
/** 鸿蒙:先按顶层 resources/rawfile/meta.json 读(hap 或直排 hap 内容的 .app);
|
|
1205
|
+
* .app 整包的 hap 嵌套在 zip 里,取出后再读(对照官方 CLI getAppInfo 的嵌套提取)。 */
|
|
1206
|
+
function harmonyBuildTime(artifactPath) {
|
|
1207
|
+
const direct = metaJsonBuildTime(unzipStdout([
|
|
1208
|
+
"-p",
|
|
1209
|
+
artifactPath,
|
|
1210
|
+
"resources/rawfile/meta.json"
|
|
1211
|
+
]));
|
|
1212
|
+
if (direct) return direct;
|
|
1213
|
+
const hapEntry = unzipStdout(["-Z1", artifactPath])?.split("\n").map((s) => s.trim()).find((s) => s.endsWith(".hap"));
|
|
1214
|
+
if (!hapEntry) return void 0;
|
|
1215
|
+
const tmp = path.join(os.tmpdir(), `applift-meta-hap-${process.pid}-${Date.now()}`);
|
|
1216
|
+
try {
|
|
1217
|
+
const ex = spawnSync("unzip", [
|
|
1218
|
+
"-p",
|
|
1219
|
+
artifactPath,
|
|
1220
|
+
hapEntry
|
|
1221
|
+
], {
|
|
1222
|
+
timeout: 6e4,
|
|
1223
|
+
maxBuffer: 536870912
|
|
1224
|
+
});
|
|
1225
|
+
if (ex.error || ex.status !== 0 || !ex.stdout) return void 0;
|
|
1226
|
+
fs.writeFileSync(tmp, ex.stdout);
|
|
1227
|
+
return metaJsonBuildTime(unzipStdout([
|
|
1228
|
+
"-p",
|
|
1229
|
+
tmp,
|
|
1230
|
+
"resources/rawfile/meta.json"
|
|
1231
|
+
]));
|
|
1232
|
+
} finally {
|
|
1233
|
+
fs.rmSync(tmp, { force: true });
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
/** APK:AndroidManifest meta-data pushy_build_time(对照官方 CLI getApkInfo 的 meta 读取) */
|
|
1237
|
+
function apkBuildTime(artifactPath) {
|
|
1238
|
+
for (const tool of aaptTools()) {
|
|
1239
|
+
const args = path.basename(tool).startsWith("aapt2") ? [
|
|
1240
|
+
"dump",
|
|
1241
|
+
"xmltree",
|
|
1242
|
+
"--file",
|
|
1243
|
+
"AndroidManifest.xml",
|
|
1244
|
+
artifactPath
|
|
1245
|
+
] : [
|
|
1246
|
+
"dump",
|
|
1247
|
+
"xmltree",
|
|
1248
|
+
artifactPath,
|
|
1249
|
+
"AndroidManifest.xml"
|
|
1250
|
+
];
|
|
1251
|
+
const r = spawnSync(tool, args, {
|
|
1252
|
+
timeout: 1e4,
|
|
1253
|
+
encoding: "utf8"
|
|
1254
|
+
});
|
|
1255
|
+
if (r.error || r.status !== 0) continue;
|
|
1256
|
+
const m = /pushy_build_time"[\s\S]{0,400}?="(\d+)"/.exec(r.stdout ?? "");
|
|
1257
|
+
if (m?.[1]) return m[1];
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
/** iOS:Payload/*.app/pushy_build_time.txt(官方 Xcode 构建 phase 产物) */
|
|
1261
|
+
function ipaBuildTime(artifactPath) {
|
|
1262
|
+
return unzipStdout([
|
|
1263
|
+
"-p",
|
|
1264
|
+
artifactPath,
|
|
1265
|
+
"Payload/*.app/pushy_build_time.txt"
|
|
1266
|
+
])?.trim() || void 0;
|
|
1267
|
+
}
|
|
1170
1268
|
/** 鸿蒙包版本读取:优先包内 pack.info(zip 容器内的权威数据),回退同目录 pack.info(标注可能过期) */
|
|
1171
1269
|
function fromPackInfo(artifactPath) {
|
|
1172
1270
|
const r = spawnSync("unzip", [
|
|
@@ -1202,8 +1300,8 @@ function parsePackInfo(text, source) {
|
|
|
1202
1300
|
};
|
|
1203
1301
|
} catch {}
|
|
1204
1302
|
}
|
|
1205
|
-
/**
|
|
1206
|
-
function
|
|
1303
|
+
/** aapt 工具探测(ANDROID_HOME/SDK build-tools 下新版优先,aapt2 先于 aapt) */
|
|
1304
|
+
function aaptTools() {
|
|
1207
1305
|
const tools = [];
|
|
1208
1306
|
const sdkDir = process.env.ANDROID_HOME ?? path.join(os.homedir(), "Library/Android/sdk");
|
|
1209
1307
|
const btDir = path.join(sdkDir, "build-tools");
|
|
@@ -1211,6 +1309,11 @@ function fromAapt(artifactPath) {
|
|
|
1211
1309
|
const p = path.join(btDir, bt, tool);
|
|
1212
1310
|
if (fs.existsSync(p)) tools.push(p);
|
|
1213
1311
|
}
|
|
1312
|
+
return tools;
|
|
1313
|
+
}
|
|
1314
|
+
/** APK:aapt2/aapt dump badging(versionCode/versionName) */
|
|
1315
|
+
function fromAapt(artifactPath) {
|
|
1316
|
+
const tools = aaptTools();
|
|
1214
1317
|
for (const tool of tools) {
|
|
1215
1318
|
const r = spawnSync(tool, [
|
|
1216
1319
|
"dump",
|
|
@@ -1231,4 +1334,4 @@ function fromAapt(artifactPath) {
|
|
|
1231
1334
|
}
|
|
1232
1335
|
}
|
|
1233
1336
|
//#endregion
|
|
1234
|
-
export {
|
|
1337
|
+
export { readJson as A, looseSemver as B, rnFramework as C, deps as D, tauriFramework as E, commitsSince as F, tagReleaseVersion as H, git as I, isGitRepo as L, subdirs as M, collectReleaseDiff as N, detectBundleIds as O, routeDelivery as P, latestSemverTag as R, rnAdapter as S, tauriAdapter as T, statusShort as V, nativeAndroidFramework as _, assertBetaVersionSupported as a, nativeIosAdapter as b, readProjectVersions as c, electronAdapter as d, electronFramework as f, nativeAndroidAdapter as g, knownFrameworkAdapters as h, PLATFORM_VERSION_CAPS as i, resolveFramework as j, findArtifacts as k, writeProjectVersions as l, flutterFramework as m, readArtifactVersion as n, betaVersionName as o, flutterAdapter as p, DEFAULT_BETA_VERSION_CONFIG as r, checkVersionNameShape as s, readArtifactBuildTime as t, redactText as u, nativeHarmonyAdapter as v, suggestFramework as w, nativeIosFramework as x, nativeHarmonyFramework as y, latestVersionAnchor as z };
|
|
@@ -184,6 +184,8 @@ declare const BetaConfigSchema: z.ZodObject<{
|
|
|
184
184
|
submit: z.ZodDefault<z.ZodBoolean>;
|
|
185
185
|
group: z.ZodOptional<z.ZodString>;
|
|
186
186
|
testType: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<3>, z.ZodLiteral<4>]>>;
|
|
187
|
+
privacyPolicy: z.ZodOptional<z.ZodString>;
|
|
188
|
+
appDesc: z.ZodOptional<z.ZodString>;
|
|
187
189
|
cleanup: z.ZodDefault<z.ZodBoolean>;
|
|
188
190
|
}, z.core.$strip>>;
|
|
189
191
|
testflight: z.ZodOptional<z.ZodObject<{
|
|
@@ -297,6 +299,8 @@ declare const ProjectConfigSchema: z.ZodObject<{
|
|
|
297
299
|
submit: z.ZodDefault<z.ZodBoolean>;
|
|
298
300
|
group: z.ZodOptional<z.ZodString>;
|
|
299
301
|
testType: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<3>, z.ZodLiteral<4>]>>;
|
|
302
|
+
privacyPolicy: z.ZodOptional<z.ZodString>;
|
|
303
|
+
appDesc: z.ZodOptional<z.ZodString>;
|
|
300
304
|
cleanup: z.ZodDefault<z.ZodBoolean>;
|
|
301
305
|
}, z.core.$strip>>;
|
|
302
306
|
testflight: z.ZodOptional<z.ZodObject<{
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as ProjectConfigSchema, A as routeDelivery, B as appendEntry, C as resolvePlugins, Ct as readJson, D as PublishContext, E as FrameworkContext, F as runSubmit, G as BetaVersionConfigSchema, H as BetaConfig, I as HISTORY_PATH, J as CredentialsProfile, K as CredentialsFile, L as HistoryEntry, M as PipelineSummary, N as PipelineSummaryEntry, O as UpdateProvider, P as runStage, Q as ProjectConfig, R as HistoryEvent, S as defineConfig, St as findArtifacts, T as DeliveryRoute, Tt as subdirs, U as BetaConfigSchema, V as readEntries, W as BetaVersionConfig, X as GlobalConfig, Y as CredentialsProfileSchema, Z as GlobalConfigSchema, _ as AppliftPlugin, _t as BundleIds, a as knownFrameworkAdapters, at as VersionCodeConfigSchema, b as PluginHookName, bt as deps, c as nativeHarmonyAdapter, ct as Channel, d as nativeIosFramework, dt as ChannelEvent, et as StoreConfig, f as rnAdapter, ft as ChannelRegistry, g as tauriFramework, gt as SubmitResult, h as tauriAdapter, ht as StageResult, i as flutterFramework, it as VersionCodeConfig, j as PipelineInput, k as collectReleaseDiff, l as nativeHarmonyFramework, lt as ChannelCapabilities, m as suggestFramework, mt as ReviewStatus, n as electronFramework, nt as Stores, o as nativeAndroidAdapter, ot as VersionConfig, p as rnFramework, pt as ReleasePlanEntry, q as CredentialsFileSchema, r as flutterAdapter, rt as StoresSchema, s as nativeAndroidFramework, st as VersionConfigSchema, t as electronAdapter, tt as StoreConfigSchema, u as nativeIosAdapter, ut as ChannelContext, v as AppliftUserConfig, vt as FrameworkAdapter, w as DeliveryJudgement, wt as resolveFramework, x as PluginHost, xt as detectBundleIds, y as HookContext, yt as Platform, z as HistoryQuery } from "./frameworks-
|
|
1
|
+
import { $ as ProjectConfigSchema, A as routeDelivery, B as appendEntry, C as resolvePlugins, Ct as readJson, D as PublishContext, E as FrameworkContext, F as runSubmit, G as BetaVersionConfigSchema, H as BetaConfig, I as HISTORY_PATH, J as CredentialsProfile, K as CredentialsFile, L as HistoryEntry, M as PipelineSummary, N as PipelineSummaryEntry, O as UpdateProvider, P as runStage, Q as ProjectConfig, R as HistoryEvent, S as defineConfig, St as findArtifacts, T as DeliveryRoute, Tt as subdirs, U as BetaConfigSchema, V as readEntries, W as BetaVersionConfig, X as GlobalConfig, Y as CredentialsProfileSchema, Z as GlobalConfigSchema, _ as AppliftPlugin, _t as BundleIds, a as knownFrameworkAdapters, at as VersionCodeConfigSchema, b as PluginHookName, bt as deps, c as nativeHarmonyAdapter, ct as Channel, d as nativeIosFramework, dt as ChannelEvent, et as StoreConfig, f as rnAdapter, ft as ChannelRegistry, g as tauriFramework, gt as SubmitResult, h as tauriAdapter, ht as StageResult, i as flutterFramework, it as VersionCodeConfig, j as PipelineInput, k as collectReleaseDiff, l as nativeHarmonyFramework, lt as ChannelCapabilities, m as suggestFramework, mt as ReviewStatus, n as electronFramework, nt as Stores, o as nativeAndroidAdapter, ot as VersionConfig, p as rnFramework, pt as ReleasePlanEntry, q as CredentialsFileSchema, r as flutterAdapter, rt as StoresSchema, s as nativeAndroidFramework, st as VersionConfigSchema, t as electronAdapter, tt as StoreConfigSchema, u as nativeIosAdapter, ut as ChannelContext, v as AppliftUserConfig, vt as FrameworkAdapter, w as DeliveryJudgement, wt as resolveFramework, x as PluginHost, xt as detectBundleIds, y as HookContext, yt as Platform, z as HistoryQuery } from "./frameworks-B-t5Ywma.mjs";
|
|
2
2
|
//#region src/registry.d.ts
|
|
3
3
|
export declare class DefaultChannelRegistry implements ChannelRegistry {
|
|
4
4
|
private readonly channels;
|
|
@@ -766,5 +766,11 @@ export interface ArtifactVersion {
|
|
|
766
766
|
source: string;
|
|
767
767
|
}
|
|
768
768
|
export declare function readArtifactVersion(artifactPath: string): ArtifactVersion | undefined;
|
|
769
|
+
/** 产物 pushy 构建时间戳读取(buildTime 与设备上报必须精确一致,读不出返回 undefined,
|
|
770
|
+
* 由调用方决定拒绝上传而非猜测)。
|
|
771
|
+
* .hap/.app:包内(.app 可能嵌套 hap)resources/rawfile/meta.json 的 pushy_build_time;
|
|
772
|
+
* .apk:AndroidManifest meta-data pushy_build_time(aapt2/aapt xmltree);
|
|
773
|
+
* .ipa:Payload/*.app/pushy_build_time.txt(官方 Xcode 构建 phase 产物)。 */
|
|
774
|
+
export declare function readArtifactBuildTime(artifactPath: string): string | undefined;
|
|
769
775
|
//#endregion
|
|
770
776
|
export { AppliftPlugin, AppliftUserConfig, BetaConfig, BetaConfigSchema, BetaVersionConfig, BetaVersionConfigSchema, BundleIds, Channel, ChannelCapabilities, ChannelContext, ChannelEvent, ChannelRegistry, CredentialsFile, CredentialsFileSchema, CredentialsProfile, CredentialsProfileSchema, DeliveryJudgement, DeliveryRoute, FrameworkAdapter, FrameworkContext, GlobalConfig, GlobalConfigSchema, HISTORY_PATH, HistoryEntry, HistoryEvent, HistoryQuery, HookContext, PipelineInput, PipelineSummary, PipelineSummaryEntry, Platform, PluginHookName, PluginHost, ProjectConfig, ProjectConfigSchema, PublishContext, ReleasePlanEntry, ReviewStatus, StageResult, StoreConfig, StoreConfigSchema, Stores, StoresSchema, SubmitResult, UpdateProvider, VersionCodeConfig, VersionCodeConfigSchema, VersionConfig, VersionConfigSchema, appendEntry, collectReleaseDiff, defineConfig, deps, detectBundleIds, electronAdapter, electronFramework, findArtifacts, flutterAdapter, flutterFramework, knownFrameworkAdapters, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, readEntries, readJson, resolveFramework, resolvePlugins, rnAdapter, rnFramework, routeDelivery, runStage, runSubmit, subdirs, suggestFramework, tauriAdapter, tauriFramework };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as readJson, B as looseSemver, C as rnFramework, D as deps, E as tauriFramework, F as commitsSince, H as tagReleaseVersion, I as git, L as isGitRepo, M as subdirs, N as collectReleaseDiff, O as detectBundleIds, P as routeDelivery, R as latestSemverTag, S as rnAdapter, T as tauriAdapter, V as statusShort, _ as nativeAndroidFramework, a as assertBetaVersionSupported, b as nativeIosAdapter, c as readProjectVersions, d as electronAdapter, f as electronFramework, g as nativeAndroidAdapter, h as knownFrameworkAdapters, i as PLATFORM_VERSION_CAPS, j as resolveFramework, k as findArtifacts, l as writeProjectVersions, m as flutterFramework, n as readArtifactVersion, o as betaVersionName, p as flutterAdapter, r as DEFAULT_BETA_VERSION_CONFIG, s as checkVersionNameShape, t as readArtifactBuildTime, u as redactText, v as nativeHarmonyAdapter, w as suggestFramework, x as nativeIosFramework, y as nativeHarmonyFramework, z as latestVersionAnchor } from "./artifact-D3BSnmqY.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -92,6 +92,18 @@ const BetaConfigSchema = z.object({
|
|
|
92
92
|
/** 3=邀请测试(默认)4=公开测试 */
|
|
93
93
|
testType: z.union([z.literal(3), z.literal(4)]).default(3),
|
|
94
94
|
/**
|
|
95
|
+
* 隐私政策 URL(提审必填:AGC Testing API 校验 extInfo.privacyPolicy,
|
|
96
|
+
* 控制台对应版本创建时的「自定义协议」步骤;缺失提审报 204144692
|
|
97
|
+
* privacyPolicy is necessary——2026-10-25 qy-driver 实测)。透传 target.privacyPolicy。
|
|
98
|
+
*/
|
|
99
|
+
privacyPolicy: z.string().optional(),
|
|
100
|
+
/**
|
|
101
|
+
* 测试版本描述(languages[].appDesc):AGC 校验 appDesc/newFeatures/线上 briefInfo
|
|
102
|
+
* 三者不得相同(2026-10-25 实测),appDesc 与 newFeatures(--note)来源必须互异。
|
|
103
|
+
* 未配置时用通用基线文案;透传 target.appDesc。
|
|
104
|
+
*/
|
|
105
|
+
appDesc: z.string().optional(),
|
|
106
|
+
/**
|
|
95
107
|
* 发布前自动清理旧测试版本(stop+delete,默认 true):
|
|
96
108
|
* AGC 测试版本在审/在架数量有上限(在审超限提交报 204144692、在架邀请测试 3 个),
|
|
97
109
|
* 旧版本不清理会阻塞新版本提审。清理只移除 AGC 在架记录——已装设备与热更均不受影响,
|
|
@@ -2550,7 +2562,7 @@ var AgcHarmonyChannel = class {
|
|
|
2550
2562
|
"1003": "client_id/client_secret 无效(AGC → 项目设置 → 常规 → API Client 重新获取)",
|
|
2551
2563
|
"204144702": "签名/证书不匹配:检查签名证书指纹(SHA256)与 AGC 后台登记是否一致",
|
|
2552
2564
|
"204144677": "bundleName 与应用不匹配:确认 appId 对应的应用包名",
|
|
2553
|
-
"204144692": "提审前置校验失败(按 msg
|
|
2565
|
+
"204144692": "提审前置校验失败(按 msg 对症,2026-10-25 实测):privacyPolicy → 配置 beta.agc.privacyPolicy(Testing API extInfo.privacyPolicy,控制台对应版本创建的「自定义协议」);displayArea → 邀请测试必填测试专区(CLI 已默认携带,仍报则到控制台核对版本);count of harmony test in audit → 在审测试版本超限(beta.agc.cleanup 默认已自动清理,仍出现请到控制台核对是否有删不掉的旧测试版本)"
|
|
2554
2566
|
};
|
|
2555
2567
|
async authHeaders(ctx) {
|
|
2556
2568
|
const clientId = required$1(ctx, "AGC_CLIENT_ID");
|
|
@@ -2934,6 +2946,10 @@ var AgcHarmonyChannel = class {
|
|
|
2934
2946
|
}, "添加测试软件包")).pkgVersion?.[0] ?? "";
|
|
2935
2947
|
if (!pkgId) throw new Error("AGC 添加测试软件包未返回 pkgVersion");
|
|
2936
2948
|
await this.awaitCompile(ctx, appId, pkgId, headers);
|
|
2949
|
+
const privacyPolicy = ctx.target.privacyPolicy?.trim();
|
|
2950
|
+
const note = ctx.updateDescription ?? "applift 测试发布";
|
|
2951
|
+
const appDesc = (ctx.target.appDesc?.trim() || "内测验证版本(internal test build),更新内容以新特性说明为准。").slice(0, 100);
|
|
2952
|
+
const newFeatures = note.slice(0, 100);
|
|
2937
2953
|
await agcJson(`${BASE}/publish/v2/test/app/version?appId=${encodeURIComponent(appId)}`, {
|
|
2938
2954
|
method: "PUT",
|
|
2939
2955
|
headers: {
|
|
@@ -2942,7 +2958,13 @@ var AgcHarmonyChannel = class {
|
|
|
2942
2958
|
},
|
|
2943
2959
|
body: JSON.stringify({
|
|
2944
2960
|
versionId,
|
|
2945
|
-
pkgId
|
|
2961
|
+
pkgId,
|
|
2962
|
+
...privacyPolicy ? { extInfo: { privacyPolicy } } : {},
|
|
2963
|
+
languages: [{
|
|
2964
|
+
language: "zh-CN",
|
|
2965
|
+
appDesc,
|
|
2966
|
+
newFeatures
|
|
2967
|
+
}]
|
|
2946
2968
|
})
|
|
2947
2969
|
}, "绑定测试软件包");
|
|
2948
2970
|
if (ctx.target.submitTest === "true") {
|
|
@@ -2962,10 +2984,13 @@ var AgcHarmonyChannel = class {
|
|
|
2962
2984
|
openTestInfo: {
|
|
2963
2985
|
startTime: now,
|
|
2964
2986
|
endTime: now + 2592e6,
|
|
2965
|
-
testTaskInfo: {
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2987
|
+
testTaskInfo: {
|
|
2988
|
+
groupInfos: [{
|
|
2989
|
+
groupId,
|
|
2990
|
+
groupName
|
|
2991
|
+
}],
|
|
2992
|
+
displayArea: "1"
|
|
2993
|
+
}
|
|
2969
2994
|
}
|
|
2970
2995
|
})
|
|
2971
2996
|
}, "绑定测试群组");
|
|
@@ -3069,9 +3094,11 @@ var AgcHarmonyChannel = class {
|
|
|
3069
3094
|
body: JSON.stringify({ versionId: vid })
|
|
3070
3095
|
}, "停止测试版本");
|
|
3071
3096
|
} catch (e) {
|
|
3097
|
+
const msg = e.message;
|
|
3098
|
+
const hint = msg.includes("state is 9998") ? "——该版本在审中,AGC 不允许停/删:到控制台撤回该审核或等审毕后下次发版自动清理" : "";
|
|
3072
3099
|
ctx.emit({
|
|
3073
3100
|
type: "warn",
|
|
3074
|
-
message: `停止测试版本 ${label}失败(继续尝试删除): ${
|
|
3101
|
+
message: `停止测试版本 ${label}失败(继续尝试删除): ${msg}${hint}`
|
|
3075
3102
|
});
|
|
3076
3103
|
}
|
|
3077
3104
|
try {
|
|
@@ -4750,4 +4777,4 @@ function applyBump(cwd, plan, framework, opts) {
|
|
|
4750
4777
|
}
|
|
4751
4778
|
}
|
|
4752
4779
|
//#endregion
|
|
4753
|
-
export { APPLIFT_HOME, AgcHarmonyChannel, AscChannel, BetaConfigSchema, BetaVersionConfigSchema, CREDENTIALS_PATH, CredentialsFileSchema, CredentialsProfileSchema, DEFAULT_BETA_VERSION_CONFIG, DefaultChannelRegistry, GLOBAL_CONFIG_PATH, GlobalConfigSchema, GooglePlayChannel, HISTORY_PATH, HonorChannel, HuaweiAndroidChannel, OppoChannel, PLATFORM_VERSION_CAPS, PROJECTS_MAP_PATH, PgyerChannel, PluginHost, ProjectConfigSchema, StoreConfigSchema, StoresSchema, VersionCodeConfigSchema, VersionConfigSchema, VivoChannel, WAIT_BEFORE_SUBMIT_MS, XiaomiChannel, YybChannel, appendEntry, applyBump, assertBetaVersionSupported, assertListingFiles, betaVersionName, checkVersionNameShape, collectReleaseDiff, commitsSince, compareDeclared, decideNextVersion, defineConfig, deps, detectBundleIds, electronAdapter, electronFramework, evalVersionCodeFormula, findArtifacts, findUp, flutterAdapter, flutterFramework, formPost, getAgcToken, getHarmonyAppId, git, hmacSign, humanizeError, inferBumpLevel, isGitRepo, knownFrameworkAdapters, latestSemverTag, latestVersionAnchor, loadCredentials, loadCredentialsLayered, loadGlobalConfig, loadListingFile, loadProjectConfig, loadProjectProfileMap, looseSemver, md5File, md5String, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, nextVersionCode, planBump, projectCredentialsPath, readArtifactVersion, readEntries, readJson, readProjectVersions, redactText, registry, renderChangelogSection, resolveFramework, resolveListing, resolvePlugins, resolveProfile, resolveProfileFor, resolveProfileSource, rnAdapter, rnFramework, routeDelivery, runStage, runSubmit, saveCredentials, saveProjectProfileMap, setProjectProfile, sha256File, sortedQueryString, statusShort, storeVersionName, subdirs, suggestFramework, tagReleaseVersion, tauriAdapter, tauriFramework, toChangelogEntries, tsMillis, tsSeconds, upsertChangelog, writeProjectVersions };
|
|
4780
|
+
export { APPLIFT_HOME, AgcHarmonyChannel, AscChannel, BetaConfigSchema, BetaVersionConfigSchema, CREDENTIALS_PATH, CredentialsFileSchema, CredentialsProfileSchema, DEFAULT_BETA_VERSION_CONFIG, DefaultChannelRegistry, GLOBAL_CONFIG_PATH, GlobalConfigSchema, GooglePlayChannel, HISTORY_PATH, HonorChannel, HuaweiAndroidChannel, OppoChannel, PLATFORM_VERSION_CAPS, PROJECTS_MAP_PATH, PgyerChannel, PluginHost, ProjectConfigSchema, StoreConfigSchema, StoresSchema, VersionCodeConfigSchema, VersionConfigSchema, VivoChannel, WAIT_BEFORE_SUBMIT_MS, XiaomiChannel, YybChannel, appendEntry, applyBump, assertBetaVersionSupported, assertListingFiles, betaVersionName, checkVersionNameShape, collectReleaseDiff, commitsSince, compareDeclared, decideNextVersion, defineConfig, deps, detectBundleIds, electronAdapter, electronFramework, evalVersionCodeFormula, findArtifacts, findUp, flutterAdapter, flutterFramework, formPost, getAgcToken, getHarmonyAppId, git, hmacSign, humanizeError, inferBumpLevel, isGitRepo, knownFrameworkAdapters, latestSemverTag, latestVersionAnchor, loadCredentials, loadCredentialsLayered, loadGlobalConfig, loadListingFile, loadProjectConfig, loadProjectProfileMap, looseSemver, md5File, md5String, nativeAndroidAdapter, nativeAndroidFramework, nativeHarmonyAdapter, nativeHarmonyFramework, nativeIosAdapter, nativeIosFramework, nextVersionCode, planBump, projectCredentialsPath, readArtifactBuildTime, readArtifactVersion, readEntries, readJson, readProjectVersions, redactText, registry, renderChangelogSection, resolveFramework, resolveListing, resolvePlugins, resolveProfile, resolveProfileFor, resolveProfileSource, rnAdapter, rnFramework, routeDelivery, runStage, runSubmit, saveCredentials, saveProjectProfileMap, setProjectProfile, sha256File, sortedQueryString, statusShort, storeVersionName, subdirs, suggestFramework, tagReleaseVersion, tauriAdapter, tauriFramework, toChangelogEntries, tsMillis, tsSeconds, upsertChangelog, writeProjectVersions };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as FrameworkContext, O as UpdateProvider, W as BetaVersionConfig, _ as AppliftPlugin, a as knownFrameworkAdapters, c as nativeHarmonyAdapter, d as nativeIosFramework, f as rnAdapter, g as tauriFramework, h as tauriAdapter, i as flutterFramework, l as nativeHarmonyFramework, m as suggestFramework, n as electronFramework, o as nativeAndroidAdapter, p as rnFramework, r as flutterAdapter, s as nativeAndroidFramework, t as electronAdapter, u as nativeIosAdapter, w as DeliveryJudgement } from "../frameworks-
|
|
1
|
+
import { E as FrameworkContext, O as UpdateProvider, W as BetaVersionConfig, _ as AppliftPlugin, a as knownFrameworkAdapters, c as nativeHarmonyAdapter, d as nativeIosFramework, f as rnAdapter, g as tauriFramework, h as tauriAdapter, i as flutterFramework, l as nativeHarmonyFramework, m as suggestFramework, n as electronFramework, o as nativeAndroidAdapter, p as rnFramework, r as flutterAdapter, s as nativeAndroidFramework, t as electronAdapter, u as nativeIosAdapter, w as DeliveryJudgement } from "../frameworks-B-t5Ywma.mjs";
|
|
2
2
|
//#region src/plugins/dingtalk-notify.d.ts
|
|
3
3
|
interface DingtalkNotifyOptions {
|
|
4
4
|
webhook: string;
|
|
@@ -32,8 +32,9 @@ interface PushyCli {
|
|
|
32
32
|
}): Promise<{
|
|
33
33
|
versionId: number;
|
|
34
34
|
}>;
|
|
35
|
-
/** 上传原生基线(versionName
|
|
36
|
-
|
|
35
|
+
/** 上传原生基线(versionName 与 buildTime 均由调用方从产物内读取后显式传入;
|
|
36
|
+
* buildTime 必须与设备上报的编译时间戳精确一致,读不出时调用方应拒绝上传。deps 同 publish) */
|
|
37
|
+
uploadApp(appId: number, appFile: string, versionName: string, deps: Record<string, string>, buildTime: string): Promise<{
|
|
37
38
|
packageId: number;
|
|
38
39
|
version: string;
|
|
39
40
|
}>;
|
|
@@ -44,12 +45,24 @@ interface PushyCli {
|
|
|
44
45
|
packageVersion: string;
|
|
45
46
|
rollout?: number;
|
|
46
47
|
}): Promise<void>;
|
|
47
|
-
/**
|
|
48
|
+
/** 版本列表(取号与状态展示用)。packageVersion:该热更绑定的原生基线版本名
|
|
49
|
+
* (基线自动替换的安全判据;服务端未回显时字段缺省,调用方按无法确认处理) */
|
|
48
50
|
versions(appId: number): Promise<Array<{
|
|
49
51
|
id: number;
|
|
50
52
|
hash: string;
|
|
51
53
|
name: string;
|
|
54
|
+
packageVersion?: string;
|
|
52
55
|
}>>;
|
|
56
|
+
/** 基线包列表(GET /app/:id/package/list;409 自动替换的发现手段) */
|
|
57
|
+
packages(appId: number): Promise<Array<{
|
|
58
|
+
id: number;
|
|
59
|
+
hash: string;
|
|
60
|
+
name: string;
|
|
61
|
+
status: string;
|
|
62
|
+
}>>;
|
|
63
|
+
/** 删除基线包(DELETE /app/:id/package/:packageId,2026-10-25 实测端点存在)。
|
|
64
|
+
* 调用方必须先确认该基线无热更版本绑定(删除被绑定的基线会孤儿化热更)。 */
|
|
65
|
+
deletePackage(appId: number, packageId: number): Promise<void>;
|
|
53
66
|
}
|
|
54
67
|
/** credentials.json 中的 pushy token 键名 */
|
|
55
68
|
export declare const PUSHY_TOKEN_KEY = "PUSHY_API_TOKEN";
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as rnFramework, E as tauriFramework, N as collectReleaseDiff, S as rnAdapter, T as tauriAdapter, _ as nativeAndroidFramework, a as assertBetaVersionSupported, b as nativeIosAdapter, c as readProjectVersions, d as electronAdapter, f as electronFramework, g as nativeAndroidAdapter, h as knownFrameworkAdapters, k as findArtifacts, m as flutterFramework, n as readArtifactVersion, o as betaVersionName, p as flutterAdapter, r as DEFAULT_BETA_VERSION_CONFIG, t as readArtifactBuildTime, u as redactText, v as nativeHarmonyAdapter, w as suggestFramework, x as nativeIosFramework, y as nativeHarmonyFramework } from "../artifact-D3BSnmqY.mjs";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createHmac } from "node:crypto";
|
|
@@ -62,9 +62,11 @@ function dingtalkNotify(options) {
|
|
|
62
62
|
* cresc/自建服务差异仅在 baseUrl(同一套服务端代码),serverUrl 由 rnUpdate 配置注入。
|
|
63
63
|
* uploadApp 相对官方 CLI 的有意降级(记录在案):传原始产物而非 slim 包、不带 bundleHash/
|
|
64
64
|
* bytecodeVersion/bundleLocation(服务端无法将该基线用作 hermes-base 或 package-origin diff)、
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
|
|
65
|
+
* 不校验包内 appId 与目标 app 一致(配错 appId 会传到别的 app——由配置审查保证)、
|
|
66
|
+
* 不做 maxSize 预检(超限撞对象存储错误)。需要 hermes-base 能力时在此补齐。
|
|
67
|
+
* buildTime 已对齐官方语义:由调用方从产物内提取真实构建时间戳传入(2026-10-26 qy-driver
|
|
68
|
+
* 实证:服务端按 buildTime 精确匹配设备上报,写入上传时刻会让该基线下的设备全部
|
|
69
|
+
* checkUpdate 吃「编译时间戳不匹配」+ 封锁 6h,热更永远发不下去)。 */
|
|
68
70
|
/** credentials.json 中的 pushy token 键名 */
|
|
69
71
|
const PUSHY_TOKEN_KEY = "PUSHY_API_TOKEN";
|
|
70
72
|
/** pushy 官方 API 根(官方 CLI 默认端点簇的主端点) */
|
|
@@ -94,7 +96,9 @@ async function query(f, baseUrl, token, api, init) {
|
|
|
94
96
|
}
|
|
95
97
|
if (!res.ok) {
|
|
96
98
|
const msg = json?.message || res.statusText || `HTTP ${res.status}`;
|
|
97
|
-
|
|
99
|
+
const err = /* @__PURE__ */ new Error(res.status === 401 ? `pushy API 鉴权失败(token 无效或过期):请更新 credentials.json 的 ${PUSHY_TOKEN_KEY}` : `pushy API ${api} 失败(HTTP ${res.status}):${msg}`);
|
|
100
|
+
err.status = res.status;
|
|
101
|
+
throw err;
|
|
98
102
|
}
|
|
99
103
|
return json ?? {};
|
|
100
104
|
}
|
|
@@ -243,14 +247,14 @@ function createPushyApi(opts) {
|
|
|
243
247
|
await bind(q, input.appId, id, input.packageVersion, input.rollout);
|
|
244
248
|
return { versionId: id };
|
|
245
249
|
},
|
|
246
|
-
async uploadApp(appId, appFile, versionName, deps) {
|
|
250
|
+
async uploadApp(appId, appFile, versionName, deps, buildTime) {
|
|
247
251
|
const hash = await uploadFile(f, baseUrl, opts.token, appId, appFile, opts.httpUpload);
|
|
248
252
|
const { id } = await q(`/app/${appId}/package/create`, {
|
|
249
253
|
method: "POST",
|
|
250
254
|
body: JSON.stringify({
|
|
251
255
|
name: versionName,
|
|
252
256
|
hash,
|
|
253
|
-
buildTime
|
|
257
|
+
buildTime,
|
|
254
258
|
deps
|
|
255
259
|
})
|
|
256
260
|
});
|
|
@@ -271,11 +275,31 @@ function createPushyApi(opts) {
|
|
|
271
275
|
for (const v of data) out.push({
|
|
272
276
|
id: v.id,
|
|
273
277
|
hash: v.hash ?? "",
|
|
274
|
-
name: v.name
|
|
278
|
+
name: v.name,
|
|
279
|
+
...v.packageVersion !== void 0 ? { packageVersion: v.packageVersion } : {}
|
|
280
|
+
});
|
|
281
|
+
if (data.length < limit) break;
|
|
282
|
+
}
|
|
283
|
+
return out;
|
|
284
|
+
},
|
|
285
|
+
async packages(appId) {
|
|
286
|
+
const out = [];
|
|
287
|
+
const limit = 100;
|
|
288
|
+
for (let offset = 0; offset < 1e4; offset += limit) {
|
|
289
|
+
const { data } = await q(`/app/${appId}/package/list?offset=${offset}&limit=${limit}`);
|
|
290
|
+
if (!data?.length) break;
|
|
291
|
+
for (const p of data) out.push({
|
|
292
|
+
id: p.id,
|
|
293
|
+
hash: p.hash ?? "",
|
|
294
|
+
name: p.name,
|
|
295
|
+
status: p.status ?? ""
|
|
275
296
|
});
|
|
276
297
|
if (data.length < limit) break;
|
|
277
298
|
}
|
|
278
299
|
return out;
|
|
300
|
+
},
|
|
301
|
+
async deletePackage(appId, packageId) {
|
|
302
|
+
await q(`/app/${appId}/package/${packageId}`, { method: "DELETE" });
|
|
279
303
|
}
|
|
280
304
|
};
|
|
281
305
|
}
|
|
@@ -721,11 +745,27 @@ function rnUpdate(opts = {}, cli) {
|
|
|
721
745
|
try {
|
|
722
746
|
const versionName = readArtifactVersion(result.artifactPath)?.versionName;
|
|
723
747
|
if (!versionName) throw new Error(`未能从产物读出 versionName:${result.artifactPath}(readArtifactVersion 不支持该格式?)`);
|
|
748
|
+
const buildTime = readArtifactBuildTime(result.artifactPath);
|
|
749
|
+
if (!buildTime) throw new Error(`未能从产物读出 pushy 构建时间戳:${result.artifactPath}(包内缺 meta.json / pushy_build_time?请人工用 pushy CLI 补传基线)`);
|
|
724
750
|
const appId = platformAppId(opts, platform, result.target ?? baselineChannel(versionName, platform, hookCtx.cwd));
|
|
725
751
|
const key = `${platform}:${versionName}`;
|
|
726
752
|
if (uploadedBaselines.has(key)) return;
|
|
727
753
|
uploadedBaselines.add(key);
|
|
728
|
-
|
|
754
|
+
const pushy = resolvePushyClient(opts, cli, hookCtx.credentials);
|
|
755
|
+
try {
|
|
756
|
+
await pushy.uploadApp(appId, result.artifactPath, versionName, readDepVersions(hookCtx.cwd), buildTime);
|
|
757
|
+
} catch (e) {
|
|
758
|
+
if (e.status !== 409) throw e;
|
|
759
|
+
const sameName = (await pushy.packages(appId)).filter((p) => p.name === versionName);
|
|
760
|
+
if (sameName.length === 0) throw new Error(`基线 409 但未发现同名基线(hash 重复?):${versionName}——请人工核对 pushy 后台`);
|
|
761
|
+
const vers = await pushy.versions(appId);
|
|
762
|
+
const bound = vers.filter((v) => v.packageVersion === versionName || v.packageVersion === void 0 && sameName.some((p) => v.hash === p.hash && v.name === versionName));
|
|
763
|
+
if (vers.length > 0 && bound.length > 0) throw new Error(`基线 ${versionName} 已绑定 ${bound.length} 个热更版本,自动替换会使热更孤儿化——请人工处理(pushy 后台迁移热更或删除后重发)`);
|
|
764
|
+
if (vers.length > 0 && vers.every((v) => v.packageVersion === void 0)) throw new Error(`服务端未回显热更绑定关系,无法确认 ${versionName} 基线可安全替换——请人工核对后删除重传`);
|
|
765
|
+
for (const p of sameName) await pushy.deletePackage(appId, p.id);
|
|
766
|
+
process.stderr.write(`⚠ pushy 基线 ${versionName} 内容已变(同版本名重建),自动删除旧基线 ${sameName.map((p) => `#${p.id}(${p.hash})`).join(",")} 并重传\n`);
|
|
767
|
+
await pushy.uploadApp(appId, result.artifactPath, versionName, readDepVersions(hookCtx.cwd), buildTime);
|
|
768
|
+
}
|
|
729
769
|
} catch (e) {
|
|
730
770
|
uploadedBaselines.delete(`${platform}:${readArtifactVersion(result.artifactPath)?.versionName ?? ""}`);
|
|
731
771
|
process.stderr.write(`⚠ pushy 基线上传失败(请人工补传):${e.message}\n`);
|