@zhin.js/adapter-github 1.1.15 → 1.1.16
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 +33 -0
- package/README.md +4 -0
- package/agents/github/messages.js +72 -0
- package/agents/github/messages.ts +72 -0
- package/agents/github/skills/github-account/handlers.js +30 -25
- package/agents/github/skills/github-account/handlers.ts +30 -25
- package/agents/github/skills/github-account/tools/bind/index.js +1 -1
- package/agents/github/skills/github-account/tools/bind/index.ts +1 -1
- package/agents/github/skills/github-account/tools/install/index.js +1 -1
- package/agents/github/skills/github-account/tools/install/index.ts +1 -1
- package/agents/github/skills/github-account/tools/unbind/index.js +1 -1
- package/agents/github/skills/github-account/tools/unbind/index.ts +1 -1
- package/agents/github/skills/github-account/tools/whoami/index.js +1 -1
- package/agents/github/skills/github-account/tools/whoami/index.ts +1 -1
- package/agents/github/skills/github-repository/handlers.js +82 -35
- package/agents/github/skills/github-repository/handlers.ts +83 -31
- package/agents/github/skills/github-repository/tools/create_pr/index.js +1 -1
- package/agents/github/skills/github-repository/tools/create_pr/index.ts +1 -1
- package/agents/github/skills/github-repository/tools/patch_file/index.js +1 -1
- package/agents/github/skills/github-repository/tools/patch_file/index.ts +1 -1
- package/agents/github/skills/github-repository/tools/prepare_workspace/index.js +1 -1
- package/agents/github/skills/github-repository/tools/prepare_workspace/index.ts +1 -1
- package/agents/github/skills/github-repository/tools/push_branch/index.js +1 -1
- package/agents/github/skills/github-repository/tools/push_branch/index.ts +1 -1
- package/agents/github/skills/github-subscriptions/handlers.js +85 -22
- package/agents/github/skills/github-subscriptions/handlers.ts +86 -22
- package/agents/github/skills/github-subscriptions/tools/star/index.js +1 -1
- package/agents/github/skills/github-subscriptions/tools/star/index.ts +1 -1
- package/agents/github/skills/github-subscriptions/tools/subscribe/index.js +1 -1
- package/agents/github/skills/github-subscriptions/tools/subscribe/index.ts +1 -1
- package/agents/github/skills/github-subscriptions/tools/subscriptions/index.js +1 -1
- package/agents/github/skills/github-subscriptions/tools/subscriptions/index.ts +1 -1
- package/agents/github/skills/github-subscriptions/tools/unsubscribe/index.js +1 -1
- package/agents/github/skills/github-subscriptions/tools/unsubscribe/index.ts +1 -1
- package/commands/github/endpoint/definition.js +2 -2
- package/commands/github/endpoint/definition.ts +2 -2
- package/lib/github-channel-context.d.ts +2 -1
- package/lib/github-channel-context.js +6 -2
- package/lib/workspace-manager.d.ts +8 -7
- package/lib/workspace-manager.js +62 -50
- package/package.json +19 -19
- package/schema.json +41 -6
- package/src/github-channel-context.ts +7 -1
- package/src/workspace-manager.ts +62 -50
package/schema.json
CHANGED
|
@@ -31,7 +31,12 @@
|
|
|
31
31
|
"string",
|
|
32
32
|
"number"
|
|
33
33
|
],
|
|
34
|
-
"description": "框架 master(GitHub user login or id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
34
|
+
"description": "框架 master(GitHub user login or id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖",
|
|
35
|
+
"x-i18n": {
|
|
36
|
+
"en": {
|
|
37
|
+
"description": "Framework masters (GitHub user login or id; AI/tool permissions and endpoint management). endpoints[i].master can override this value."
|
|
38
|
+
}
|
|
39
|
+
}
|
|
35
40
|
},
|
|
36
41
|
"trusted": {
|
|
37
42
|
"type": "array",
|
|
@@ -42,7 +47,12 @@
|
|
|
42
47
|
],
|
|
43
48
|
"description": "Trusted GitHub user login or id"
|
|
44
49
|
},
|
|
45
|
-
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
50
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加",
|
|
51
|
+
"x-i18n": {
|
|
52
|
+
"en": {
|
|
53
|
+
"description": "Framework trusted users, below master authority. endpoints[i].trusted can add users."
|
|
54
|
+
}
|
|
55
|
+
}
|
|
46
56
|
},
|
|
47
57
|
"endpoints": {
|
|
48
58
|
"type": "array",
|
|
@@ -57,7 +67,12 @@
|
|
|
57
67
|
"string",
|
|
58
68
|
"number"
|
|
59
69
|
],
|
|
60
|
-
"description": "本 endpoint 的框架 master(GitHub user login or id);覆盖顶层 master"
|
|
70
|
+
"description": "本 endpoint 的框架 master(GitHub user login or id);覆盖顶层 master",
|
|
71
|
+
"x-i18n": {
|
|
72
|
+
"en": {
|
|
73
|
+
"description": "Framework masters for this endpoint (GitHub user login or id), overriding the top-level master list."
|
|
74
|
+
}
|
|
75
|
+
}
|
|
61
76
|
},
|
|
62
77
|
"trusted": {
|
|
63
78
|
"type": "array",
|
|
@@ -68,7 +83,12 @@
|
|
|
68
83
|
],
|
|
69
84
|
"description": "Trusted GitHub user login or id"
|
|
70
85
|
},
|
|
71
|
-
"description": "本 endpoint 的 trusted 列表"
|
|
86
|
+
"description": "本 endpoint 的 trusted 列表",
|
|
87
|
+
"x-i18n": {
|
|
88
|
+
"en": {
|
|
89
|
+
"description": "Trusted users for this endpoint."
|
|
90
|
+
}
|
|
91
|
+
}
|
|
72
92
|
},
|
|
73
93
|
"app_id": {
|
|
74
94
|
"type": [
|
|
@@ -115,7 +135,12 @@
|
|
|
115
135
|
},
|
|
116
136
|
"commandPrefix": {
|
|
117
137
|
"type": "string",
|
|
118
|
-
"description": "本 endpoint 的命令前缀"
|
|
138
|
+
"description": "本 endpoint 的命令前缀",
|
|
139
|
+
"x-i18n": {
|
|
140
|
+
"en": {
|
|
141
|
+
"description": "Command prefix for this endpoint."
|
|
142
|
+
}
|
|
143
|
+
}
|
|
119
144
|
}
|
|
120
145
|
},
|
|
121
146
|
"required": [
|
|
@@ -123,12 +148,22 @@
|
|
|
123
148
|
"app_id",
|
|
124
149
|
"private_key"
|
|
125
150
|
]
|
|
151
|
+
},
|
|
152
|
+
"x-i18n": {
|
|
153
|
+
"en": {
|
|
154
|
+
"description": "Multiple accounts: mount multiple endpoints in one plugin instance."
|
|
155
|
+
}
|
|
126
156
|
}
|
|
127
157
|
},
|
|
128
158
|
"commandPrefix": {
|
|
129
159
|
"type": "string",
|
|
130
160
|
"default": "",
|
|
131
|
-
"description": "命令前缀(默认 '' 无前缀,任意文本按命令匹配;如 '/' 要求 / 开头)。endpoints[i] 可逐项覆盖"
|
|
161
|
+
"description": "命令前缀(默认 '' 无前缀,任意文本按命令匹配;如 '/' 要求 / 开头)。endpoints[i] 可逐项覆盖",
|
|
162
|
+
"x-i18n": {
|
|
163
|
+
"en": {
|
|
164
|
+
"description": "Command prefix. The default empty string allows unprefixed commands; '/' requires a leading slash. Each endpoints[i] can override it."
|
|
165
|
+
}
|
|
166
|
+
}
|
|
132
167
|
}
|
|
133
168
|
},
|
|
134
169
|
"required": [
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Parse GitHub Issue/PR channel context from IM messages.
|
|
3
3
|
*/
|
|
4
4
|
import type { Message } from 'zhin.js';
|
|
5
|
+
import { createMessages, type Locale } from 'zhin.js/i18n';
|
|
5
6
|
import { buildChannelId, parseChannelId, type ParsedChannel } from './types.js';
|
|
6
7
|
import type { GhClient } from './gh-client.js';
|
|
7
8
|
|
|
@@ -24,6 +25,7 @@ export function issueBranchName(number: number): string {
|
|
|
24
25
|
export async function resolveWorkspaceBranch(
|
|
25
26
|
gh: GhClient,
|
|
26
27
|
ctx: GitHubChannelContext,
|
|
28
|
+
locale?: Locale,
|
|
27
29
|
): Promise<{ branch: string; base: string }> {
|
|
28
30
|
if (ctx.type === 'pr') {
|
|
29
31
|
const pr = await gh.getPR(ctx.repo, ctx.number);
|
|
@@ -31,7 +33,7 @@ export async function resolveWorkspaceBranch(
|
|
|
31
33
|
const base = pr.data.base?.ref ?? 'main';
|
|
32
34
|
return { branch: pr.data.head.ref, base };
|
|
33
35
|
}
|
|
34
|
-
throw new Error(
|
|
36
|
+
throw new Error(t(locale, 'missingHead', { number: ctx.number }));
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
const repoInfo = await gh.getRepo(ctx.repo);
|
|
@@ -44,3 +46,7 @@ export async function resolveWorkspaceBranch(
|
|
|
44
46
|
export function formatChannelContext(ctx: GitHubChannelContext): string {
|
|
45
47
|
return buildChannelId(ctx.repo, ctx.type, ctx.number);
|
|
46
48
|
}
|
|
49
|
+
|
|
50
|
+
const t = createMessages({
|
|
51
|
+
missingHead: { 'zh-CN': '无法读取 PR #{number} 的 head 分支', en: 'Cannot read the head branch of PR #{number}' },
|
|
52
|
+
});
|
package/src/workspace-manager.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
+
import { createMessages, type Locale } from 'zhin.js/i18n';
|
|
7
8
|
import type { GhClient, GitHubBotIdentity } from './gh-client.js';
|
|
8
9
|
|
|
9
10
|
const REPO_FULL_NAME_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
@@ -23,13 +24,13 @@ function containsIllegalGitRefCharacter(ref: string): boolean {
|
|
|
23
24
|
* 校验 GitHub "owner/name" 全名,防止路径穿越与 git 选项注入。
|
|
24
25
|
* 返回通过校验的原值,便于调用方直接使用「已消毒」的变量。
|
|
25
26
|
*/
|
|
26
|
-
export function assertRepoFullName(repo: string): string {
|
|
27
|
+
export function assertRepoFullName(repo: string, locale?: Locale): string {
|
|
27
28
|
if (
|
|
28
29
|
typeof repo !== 'string' ||
|
|
29
30
|
!REPO_FULL_NAME_RE.test(repo) ||
|
|
30
31
|
repo.split('/').some((seg) => seg === '' || seg.startsWith('-') || /^\.+$/.test(seg))
|
|
31
32
|
) {
|
|
32
|
-
throw new TypeError(
|
|
33
|
+
throw new TypeError(t(locale, 'invalidRepo', { value: JSON.stringify(repo) }));
|
|
33
34
|
}
|
|
34
35
|
return repo;
|
|
35
36
|
}
|
|
@@ -37,9 +38,9 @@ export function assertRepoFullName(repo: string): string {
|
|
|
37
38
|
/**
|
|
38
39
|
* 校验 git ref 名称,拒绝选项注入(`-` 前缀)与 git 非法字符。
|
|
39
40
|
*/
|
|
40
|
-
export function assertGitRefName(ref: string): string {
|
|
41
|
+
export function assertGitRefName(ref: string, locale?: Locale): string {
|
|
41
42
|
if (typeof ref !== 'string' || ref.length === 0) {
|
|
42
|
-
throw new TypeError(
|
|
43
|
+
throw new TypeError(t(locale, 'invalidRef', { value: JSON.stringify(ref) }));
|
|
43
44
|
}
|
|
44
45
|
if (
|
|
45
46
|
ref.startsWith('-') ||
|
|
@@ -48,7 +49,7 @@ export function assertGitRefName(ref: string): string {
|
|
|
48
49
|
ref.endsWith('/') ||
|
|
49
50
|
ref.endsWith('.')
|
|
50
51
|
) {
|
|
51
|
-
throw new TypeError(
|
|
52
|
+
throw new TypeError(t(locale, 'invalidRef', { value: JSON.stringify(ref) }));
|
|
52
53
|
}
|
|
53
54
|
return ref;
|
|
54
55
|
}
|
|
@@ -59,13 +60,13 @@ export class WorkspaceManager {
|
|
|
59
60
|
private readonly rootDir: string,
|
|
60
61
|
) {}
|
|
61
62
|
|
|
62
|
-
getRepoPath(repo: string): string {
|
|
63
|
-
repo = assertRepoFullName(repo);
|
|
63
|
+
getRepoPath(repo: string, locale?: Locale): string {
|
|
64
|
+
repo = assertRepoFullName(repo, locale);
|
|
64
65
|
const [owner, name] = repo.split('/');
|
|
65
66
|
return path.join(this.rootDir, owner, name);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
private runGit(cwd: string, args: string[], env?: NodeJS.ProcessEnv): Promise<string> {
|
|
69
|
+
private runGit(cwd: string, args: string[], env?: NodeJS.ProcessEnv, locale?: Locale): Promise<string> {
|
|
69
70
|
return new Promise((resolve, reject) => {
|
|
70
71
|
const proc = spawn('git', args, {
|
|
71
72
|
cwd,
|
|
@@ -77,7 +78,7 @@ export class WorkspaceManager {
|
|
|
77
78
|
proc.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });
|
|
78
79
|
proc.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });
|
|
79
80
|
proc.on('error', (err: NodeJS.ErrnoException) => {
|
|
80
|
-
if (err.code === 'ENOENT') reject(new Error(
|
|
81
|
+
if (err.code === 'ENOENT') reject(new Error(t(locale, 'missingGit')));
|
|
81
82
|
else reject(err);
|
|
82
83
|
});
|
|
83
84
|
proc.on('close', (code) => {
|
|
@@ -87,82 +88,93 @@ export class WorkspaceManager {
|
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
configureBotGit(repoPath: string, identity: GitHubBotIdentity): Promise<void> {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
]).then(() => undefined);
|
|
91
|
+
async configureBotGit(repoPath: string, identity: GitHubBotIdentity, locale?: Locale): Promise<void> {
|
|
92
|
+
// Both writes acquire the same .git/config.lock.
|
|
93
|
+
await this.runGit(repoPath, ['config', 'user.name', identity.login], undefined, locale);
|
|
94
|
+
await this.runGit(repoPath, ['config', 'user.email', identity.email], undefined, locale);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
async ensureRepo(repo: string): Promise<string> {
|
|
98
|
-
repo = assertRepoFullName(repo);
|
|
97
|
+
async ensureRepo(repo: string, locale?: Locale): Promise<string> {
|
|
98
|
+
repo = assertRepoFullName(repo, locale);
|
|
99
99
|
if (!this.gh.isAppAuth) {
|
|
100
|
-
throw new Error(
|
|
100
|
+
throw new Error(t(locale, 'appRequired'));
|
|
101
101
|
}
|
|
102
102
|
const token = await this.gh.ensureInstallationTokenForRepo(repo);
|
|
103
|
-
if (!token) throw new Error(
|
|
103
|
+
if (!token) throw new Error(t(locale, 'repoTokenUnavailable', { repo }));
|
|
104
104
|
|
|
105
|
-
const repoPath = this.getRepoPath(repo);
|
|
105
|
+
const repoPath = this.getRepoPath(repo, locale);
|
|
106
106
|
fs.mkdirSync(path.dirname(repoPath), { recursive: true });
|
|
107
107
|
|
|
108
108
|
const identity = await this.gh.getBotIdentity();
|
|
109
|
-
if (!identity) throw new Error(
|
|
109
|
+
if (!identity) throw new Error(t(locale, 'missingIdentity'));
|
|
110
110
|
|
|
111
111
|
const cloneUrl = this.gh.buildCloneUrl(repo, token);
|
|
112
112
|
if (!fs.existsSync(path.join(repoPath, '.git'))) {
|
|
113
|
-
await this.runGit(path.dirname(repoPath), ['clone', cloneUrl, path.basename(repoPath)]);
|
|
113
|
+
await this.runGit(path.dirname(repoPath), ['clone', '--', cloneUrl, path.basename(repoPath)], undefined, locale);
|
|
114
114
|
} else {
|
|
115
|
-
await this.runGit(repoPath, ['remote', 'set-url', 'origin', cloneUrl]);
|
|
116
|
-
await this.runGit(repoPath, ['fetch', 'origin', '--prune']);
|
|
115
|
+
await this.runGit(repoPath, ['remote', 'set-url', 'origin', cloneUrl], undefined, locale);
|
|
116
|
+
await this.runGit(repoPath, ['fetch', 'origin', '--prune'], undefined, locale);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
await this.configureBotGit(repoPath, identity);
|
|
119
|
+
await this.configureBotGit(repoPath, identity, locale);
|
|
120
120
|
return repoPath;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
async checkoutBranch(repo: string, branch: string, baseRef: string): Promise<string> {
|
|
124
|
-
repo = assertRepoFullName(repo);
|
|
125
|
-
branch = assertGitRefName(branch);
|
|
126
|
-
baseRef = assertGitRefName(baseRef);
|
|
127
|
-
const repoPath = await this.ensureRepo(repo);
|
|
128
|
-
const localBranches = await this.runGit(repoPath, ['branch', '--list', branch]);
|
|
123
|
+
async checkoutBranch(repo: string, branch: string, baseRef: string, locale?: Locale): Promise<string> {
|
|
124
|
+
repo = assertRepoFullName(repo, locale);
|
|
125
|
+
branch = assertGitRefName(branch, locale);
|
|
126
|
+
baseRef = assertGitRefName(baseRef, locale);
|
|
127
|
+
const repoPath = await this.ensureRepo(repo, locale);
|
|
128
|
+
const localBranches = await this.runGit(repoPath, ['branch', '--list', branch], undefined, locale);
|
|
129
129
|
if (localBranches.trim()) {
|
|
130
|
-
await this.runGit(repoPath, ['checkout', branch]);
|
|
131
|
-
await this.runGit(repoPath, ['pull', '--rebase', 'origin', branch]).catch(async () => {
|
|
132
|
-
await this.runGit(repoPath, ['fetch', 'origin', branch]);
|
|
130
|
+
await this.runGit(repoPath, ['checkout', branch], undefined, locale);
|
|
131
|
+
await this.runGit(repoPath, ['pull', '--rebase', '--', 'origin', branch], undefined, locale).catch(async () => {
|
|
132
|
+
await this.runGit(repoPath, ['fetch', '--', 'origin', branch], undefined, locale);
|
|
133
133
|
});
|
|
134
134
|
return repoPath;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
const remoteBranch = await this.runGit(repoPath, ['ls-remote', '--heads', 'origin', branch]);
|
|
137
|
+
const remoteBranch = await this.runGit(repoPath, ['ls-remote', '--heads', '--', 'origin', branch], undefined, locale);
|
|
138
138
|
if (remoteBranch.trim()) {
|
|
139
|
-
await this.runGit(repoPath, ['checkout', '-B', branch, `origin/${branch}`]);
|
|
139
|
+
await this.runGit(repoPath, ['checkout', '-B', branch, `origin/${branch}`], undefined, locale);
|
|
140
140
|
return repoPath;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
await this.runGit(repoPath, ['fetch', 'origin', baseRef]);
|
|
144
|
-
await this.runGit(repoPath, ['checkout', '-B', branch, `origin/${baseRef}`]);
|
|
143
|
+
await this.runGit(repoPath, ['fetch', '--', 'origin', baseRef], undefined, locale);
|
|
144
|
+
await this.runGit(repoPath, ['checkout', '-B', branch, `origin/${baseRef}`], undefined, locale);
|
|
145
145
|
return repoPath;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
async commitAndPush(repo: string, branch: string, message: string): Promise<string> {
|
|
149
|
-
repo = assertRepoFullName(repo);
|
|
150
|
-
branch = assertGitRefName(branch);
|
|
151
|
-
const repoPath = this.getRepoPath(repo);
|
|
148
|
+
async commitAndPush(repo: string, branch: string, message: string, locale?: Locale): Promise<string> {
|
|
149
|
+
repo = assertRepoFullName(repo, locale);
|
|
150
|
+
branch = assertGitRefName(branch, locale);
|
|
151
|
+
const repoPath = this.getRepoPath(repo, locale);
|
|
152
152
|
if (!fs.existsSync(repoPath)) {
|
|
153
|
-
throw new Error(
|
|
153
|
+
throw new Error(t(locale, 'missingWorkspace', { path: repoPath }));
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
const token = await this.gh.ensureInstallationTokenForRepo(repo);
|
|
157
|
-
if (!token) throw new Error(
|
|
158
|
-
await this.runGit(repoPath, ['remote', 'set-url', 'origin', this.gh.buildCloneUrl(repo, token)]);
|
|
157
|
+
if (!token) throw new Error(t(locale, 'missingToken'));
|
|
158
|
+
await this.runGit(repoPath, ['remote', 'set-url', 'origin', this.gh.buildCloneUrl(repo, token)], undefined, locale);
|
|
159
159
|
|
|
160
|
-
const status = await this.runGit(repoPath, ['status', '--porcelain']);
|
|
161
|
-
if (!status.trim()) return '
|
|
160
|
+
const status = await this.runGit(repoPath, ['status', '--porcelain'], undefined, locale);
|
|
161
|
+
if (!status.trim()) return t(locale, 'noChanges');
|
|
162
162
|
|
|
163
|
-
await this.runGit(repoPath, ['add', '-A']);
|
|
164
|
-
await this.runGit(repoPath, ['commit', '-m', message]);
|
|
165
|
-
await this.runGit(repoPath, ['push', '-u', 'origin', branch]);
|
|
166
|
-
return
|
|
163
|
+
await this.runGit(repoPath, ['add', '-A'], undefined, locale);
|
|
164
|
+
await this.runGit(repoPath, ['commit', '-m', message], undefined, locale);
|
|
165
|
+
await this.runGit(repoPath, ['push', '-u', 'origin', branch], undefined, locale);
|
|
166
|
+
return t(locale, 'pushed', { branch });
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
+
const t = createMessages({
|
|
170
|
+
invalidRepo: { 'zh-CN': '非法的仓库全名: {value}', en: 'Invalid repository name: {value}' },
|
|
171
|
+
invalidRef: { 'zh-CN': '非法的 git ref: {value}', en: 'Invalid git ref: {value}' },
|
|
172
|
+
missingGit: { 'zh-CN': 'git 未安装', en: 'git is not installed' },
|
|
173
|
+
appRequired: { 'zh-CN': 'GitHub App 认证未配置,无法托管工作区', en: 'GitHub App authentication is not configured; the workspace is unavailable' },
|
|
174
|
+
repoTokenUnavailable: { 'zh-CN': '无法获取 {repo} 的 Installation Token', en: 'Cannot obtain an Installation Token for {repo}' },
|
|
175
|
+
missingIdentity: { 'zh-CN': '无法解析 GitHub App Bot 身份', en: 'Cannot resolve the GitHub App bot identity' },
|
|
176
|
+
missingWorkspace: { 'zh-CN': '工作区不存在: {path},请先准备工作区', en: 'Workspace does not exist: {path}. Prepare the workspace first' },
|
|
177
|
+
missingToken: { 'zh-CN': 'Installation Token 不可用', en: 'Installation Token is unavailable' },
|
|
178
|
+
noChanges: { 'zh-CN': '没有可提交的变更', en: 'No changes to commit' },
|
|
179
|
+
pushed: { 'zh-CN': '已 push 到 origin/{branch}', en: 'Pushed to origin/{branch}' },
|
|
180
|
+
});
|