@cloudbase/manager-node 5.6.8 → 5.7.0-beta.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/lib/cloudApp/index.js +12 -3
  3. package/lib/deploy/DatabaseDeployer.js +238 -0
  4. package/lib/deploy/DeployOrchestrator.js +564 -0
  5. package/lib/deploy/FunctionDeployer.js +611 -0
  6. package/lib/deploy/GatewayDeployer.js +522 -0
  7. package/lib/deploy/StateStore.js +327 -0
  8. package/lib/deploy/StaticDeployer.js +289 -0
  9. package/lib/deploy/domain.js +39 -0
  10. package/lib/deploy/framework.js +105 -0
  11. package/lib/deploy/function/artifact.js +207 -0
  12. package/lib/deploy/function/builders/cloud.js +454 -0
  13. package/lib/deploy/function/cam-preflight.js +157 -0
  14. package/lib/deploy/function/cloud-build-service.js +170 -0
  15. package/lib/deploy/function/config-guard.js +588 -0
  16. package/lib/deploy/function/docker-preflight.js +87 -0
  17. package/lib/deploy/function/image-preflight.js +164 -0
  18. package/lib/deploy/function/local-builder.js +110 -0
  19. package/lib/deploy/function/planner.js +282 -0
  20. package/lib/deploy/function/preflight.js +264 -0
  21. package/lib/deploy/types.js +99 -0
  22. package/lib/environment.js +11 -0
  23. package/lib/hosting/index.js +4 -1
  24. package/lib/index.js +31 -0
  25. package/lib/projectValidator/index.js +375 -0
  26. package/lib/projectValidator/types.js +2 -0
  27. package/lib/storage/index.js +6 -7
  28. package/lib/utils/index.js +41 -1
  29. package/package.json +2 -1
  30. package/types/cloudApp/index.d.ts +4 -0
  31. package/types/cloudApp/types.d.ts +87 -6
  32. package/types/deploy/DatabaseDeployer.d.ts +70 -0
  33. package/types/deploy/DeployOrchestrator.d.ts +150 -0
  34. package/types/deploy/FunctionDeployer.d.ts +158 -0
  35. package/types/deploy/GatewayDeployer.d.ts +175 -0
  36. package/types/deploy/StateStore.d.ts +170 -0
  37. package/types/deploy/StaticDeployer.d.ts +104 -0
  38. package/types/deploy/domain.d.ts +17 -0
  39. package/types/deploy/framework.d.ts +23 -0
  40. package/types/deploy/function/artifact.d.ts +40 -0
  41. package/types/deploy/function/builders/cloud.d.ts +110 -0
  42. package/types/deploy/function/cam-preflight.d.ts +51 -0
  43. package/types/deploy/function/cloud-build-service.d.ts +10 -0
  44. package/types/deploy/function/config-guard.d.ts +41 -0
  45. package/types/deploy/function/docker-preflight.d.ts +17 -0
  46. package/types/deploy/function/image-preflight.d.ts +21 -0
  47. package/types/deploy/function/local-builder.d.ts +26 -0
  48. package/types/deploy/function/planner.d.ts +15 -0
  49. package/types/deploy/function/preflight.d.ts +9 -0
  50. package/types/deploy/types.d.ts +429 -0
  51. package/types/env/type.d.ts +4 -4
  52. package/types/environment.d.ts +7 -0
  53. package/types/function/types.d.ts +15 -0
  54. package/types/hosting/index.d.ts +6 -0
  55. package/types/index.d.ts +18 -0
  56. package/types/interfaces/function.interface.d.ts +1 -1
  57. package/types/projectValidator/index.d.ts +24 -0
  58. package/types/projectValidator/types.d.ts +26 -0
  59. package/types/storage/index.d.ts +6 -0
  60. package/types/utils/index.d.ts +13 -0
@@ -0,0 +1,170 @@
1
+ /** hosting 文件指纹(hash + size;size 用于懒加载 diff 预判,避免为未变文件重复读内容) */
2
+ export interface IHostingFileFingerprint {
3
+ hash: string;
4
+ size: number;
5
+ }
6
+ /** 快照中指纹值:兼容旧格式(纯 string = 仅 hash,size 未知) */
7
+ export type HostingFileValue = string | IHostingFileFingerprint;
8
+ /** hosting 状态快照条目(产物指纹,不存文件内容) */
9
+ export interface IHostingStateEntry {
10
+ name: string;
11
+ deployPath?: string;
12
+ /** 相对路径 → 文件指纹(兼容旧格式:纯字符串 = 仅 hash,size 未知) */
13
+ files: Record<string, HostingFileValue>;
14
+ }
15
+ /** hosting 文件级 diff 结果(懒加载:size 预判 + 按需 hash) */
16
+ export interface IHostingFileDiff {
17
+ added: string[];
18
+ modified: string[];
19
+ deleted: string[];
20
+ totalChanged: number;
21
+ /** 本地与快照完全一致(可跳过部署) */
22
+ unchanged: boolean;
23
+ /** true = 文件数超过指纹上限,diff 被放弃,需降级为全量部署 */
24
+ overLimit?: boolean;
25
+ }
26
+ /** hosting 指纹扫描选项 */
27
+ export interface IHostingScanOptions {
28
+ /** 指纹文件数上限:超过则抛 HostingFilesOverLimitError(默认 50000;0 = 不限) */
29
+ maxFiles?: number;
30
+ /** hash 截断长度(hex 位数,默认 16;64 = 完整 sha256) */
31
+ hashLength?: number;
32
+ }
33
+ /** diffHostingFiles 选项(继承扫描选项,追加忽略规则) */
34
+ export interface IHostingDiffOptions extends IHostingScanOptions {
35
+ /** 自定义忽略规则(追加到默认 node_modules / .DS_Store 之后) */
36
+ ignore?: string[];
37
+ }
38
+ /** hosting 指纹文件数超过上限时抛出(触发降级为全量部署) */
39
+ export declare class HostingFilesOverLimitError extends Error {
40
+ fileCount: number;
41
+ limit: number;
42
+ constructor(fileCount: number, limit: number);
43
+ }
44
+ /** 默认指纹文件数上限(防快照膨胀与 I/O 失控) */
45
+ export declare const DEFAULT_MAX_HOSTING_FILES = 50000;
46
+ /** 默认 hash 截断长度(16 位 hex = 64bit,碰撞概率可忽略;快照体积减半) */
47
+ export declare const DEFAULT_HASH_LENGTH = 16;
48
+ /** app 状态快照条目(仅 diff 相关字段,不写 envVariables 等敏感信息) */
49
+ export interface IAppStateEntry {
50
+ serviceName?: string;
51
+ installCommand?: string;
52
+ buildCommand?: string;
53
+ outputDir?: string;
54
+ deployPath?: string;
55
+ }
56
+ /** 部署状态快照(.cloudbase/state.json) */
57
+ export interface IDeployState {
58
+ version: number;
59
+ updatedAt: string;
60
+ gitCommit?: string;
61
+ resources: {
62
+ hosting?: IHostingStateEntry[];
63
+ gateway?: unknown;
64
+ app?: IAppStateEntry;
65
+ };
66
+ }
67
+ interface IStateStoreOptions {
68
+ /** 项目根目录(默认 process.cwd()) */
69
+ cwd?: string;
70
+ /** 环境名(--env production 等):按环境分文件 state.{env}.json */
71
+ env?: string;
72
+ /** 自定义 state 路径(优先于 cwd+env 推导) */
73
+ stateFile?: string;
74
+ }
75
+ /**
76
+ * 部署状态快照(StateStore)
77
+ *
78
+ * 职责:读写 `.cloudbase/state.json`(默认),为 dry-run 的 hosting/app diff 提供本地基准,
79
+ * 避免每次 diff 都拉取云端。
80
+ *
81
+ * 指纹算法:hosting = 产物目录逐文件内容 sha256(相对路径为 key)。
82
+ * 只存 hash 不存内容,体积 = O(文件数);app 快照不写入 envVariables(敏感过滤)。
83
+ */
84
+ export declare class StateStore {
85
+ private cwd;
86
+ private env?;
87
+ private stateFile?;
88
+ constructor(options?: IStateStoreOptions);
89
+ /**
90
+ * 计算 state 文件路径:
91
+ * - 自定义 stateFile 优先
92
+ * - 否则 {cwd}/.cloudbase/state.json(无 env)或 state.{env}.json(多环境隔离)
93
+ */
94
+ getFilePath(): string;
95
+ /**
96
+ * 读取状态快照;文件不存在或 JSON 损坏返回 null(缺失降级,由调用方走云端兜底)
97
+ */
98
+ read(): IDeployState | null;
99
+ /**
100
+ * 写入状态快照(自动补 version/updatedAt/gitCommit,自动创建 .cloudbase 目录)
101
+ */
102
+ write(state: {
103
+ resources: IDeployState['resources'];
104
+ gitCommit?: string;
105
+ }): void;
106
+ /**
107
+ * 计算产物目录逐文件 sha256 指纹(仅 hash,兼容旧调用)
108
+ *
109
+ * @param projectPath 产物目录(hosting 的 outputDir / root)
110
+ * @param ignore 自定义忽略规则(追加到默认 node_modules / .DS_Store 之后)
111
+ * @param options 扫描选项(maxFiles / hashLength)
112
+ * @returns 相对路径(/ 分隔)→ 文件内容 sha256(默认截断 16 位)
113
+ */
114
+ computeHostingFiles(projectPath: string, ignore?: string[], options?: IHostingScanOptions): Promise<Record<string, string>>;
115
+ /**
116
+ * 计算产物目录逐文件指纹(hash + size)
117
+ *
118
+ * - 强制忽略 node_modules / .DS_Store(与传入 ignore 合并,不可关闭)
119
+ * - hash 默认截断为 16 位 hex(hashLength 可调,64 = 完整 sha256)
120
+ * - 文件数超过 maxFiles 抛 HostingFilesOverLimitError(防快照膨胀与 I/O 失控)
121
+ *
122
+ * @param projectPath 产物目录(hosting 的 outputDir / root)
123
+ * @param ignore 自定义忽略规则
124
+ * @param options 扫描选项(maxFiles / hashLength)
125
+ * @returns 相对路径(/ 分隔)→ { hash, size }
126
+ */
127
+ computeHostingFingerprints(projectPath: string, ignore?: string[], options?: IHostingScanOptions): Promise<Record<string, IHostingFileFingerprint>>;
128
+ /**
129
+ * 计算产物目录与快照的变更集(懒加载)
130
+ *
131
+ * 优化:先 stat 拿 size,size 与快照不同的文件直接判定变更(不读文件内容),
132
+ * 只有 size 相同(或旧快照 size 未知)的文件才读内容 hash 对比,
133
+ * 避免为未变文件做无谓的 I/O 与 hash。
134
+ * 文件数超过 maxFiles 时放弃 diff,返回 overLimit=true(调用方应降级为全量部署)。
135
+ *
136
+ * @param projectPath 产物目录(hosting 的 outputDir / root)
137
+ * @param previous 上次快照指纹(undefined = 首次部署,全部视为新增)
138
+ * @param options 选项(ignore / maxFiles / hashLength)
139
+ */
140
+ diffHostingFiles(projectPath: string, previous: Record<string, HostingFileValue> | undefined, options?: IHostingDiffOptions): Promise<IHostingFileDiff>;
141
+ /**
142
+ * 提取 app 配置快照(仅 diff 白名单字段)
143
+ * envVariables / ignore 等非 diff 字段与敏感信息不进入快照
144
+ */
145
+ buildAppConfig(config: {
146
+ serviceName?: string;
147
+ installCommand?: string;
148
+ buildCommand?: string;
149
+ outputDir?: string;
150
+ deployPath?: string;
151
+ [key: string]: unknown;
152
+ }): IAppStateEntry | undefined;
153
+ private hashFile;
154
+ /** 合并默认忽略规则(node_modules / .DS_Store 不可被调用方关闭) */
155
+ private mergeIgnore;
156
+ /** 归一化快照指纹值:旧格式(纯 string = 仅 hash,size 未知用 -1 表示) */
157
+ private normalizeFileValue;
158
+ /**
159
+ * 是否命中忽略规则:
160
+ * - 目录模式(结尾 /):匹配该目录及其下所有
161
+ * - glob(含 **):转换为正则匹配相对路径
162
+ * - 其余:精确/前缀匹配
163
+ */
164
+ private isIgnored;
165
+ private matchPattern;
166
+ private escapeRegExp;
167
+ /** 解析当前 git commit(非 git 仓库或失败返回 undefined,不阻断) */
168
+ private resolveGitCommit;
169
+ }
170
+ export {};
@@ -0,0 +1,104 @@
1
+ import { Environment } from '../environment';
2
+ /** app 声明式配置(cloudbaserc.json app 对象) */
3
+ export interface IAppDeployConfig {
4
+ serviceName?: string;
5
+ root?: string;
6
+ framework?: string;
7
+ installCommand?: string;
8
+ buildCommand?: string;
9
+ outputDir?: string;
10
+ deployPath?: string;
11
+ ignore?: string[];
12
+ envVariables?: Record<string, string | number | boolean>;
13
+ }
14
+ /** hosting 声明式配置(cloudbaserc.json hosting[]) */
15
+ export interface IHostingDeployConfig {
16
+ name?: string;
17
+ root?: string;
18
+ /** 框架类型:显式指定或未配置时读 root/package.json 自动检测;static/custom 表示纯静态(不构建) */
19
+ framework?: string;
20
+ /** 安装命令,默认 npm install;空字符串跳过安装 */
21
+ installCommand?: string;
22
+ /** 构建命令:非空则本地构建后上传;空字符串/未配置且无法检测 → 纯静态直接上传 outputDir */
23
+ buildCommand?: string;
24
+ /** 构建产物目录:有构建时默认 dist,纯静态时默认 root */
25
+ outputDir?: string;
26
+ /** 云端部署路径(决定访问 URL 与网关 PathRewrite.Prefix) */
27
+ deployPath?: string;
28
+ ignore?: string[];
29
+ /** 构建时环境变量(注入本地构建进程,非敏感) */
30
+ envVariables?: Record<string, string | number | boolean>;
31
+ /** SPA 回退:true 时 404 返回 index.html */
32
+ spaFallback?: boolean;
33
+ }
34
+ export interface IStaticDeployResult {
35
+ name: string;
36
+ url?: string;
37
+ /** 是否写入了版本记录(app 写、hosting 不写) */
38
+ wroteRecord: boolean;
39
+ }
40
+ /**
41
+ * app/hosting 声明式部署器
42
+ *
43
+ * app:framework=static → 直传产物 + SkipBuild 写记录(对齐 tcb app deploy 纯静态分支);
44
+ * 其余 framework → 云端构建(上传源码 → 云端构建 → 写版本记录),与现有 tcb app deploy 一致
45
+ * hosting:固定静态流程(buildCommand 非空则本地构建后直传),不写版本记录(现有 tcb hosting deploy 行为)
46
+ */
47
+ export declare class StaticDeployer {
48
+ private environment;
49
+ constructor(environment: Environment);
50
+ /**
51
+ * app 部署(与现有 tcb app deploy 一致)
52
+ *
53
+ * framework=static:直传产物(hosting uploadFiles)+ createApp(SkipBuild) 后台写部署记录,跳过云端构建。
54
+ * 其余 framework:上传源码 ZIP → createApp 云端构建 → 写版本记录。
55
+ */
56
+ deployApp(options: {
57
+ config: IAppDeployConfig;
58
+ cwd?: string;
59
+ }): Promise<IStaticDeployResult>;
60
+ /**
61
+ * hosting 部署(固定静态流程,不写版本记录)
62
+ *
63
+ * 支持本地构建(对齐 Netlify):buildCommand 非空时自动执行 install + build 后上传产物;
64
+ * 纯静态(buildCommand 空/未配置且无法检测框架)时直接上传 outputDir(默认 root,保持现状)。
65
+ * 访问地址 = https://{CdnDomain}{deployPath}(与 tcb hosting deploy 一致)
66
+ */
67
+ deployHosting(options: {
68
+ config: IHostingDeployConfig;
69
+ cwd?: string;
70
+ }): Promise<IStaticDeployResult>;
71
+ /**
72
+ * app 纯静态直传(对齐 tcb app deploy 的 deployStaticApp 分支)
73
+ *
74
+ * 1. hosting uploadFiles 直传产物(文件级上传,立即可访问,无需打 ZIP)
75
+ * 2. 后台异步 createApp(SkipBuild) 写部署记录(失败不影响文件访问)
76
+ * 3. 跳过云端构建轮询,返回访问地址
77
+ */
78
+ private deployAppStatic;
79
+ /**
80
+ * app 云端构建:上传源码 ZIP → createApp 云端构建 → 写版本记录
81
+ */
82
+ private deployAppCloud;
83
+ /**
84
+ * 读取现有静态网站配置并保留 RoutingRules + AutoAddressing
85
+ * (putBucketWebsite 为整体覆盖,设置 SPA 回退前必须带回已有配置,否则会被清空)
86
+ */
87
+ private preserveWebsiteConfig;
88
+ /**
89
+ * 解析 hosting 访问地址:https://{CdnDomain}{deployPath}
90
+ */
91
+ private resolveHostingUrl;
92
+ /**
93
+ * 本地构建(install + build)
94
+ *
95
+ * - installCommand:默认 npm install,显式空字符串跳过安装
96
+ * - buildCommand:由调用方保证非空(hosting 经 resolveBuildCommand 判定;app local 由 if 判定)
97
+ * - envVariables:注入构建进程环境变量(值统一转字符串)
98
+ */
99
+ private runLocalBuild;
100
+ /**
101
+ * 解析 app 访问地址(describeAppInfo.Domain + appPath)
102
+ */
103
+ private resolveAppUrl;
104
+ }
@@ -0,0 +1,17 @@
1
+ import { Environment } from '../environment';
2
+ /**
3
+ * 构造环境 HTTP 访问服务默认域名 `${envId}-${AppId}.${region}.app.tcloudbase.com`
4
+ *
5
+ * 关键:用 `UserInfo.AppId`(腾讯云 appid)而非 `UserInfo.Uin`(账号 uin)。
6
+ * 控制台默认域名格式是 `${envId}-${AppId}.${region}.app.tcloudbase.com`
7
+ * (如 `xxx-1326375956.ap-shanghai.app.tcloudbase.com`),与 cookie 中的 `appid` 字段对应。
8
+ * AppId/Region 缺失或查询失败时返回 undefined
9
+ */
10
+ export declare function resolveAccessServiceDomain(environment: Environment, envId: string): Promise<string | undefined>;
11
+ /**
12
+ * 构造网关基础地址 `https://{envId}.api.tcloudbasegateway.com`
13
+ *
14
+ * 对齐 CLI 的 `EDomain.Gateway`:`isInternalEndpoint` 决定是否国际站域名
15
+ * (`api.intl.tcloudbasegateway.com`)。
16
+ */
17
+ export declare function getGatewayBaseUrl(environment: Environment, envId: string): string;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 框架 → 默认构建命令映射(hosting 本地构建 / app 云端构建复用)
3
+ */
4
+ export declare const FRAMEWORK_BUILD_COMMANDS: Record<string, string>;
5
+ export interface IFrameworkConfig {
6
+ framework?: string;
7
+ buildCommand?: string;
8
+ }
9
+ /** 读取 package.json 的函数签名(测试可注入 mock,Node 20+ 下 fs 属性为只读 getter 不便 spy) */
10
+ export type ReadPkgFile = (filePath: string, encoding: 'utf8') => string;
11
+ /**
12
+ * 探测项目根目录下的框架类型(读 package.json 依赖)
13
+ * 读取失败或无匹配返回 null(按纯静态处理)
14
+ */
15
+ export declare function detectFramework(root: string, readPkgFile?: ReadPkgFile): string | null;
16
+ /**
17
+ * 解析构建命令,优先级:
18
+ * 1. 显式配置 buildCommand(含空字符串,'' = 不构建)
19
+ * 2. 显式配置 framework → 映射推导(static/custom → null 不构建)
20
+ * 3. 未配置 framework → 读 package.json 自动探测框架并推导
21
+ * 均无法确定 → null(纯静态直接上传)
22
+ */
23
+ export declare function resolveBuildCommand(config: IFrameworkConfig, root: string, readPkgFile?: ReadPkgFile): string | null;
@@ -0,0 +1,40 @@
1
+ import { ICloudFunction } from '../../interfaces';
2
+ import { ICodeArtifact, IFunctionArtifact, IImageArtifact, INormalizedDeployConfig, INormalizedHttpCloudConfig, INormalizedHttpImageConfig, INormalizedHttpLocalConfig } from '../types';
3
+ /**
4
+ * 部署物构造与 SCF 参数映射
5
+ *
6
+ * 四种构建策略最终都产出统一的部署物,之后走同一条 SCF 创建或更新流程
7
+ */
8
+ /** 由本地代码来源构造代码类部署物 */
9
+ export declare function createCodeArtifact(config: INormalizedDeployConfig): ICodeArtifact;
10
+ /** 由已有镜像配置构造镜像类部署物 */
11
+ export declare function createImageArtifactFromConfig(config: INormalizedHttpImageConfig): IImageArtifact;
12
+ /**
13
+ * 由本地构建结果构造镜像类部署物
14
+ *
15
+ * local 策略(个人版先行)产出:镜像已由 local-builder 构建并推送,
16
+ * 此处仅承载最终 imageUri/digest 与容器启动配置,之后复用镜像部署链。
17
+ */
18
+ export declare function createImageArtifactFromBuild(config: INormalizedHttpLocalConfig, build: {
19
+ imageUri: string;
20
+ imageDigest?: string;
21
+ }): IImageArtifact;
22
+ /**
23
+ * 由云端构建结果构造镜像类部署物
24
+ *
25
+ * cloud 策略(CloudApp custom)产出:镜像已在构建容器内 docker build + push到 TCR,
26
+ * 此处仅承载最终 imageUri/digest 与构建元信息(buildId/logsUrl),之后复用镜像部署链。
27
+ * effectiveStrategy 标记为 cloud,便于结果层如实回传实际生效的策略。
28
+ */
29
+ export declare function createImageArtifactFromCloudBuild(config: INormalizedHttpCloudConfig, build: {
30
+ imageUri: string;
31
+ imageDigest?: string;
32
+ buildId?: string;
33
+ logsUrl?: string;
34
+ }): IImageArtifact;
35
+ /**
36
+ * 将部署配置与部署物映射为 FunctionService 所需的云函数配置
37
+ *
38
+ * 只映射与 SCF 相关的字段,public、gatewayPath 等访问配置由后处理阶段负责
39
+ */
40
+ export declare function toCloudFunction(config: INormalizedDeployConfig, artifact: IFunctionArtifact): ICloudFunction;
@@ -0,0 +1,110 @@
1
+ import { ICustomBuildEnv, ICustomBuildSecret, ICustomBuildStep, CloudAppArtifact, CloudAppBuildStep } from '../../../cloudApp/types';
2
+ import { INormalizedHttpCloudConfig } from '../../types';
3
+ export interface ICloudBuildResult {
4
+ imageUri: string;
5
+ imageDigest?: string;
6
+ buildId?: string;
7
+ versionName?: string;
8
+ logsUrl?: string;
9
+ }
10
+ /** COS 上传信息(对应 DescribeCloudAppCosInfo 响应的必要字段) */
11
+ export interface ICloudCosInfo {
12
+ uploadUrl: string;
13
+ uploadHeaders: Array<{
14
+ key: string;
15
+ value: string;
16
+ }>;
17
+ unixTimestamp: string;
18
+ }
19
+ /** 创建 custom 构建入参(不含 envId/deployType/buildType,由 service 补齐固定值) */
20
+ export interface ICloudCreateBuildInput {
21
+ serviceName: string;
22
+ cosTimestamp: string;
23
+ env: ICustomBuildEnv[];
24
+ secrets?: ICustomBuildSecret[];
25
+ customSteps: ICustomBuildStep[];
26
+ }
27
+ /** 创建 custom 构建结果 */
28
+ export interface ICloudCreateBuildResult {
29
+ buildId?: string;
30
+ versionName: string;
31
+ /** CreateCloudApp 接口返回的 RequestId,便于把构建问题反馈给平台后端定位 */
32
+ requestId?: string;
33
+ }
34
+ /** 构建版本状态(对应 DescribeCloudAppVersion 响应必要字段) */
35
+ export interface ICloudVersionStatus {
36
+ status: string;
37
+ steps?: CloudAppBuildStep[] | null;
38
+ artifacts?: CloudAppArtifact[] | null;
39
+ /** DescribeCloudAppVersion 接口返回的 RequestId,便于把构建问题反馈给平台后端定位 */
40
+ requestId?: string;
41
+ }
42
+ /** 需要额外注入到构建 zip 的文件条目(zip 内路径 + 内容 + 可选 unix 权限位) */
43
+ export interface ICloudBuildExtraEntry {
44
+ /** zip 包内的相对路径,如 scripts/tcr-login-and-push.sh */
45
+ zipPath: string;
46
+ /** 文件文本内容 */
47
+ content: string;
48
+ /** unix 权限位(八进制),如 0o755;脚本需可执行 */
49
+ mode?: number;
50
+ }
51
+ /**
52
+ * 云端构建所需的外部能力,由编排器注入
53
+ *每个方法对应构建方案(https://iwiki.woa.com/p/4020519533)的一个 API/IO 步骤
54
+ */
55
+ export interface ICloudBuildService {
56
+ /**
57
+ * 打包构建上下文为 ZIP,返回本地临时 zip 路径
58
+ * @param cwd 构建上下文目录
59
+ * @param extraEntries 额外注入zip 的文件(如 push 脚本),不写入用户源码目录
60
+ */
61
+ packContext: (cwd: string, extraEntries?: ICloudBuildExtraEntry[]) => Promise<string>;
62
+ /** 获取 COS 上传凭证(DescribeCloudAppCosInfo,DeployType:custom) */
63
+ getCosInfo: (serviceName: string) => Promise<ICloudCosInfo>;
64
+ /** PUT 上传 zip 到 COS,必须携带全部 uploadHeaders */
65
+ uploadZip: (cosInfo: ICloudCosInfo, zipPath: string) => Promise<void>;
66
+ /** 触发 custom 构建(CreateCloudApp,DeployType:custom) */
67
+ createBuild: (input: ICloudCreateBuildInput) => Promise<ICloudCreateBuildResult>;
68
+ /** 查询构建版本状态(DescribeCloudAppVersion) */
69
+ getVersionStatus: (serviceName: string, versionName: string) => Promise<ICloudVersionStatus>;
70
+ /** 清理本地临时 zip;失败不应影响主流程 */
71
+ cleanup: (zipPath: string) => Promise<void>;
72
+ /** 延时(便于测试注入立即返回) */
73
+ delay: (ms: number) => Promise<void>;
74
+ }
75
+ /** 注入到构建上下文 zip 中的推送脚本相对路径(与 CustomSteps 的 push命令一致) */
76
+ export declare const TCR_PUSH_SCRIPT_ZIP_PATH = "scripts/tcr-login-and-push.sh";
77
+ /**
78
+ * 注入到构建 zip 的 TCR/CCR 登录推送脚本(完整可运行)
79
+ *
80
+ * 对应构建方案(https://iwiki.woa.com/p/4020519533)「阶段 A」的 push 步骤:
81
+ * push-image 步骤执行 `bash./scripts/tcr-login-and-push.sh`,该脚本必须随源码
82
+ * 一同打进zip 根目录,否则云端会 `No such file or directory` 秒挂。
83
+ *
84
+ * 关键设计:
85
+ * - 地域参数化:REGION 读环境变量 $TCR_REGION(由 buildEnv 按部署地域注入),
86
+ * 避免硬编码 ap-shanghai跨地域时 AuthFailure.SignatureFailure。
87
+ * - 双仓库兼容:设置了 $TCR_INSTANCE_ID 走企业版 TCR CreateInstanceToken;
88
+ * 否则走个人版 CCR,用户名来自普通 Env,固定密码来自 CloudApp Secrets。
89
+ * - 安全红线:凭证一律经 --password-stdin 传入,绝不出现在 ps/日志;
90
+ * 不打印任何 $API_SECRET_* / token / $SECRET_TCR_PASSWORD_B64 或解码后的密码。
91
+ *
92
+ * 脚本内容为SDK 固定模板,不拼接任何用户输入(镜像地址等均由已校验的
93
+ * 环境变量在容器内组装),无命令注入面。
94
+ */
95
+ export declare const TCR_LOGIN_PUSH_SCRIPT = "#!/usr/bin/env bash\n# scripts/tcr-login-and-push.sh\n# \u7531 CloudBase SDK \u81EA\u52A8\u6CE8\u5165\uFF1A\u4F01\u4E1A\u7248\u4F7F\u7528 STS \u6362\u53D6\u4E34\u65F6 token\uFF0C\u4E2A\u4EBA\u7248\u4F7F\u7528 CloudApp Secret\nset -euo pipefail\n\n: \"${TCR_REGISTRY:?TCR_REGISTRY \u672A\u8BBE\u7F6E}\"\n: \"${TCR_NAMESPACE:?TCR_NAMESPACE \u672A\u8BBE\u7F6E}\"\n: \"${CLOUDBASE_SERVICE_NAME:?\u5E73\u53F0\u53D8\u91CF\u7F3A\u5931}\"\n: \"${CLOUDBASE_VERSION_NAME:?\u5E73\u53F0\u53D8\u91CF\u7F3A\u5931}\"\n\nREGION=\"${TCR_REGION:-ap-shanghai}\"\nIMAGE=\"${TCR_REGISTRY}/${TCR_NAMESPACE}/${CLOUDBASE_SERVICE_NAME}:${CLOUDBASE_VERSION_NAME}\"\n\nif [ -n \"${TCR_INSTANCE_ID:-}\" ]; then\n : \"${API_SECRET_ID:?STS \u51ED\u8BC1\u7F3A\u5931}\"\n : \"${API_SECRET_KEY:?STS \u51ED\u8BC1\u7F3A\u5931}\"\n : \"${API_TOKEN:?STS \u51ED\u8BC1\u7F3A\u5931}\"\n\n # ---- \u4F01\u4E1A\u7248 TCR\uFF1ACreateInstanceToken \u6362\u767B\u5F55\u6001 ----\n HOST=\"tcr.tencentcloudapi.com\"\n SERVICE=\"tcr\"\n VERSION=\"2019-09-24\"\n ACTION=\"CreateInstanceToken\"\n ALGORITHM=\"TC3-HMAC-SHA256\"\n TIMESTAMP=$(date +%s)\n DATE=$(date -u -d \"@${TIMESTAMP}\" +\"%Y-%m-%d\" 2>/dev/null || date -u -r \"${TIMESTAMP}\" +\"%Y-%m-%d\")\n\n PAYLOAD=$(printf '{\"RegistryId\":\"%s\",\"TokenType\":\"LongTermToken\"}' \"${TCR_INSTANCE_ID}\")\n HASHED_PAYLOAD=$(printf '%s' \"${PAYLOAD}\" | openssl dgst -sha256 -hex | awk '{print $NF}')\n CANONICAL_HEADERS=\"content-type:application/json; charset=utf-8\\nhost:${HOST}\\nx-tc-action:$(echo \"${ACTION}\" | tr '[:upper:]' '[:lower:]')\\n\"\n SIGNED_HEADERS=\"content-type;host;x-tc-action\"\n CANONICAL_REQUEST=\"POST\\n/\\n\\n${CANONICAL_HEADERS}\\n${SIGNED_HEADERS}\\n${HASHED_PAYLOAD}\"\n\n CREDENTIAL_SCOPE=\"${DATE}/${SERVICE}/tc3_request\"\n HASHED_CR=$(printf \"${CANONICAL_REQUEST}\" | openssl dgst -sha256 -hex | awk '{print $NF}')\n STRING_TO_SIGN=\"${ALGORITHM}\\n${TIMESTAMP}\\n${CREDENTIAL_SCOPE}\\n${HASHED_CR}\"\n\n secret_date=$(printf '%s' \"${DATE}\" | openssl dgst -sha256 -hmac \"TC3${API_SECRET_KEY}\" -hex | awk '{print $NF}')\n secret_svc=$(printf '%s' \"${SERVICE}\" | openssl dgst -sha256 -mac HMAC -macopt hexkey:\"${secret_date}\" -hex | awk '{print $NF}')\n secret_sign=$(printf '%s' \"tc3_request\" | openssl dgst -sha256 -mac HMAC -macopt hexkey:\"${secret_svc}\" -hex | awk '{print $NF}')\n SIGNATURE=$(printf \"${STRING_TO_SIGN}\" | openssl dgst -sha256 -mac HMAC -macopt hexkey:\"${secret_sign}\" -hex | awk '{print $NF}')\n\n AUTHZ=\"${ALGORITHM} Credential=${API_SECRET_ID}/${CREDENTIAL_SCOPE}, SignedHeaders=${SIGNED_HEADERS}, Signature=${SIGNATURE}\"\n\n RESP=$(curl -sS -X POST \"https://${HOST}\" \\\n -H \"Authorization: ${AUTHZ}\" \\\n -H \"Content-Type: application/json; charset=utf-8\" \\\n -H \"Host: ${HOST}\" \\\n -H \"X-TC-Action: ${ACTION}\" \\\n -H \"X-TC-Timestamp: ${TIMESTAMP}\" \\\n -H \"X-TC-Version: ${VERSION}\" \\\n -H \"X-TC-Region: ${REGION}\" \\\n -H \"X-TC-Token: ${API_TOKEN}\" \\\n --data \"${PAYLOAD}\")\n\n TOKEN_USER=$(printf '%s' \"${RESP}\" | jq -er '.Response.Username')\n TOKEN_PASS=$(printf '%s' \"${RESP}\" | jq -er '.Response.Token')\n\n printf '%s' \"${TOKEN_PASS}\" | docker login -u \"${TOKEN_USER}\" --password-stdin \"${TCR_REGISTRY}\"\nelse\n # ---- \u4E2A\u4EBA\u7248 CCR\uFF1A\u8D26\u53F7 ID + \u56FA\u5B9A\u5BC6\u7801\uFF08Base64 \u5C01\u88C5\u540E\u7531 CloudApp Secrets \u6CE8\u5165\uFF09 ----\n : \"${TCR_USERNAME:?TCR_USERNAME \u672A\u8BBE\u7F6E}\"\n : \"${SECRET_TCR_PASSWORD_B64:?TCR_PASSWORD \u672A\u8BBE\u7F6E}\"\n printf '%s' \"${SECRET_TCR_PASSWORD_B64}\" | base64 --decode | docker login -u \"${TCR_USERNAME}\" --password-stdin \"${TCR_REGISTRY}\"\nfi\n\ndocker push \"${IMAGE}\"\n\necho \"::output::tag=${CLOUDBASE_VERSION_NAME}\"\n";
96
+ /** buildImageOnCloud 可选项 */
97
+ export interface IBuildImageOnCloudOptions {
98
+ /** 日志回调,用于透出构建进度(不含凭证) */
99
+ onLog?: (line: string) => void;
100
+ /** 部署地域,注入构建环境供推送脚本换取仓库登录态(跨地域必需) */
101
+ region?: string;
102
+ }
103
+ /**
104
+ * 执行云端构建并推送镜像
105
+ *
106
+ * @param config 规范化的 cloud 部署配置
107
+ * @param service 注入的外部能力(打包/tcb API/COS 上传)
108
+ * @param options 可选项:日志回调 onLog、部署地域 region
109
+ */
110
+ export declare function buildImageOnCloud(config: INormalizedHttpCloudConfig, service: ICloudBuildService, options?: IBuildImageOnCloudOptions): Promise<ICloudBuildResult>;
@@ -0,0 +1,51 @@
1
+ import { ICheckReport, INormalizedDeployConfig } from '../types';
2
+ /**
3
+ * 镜像拉取授权 Preflight(涉及 CAM,scope: cloud)
4
+ *
5
+ * SCF 拉取镜像由服务角色 SCF_QcsRole 代理,个人版镜像要求该角色绑定
6
+ * QcloudAccessForSCFRoleInPullImage 策略。本模块在 image 策略部署前:
7
+ * 1. 探测该角色与策略是否就绪;
8
+ * 2. 缺失且允许时,自动绑定「唯一白名单策略」补齐(绝不放大到其它策略);
9
+ * 3. 当前身份无 CAM 权限时不硬失败,降级为结构化指引 + 一键授权链接兜底。
10
+ *
11
+ * 安全边界(对应 security_rules 的 AuthZ / 最小权限):
12
+ * - 自动授权只允许绑定 REQUIRED_IMAGE_PULL_POLICY 这一条部署必需的预置策略;
13
+ * - 不代用户创建角色、不绑定任何白名单外策略;
14
+ * - 探测/授权失败一律走降级,不阻断到无法给出可操作指引。
15
+ */
16
+ /** SCF 拉取镜像使用的服务角色 */
17
+ export declare const SCF_PULL_IMAGE_ROLE = "SCF_QcsRole";
18
+ /** 拉取个人版镜像所需的唯一预置策略(自动授权白名单,仅此一条) */
19
+ export declare const REQUIRED_IMAGE_PULL_POLICY = "QcloudAccessForSCFRoleInPullImage";
20
+ /** 官方一键授权链接,作为无 CAM 权限时的兜底指引 */
21
+ export declare const IMAGE_PULL_GRANT_URL: string;
22
+ /** 角色详情,仅取判断所需字段 */
23
+ interface IRoleDetail {
24
+ RoleName?: string;
25
+ /** 已绑定的策略名集合,具体来源由适配层填充 */
26
+ attachedPolicyNames?: string[];
27
+ }
28
+ /**
29
+ * CAM 能力的最小依赖接口
30
+ *
31
+ * 只声明本模块需要的方法,便于解耦具体实现与单元测试。
32
+ * 适配层负责把 CamService 的返回适配为 attachedPolicyNames。
33
+ */
34
+ export interface ICamPreflightService {
35
+ /** 获取角色详情及其已绑定策略名;角色不存在应抛出可识别错误 */
36
+ getRoleWithPolicies: (roleName: string) => Promise<IRoleDetail>;
37
+ /** 为角色绑定指定预置策略(按策略名) */
38
+ attachPolicyByName: (roleName: string, policyName: string) => Promise<void>;
39
+ }
40
+ /** 判断错误是否为 CAM 权限不足 */
41
+ export declare function isCamPermissionError(error: any): boolean;
42
+ /**
43
+ * 执行镜像拉取授权 Preflight
44
+ *
45
+ * @param service CAM 能力适配(无则视为无法校验,直接降级为提示)
46
+ * @param config 规范化部署配置
47
+ * @param autoGrant 是否允许自动补齐授权(默认 true)
48
+ * @returns scope 为 cloud 的检查报告,聚合全部结论
49
+ */
50
+ export declare function runImagePullAuthPreflight(service: ICamPreflightService | null, config: INormalizedDeployConfig, autoGrant?: boolean): Promise<ICheckReport>;
51
+ export {};
@@ -0,0 +1,10 @@
1
+ import { CloudAppService } from '../../cloudApp';
2
+ import { ICloudBuildService } from './builders/cloud';
3
+ export interface ICreateCloudBuildServiceOptions {
4
+ /** 追加的打包忽略项 */
5
+ ignore?: string[];
6
+ }
7
+ /**
8
+ * 由CloudAppService 构造 ICloudBuildService实现
9
+ */
10
+ export declare function createCloudBuildService(cloudApp: CloudAppService, options?: ICreateCloudBuildServiceOptions): ICloudBuildService;
@@ -0,0 +1,41 @@
1
+ import { ICheckReport, IFunctionDeployConfig, INormalizedDeployConfig } from '../types';
2
+ export interface IParsedImageReference {
3
+ registry?: string;
4
+ repository: string;
5
+ tag?: string;
6
+ digest?: string;
7
+ }
8
+ /**
9
+ * 解析 OCI 镜像引用
10
+ *
11
+ * 支持 [registry[:port]/]repository[:tag][@digest]
12
+ * 无法仅通过是否包含冒号判断 tag,因为 registry 可能带端口
13
+ * @returns 解析结果,非法时返回 null
14
+ */
15
+ export declare function parseImageReference(reference: string): IParsedImageReference | null;
16
+ /**
17
+ * 规范化网关路径
18
+ *
19
+ * 合并连续斜杠并去除尾部斜杠,根路径保持为 /
20
+ * @returns 规范化结果,非法时返回 null
21
+ */
22
+ export declare function normalizeGatewayPath(input: string): string | null;
23
+ /** 判断是否为自定义镜像运行时 */
24
+ export declare function isCustomImageRuntime(runtime?: string): boolean;
25
+ /**
26
+ * 规范化部署配置
27
+ *
28
+ * 仅填充默认值与收窄类型,不做合法性判断,保证在非法输入下也能安全返回,
29
+ * 以便 checkDeployConfig 汇总全部问题
30
+ */
31
+ export declare function normalizeDeployConfig(config: IFunctionDeployConfig): INormalizedDeployConfig;
32
+ /**
33
+ * 校验部署配置
34
+ * @returns 检查报告,包含全部问题而非仅第一个
35
+ */
36
+ export declare function checkDeployConfig(config: IFunctionDeployConfig): ICheckReport;
37
+ /**
38
+ * 校验并规范化部署配置
39
+ * @throws CloudBaseError 存在任一 fail 项时抛出,错误信息包含全部失败原因
40
+ */
41
+ export declare function assertDeployConfig(config: IFunctionDeployConfig): INormalizedDeployConfig;
@@ -0,0 +1,17 @@
1
+ import { ICheckReport } from '../types';
2
+ export interface IExecResult {
3
+ ok: boolean;
4
+ stdout: string;
5
+ stderr: string;
6
+ }
7
+ /** 只读命令执行器签名 */
8
+ export type ReadonlyRunner = (command: string, args: string[]) => Promise<IExecResult>;
9
+ /**
10
+ * 执行 Docker 本地能力检查
11
+ *
12
+ * 检测顺序:CLI 存在性 → daemon 可用性 → buildx 可用性。
13
+ * CLI 缺失时短路(daemon/buildx 无从谈起),其余项独立收集后聚合返回。
14
+ *
15
+ * @param runner 命令执行器,默认真实 execFile;测试可注入 mock
16
+ */
17
+ export declare function runDockerPreflight(runner?: ReadonlyRunner): Promise<ICheckReport>;
@@ -0,0 +1,21 @@
1
+ import { ICheckReport, INormalizedDeployConfig } from '../types';
2
+ export interface IExecResult {
3
+ ok: boolean;
4
+ stdout: string;
5
+ stderr: string;
6
+ /** 命令本身无法启动(如 docker 未安装)时为 true,与“命令执行了但返回非零”区分 */
7
+ spawnFailed?: boolean;
8
+ }
9
+ /** 可注入依赖:远端 manifest 查询命令 */
10
+ export interface IImagePreflightDeps {
11
+ runCommand: (command: string, args: string[]) => Promise<IExecResult>;
12
+ }
13
+ /**
14
+ * 执行镜像远端校验 Preflight
15
+ *
16
+ * @param config 规范化部署配置
17
+ * @param deployRegion 函数部署地域(可选,来源于 environment;未知时跳过地域校验)
18
+ * @param deps 可注入依赖,默认真实命令;测试可传 mock
19
+ * @returns scope 为 cloud 的检查报告
20
+ */
21
+ export declare function runImageRemotePreflight(config: INormalizedDeployConfig, deployRegion?: string, deps?: IImagePreflightDeps): Promise<ICheckReport>;
@@ -0,0 +1,26 @@
1
+ import { INormalizedHttpLocalConfig } from '../types';
2
+ export interface ILocalBuildResult {
3
+ imageUri: string;
4
+ imageDigest?: string;
5
+ }
6
+ export interface IExecResult {
7
+ ok: boolean;
8
+ stdout: string;
9
+ stderr: string;
10
+ }
11
+ /** 可注入依赖:命令执行与文件系统检查 */
12
+ export interface ILocalBuilderDeps {
13
+ runCommand: (command: string, args: string[]) => Promise<IExecResult>;
14
+ existsSync: (target: string) => boolean;
15
+ isDirectory: (target: string) => boolean;
16
+ isFile: (target: string) => boolean;
17
+ }
18
+ /**
19
+ * 本地构建镜像并推送到目标仓库
20
+ *
21
+ * @param config 规范化的 local 部署配置
22
+ * @param onLog 可选日志回调,用于透出构建输出(不含凭证)
23
+ * @param deps 可注入依赖,默认真实命令与 fs;测试可传 mock
24
+ * @returns 最终镜像引用与 digest
25
+ */
26
+ export declare function buildAndPushImage(config: INormalizedHttpLocalConfig, onLog?: (line: string) => void, deps?: ILocalBuilderDeps): Promise<ILocalBuildResult>;
@@ -0,0 +1,15 @@
1
+ import { IFunctionInfo } from '../../function/types';
2
+ import { IFunctionCurrentState, IFunctionDeployPlan, INormalizedDeployConfig } from '../types';
3
+ /**
4
+ * 部署计划生成
5
+ *
6
+ * 纯函数实现,线上函数状态由调用方查询后传入,便于单独测试
7
+ */
8
+ /** 将 SCF 返回的函数详情收敛为计划所需的状态摘要 */
9
+ export declare function toCurrentState(info: IFunctionInfo): IFunctionCurrentState;
10
+ /**
11
+ * 生成部署计划
12
+ * @param config 已规范化的部署配置
13
+ * @param current 线上函数详情,不存在时传 null
14
+ */
15
+ export declare function createDeployPlan(config: INormalizedDeployConfig, current?: IFunctionInfo | null): IFunctionDeployPlan;