deploy-vir 3.0.0 → 3.1.0
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/config.d.ts +17 -0
- package/dist/git.js +33 -2
- package/dist/notifications/slack.js +8 -2
- package/package.json +22 -22
- package/src/config.ts +18 -0
- package/src/git.ts +59 -2
- package/src/notifications/slack.ts +8 -2
package/dist/config.d.ts
CHANGED
|
@@ -52,6 +52,15 @@ export type SlackNotificationConfig = {
|
|
|
52
52
|
* @category Config
|
|
53
53
|
*/
|
|
54
54
|
export type NotificationConfig = SlackNotificationConfig;
|
|
55
|
+
/**
|
|
56
|
+
* A deploy-level notification override. Same as {@link NotificationConfig} but `webhookUrl` is
|
|
57
|
+
* optional — when omitted, the first matching top-level notification's `webhookUrl` is used.
|
|
58
|
+
*
|
|
59
|
+
* @category Config
|
|
60
|
+
*/
|
|
61
|
+
export type DeployNotificationConfig = Omit<SlackNotificationConfig, 'webhookUrl'> & {
|
|
62
|
+
webhookUrl?: string | undefined;
|
|
63
|
+
};
|
|
55
64
|
/**
|
|
56
65
|
* A repo config for deploying.
|
|
57
66
|
*
|
|
@@ -96,6 +105,14 @@ export type DeployVirBranchConfig = {
|
|
|
96
105
|
toBranch: string;
|
|
97
106
|
enableNotifications?: boolean | undefined;
|
|
98
107
|
}[];
|
|
108
|
+
enableNotifications?: boolean | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Deploy-level notification overrides. When set, these are used instead of the top-level
|
|
111
|
+
* notifications. If a notification here omits `webhookUrl`, the first top-level notification
|
|
112
|
+
* with the same `target` provides it. Setting this also implicitly enables notifications for
|
|
113
|
+
* this deploy.
|
|
114
|
+
*/
|
|
115
|
+
notifications?: DeployNotificationConfig[] | undefined;
|
|
99
116
|
};
|
|
100
117
|
/**
|
|
101
118
|
* Define a type safe deploy-vir config.
|
package/dist/git.js
CHANGED
|
@@ -100,8 +100,14 @@ export async function pushDeploy(git, branchConfig, repoConfig, remoteName, noti
|
|
|
100
100
|
after: afterCommit,
|
|
101
101
|
},
|
|
102
102
|
};
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
const resolvedNotifications = resolveNotifications({
|
|
104
|
+
branchConfig,
|
|
105
|
+
enableNotifications,
|
|
106
|
+
globalNotifications: notifications,
|
|
107
|
+
repoConfig,
|
|
108
|
+
});
|
|
109
|
+
if (resolvedNotifications.length) {
|
|
110
|
+
await sendNotifications(resolvedNotifications, {
|
|
105
111
|
branchConfig,
|
|
106
112
|
deployResult,
|
|
107
113
|
repoConfig,
|
|
@@ -110,3 +116,28 @@ export async function pushDeploy(git, branchConfig, repoConfig, remoteName, noti
|
|
|
110
116
|
return deployResult;
|
|
111
117
|
});
|
|
112
118
|
}
|
|
119
|
+
function resolveNotifications({ branchConfig, enableNotifications, globalNotifications, repoConfig, }) {
|
|
120
|
+
if (branchConfig.notifications?.length) {
|
|
121
|
+
return resolveDeployNotifications(branchConfig.notifications, globalNotifications);
|
|
122
|
+
}
|
|
123
|
+
const notificationsEnabled = repoConfig.enableNotifications || enableNotifications || branchConfig.enableNotifications;
|
|
124
|
+
if (notificationsEnabled && globalNotifications?.length) {
|
|
125
|
+
return [...globalNotifications];
|
|
126
|
+
}
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
function resolveDeployNotifications(deployNotifications, globalNotifications) {
|
|
130
|
+
return deployNotifications.map((deployNotification) => {
|
|
131
|
+
if (deployNotification.webhookUrl) {
|
|
132
|
+
return deployNotification;
|
|
133
|
+
}
|
|
134
|
+
const globalWebhookUrl = globalNotifications?.[0]?.webhookUrl;
|
|
135
|
+
if (!globalWebhookUrl) {
|
|
136
|
+
throw new KnownError(`Deploy notification for target '${deployNotification.target}' is missing webhookUrl and no top-level notification was found to fall back on.`);
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
...deployNotification,
|
|
140
|
+
webhookUrl: globalWebhookUrl,
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
}
|
|
@@ -27,7 +27,10 @@ function chunkSectionLines(lines) {
|
|
|
27
27
|
const latestSection = sectionLines.slice(-1)[0];
|
|
28
28
|
const currentSection = latestSection && latestSection.length + line.length < slackMaxSectionLength
|
|
29
29
|
? latestSection
|
|
30
|
-
: pushAndGet(sectionLines, {
|
|
30
|
+
: pushAndGet(sectionLines, {
|
|
31
|
+
length: 0,
|
|
32
|
+
lines: [],
|
|
33
|
+
});
|
|
31
34
|
currentSection.length += line.length;
|
|
32
35
|
currentSection.lines.push(line);
|
|
33
36
|
});
|
|
@@ -107,7 +110,10 @@ export async function sendNotificationToSlack({ deployResult: { deployCommits: {
|
|
|
107
110
|
];
|
|
108
111
|
await sendSlackMessage(notification, {
|
|
109
112
|
attachments: [],
|
|
110
|
-
channel: addPrefix({
|
|
113
|
+
channel: addPrefix({
|
|
114
|
+
value: notification.channelName,
|
|
115
|
+
prefix: '#',
|
|
116
|
+
}),
|
|
111
117
|
blocks,
|
|
112
118
|
});
|
|
113
119
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deploy-vir",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Deploy a branch to another branch with notifications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deploy",
|
|
@@ -41,51 +41,51 @@
|
|
|
41
41
|
"test:update": "npm run test update"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@augment-vir/assert": "^31.
|
|
45
|
-
"@augment-vir/common": "^31.
|
|
46
|
-
"@augment-vir/node": "^31.
|
|
47
|
-
"@inquirer/prompts": "^8.2
|
|
48
|
-
"@slack/web-api": "^7.
|
|
44
|
+
"@augment-vir/assert": "^31.68.2",
|
|
45
|
+
"@augment-vir/common": "^31.68.2",
|
|
46
|
+
"@augment-vir/node": "^31.68.2",
|
|
47
|
+
"@inquirer/prompts": "^8.3.2",
|
|
48
|
+
"@slack/web-api": "^7.15.0",
|
|
49
49
|
"cli-vir": "^1.0.3",
|
|
50
|
-
"simple-git": "^3.
|
|
50
|
+
"simple-git": "^3.33.0",
|
|
51
51
|
"tsx": "^4.21.0",
|
|
52
52
|
"url-vir": "^2.1.7"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@eslint/eslintrc": "^3.3.
|
|
55
|
+
"@eslint/eslintrc": "^3.3.5",
|
|
56
56
|
"@eslint/js": "^9.39.2",
|
|
57
|
-
"@stylistic/eslint-plugin": "^5.
|
|
57
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
58
58
|
"@stylistic/eslint-plugin-ts": "^4.4.1",
|
|
59
|
-
"@types/node": "^25.
|
|
60
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
61
|
-
"cspell": "^9.
|
|
62
|
-
"dependency-cruiser": "^17.3.
|
|
63
|
-
"esbuild": "^0.27.
|
|
59
|
+
"@types/node": "^25.5.0",
|
|
60
|
+
"@typescript-eslint/eslint-plugin": "^8.57.1",
|
|
61
|
+
"cspell": "^9.7.0",
|
|
62
|
+
"dependency-cruiser": "^17.3.9",
|
|
63
|
+
"esbuild": "^0.27.4",
|
|
64
64
|
"eslint": "^9.39.2",
|
|
65
65
|
"eslint-config-prettier": "^10.1.8",
|
|
66
|
-
"eslint-plugin-jsdoc": "^62.
|
|
66
|
+
"eslint-plugin-jsdoc": "^62.8.0",
|
|
67
67
|
"eslint-plugin-monorepo-cop": "^1.0.2",
|
|
68
|
-
"eslint-plugin-playwright": "^2.
|
|
68
|
+
"eslint-plugin-playwright": "^2.9.0",
|
|
69
69
|
"eslint-plugin-prettier": "^5.5.5",
|
|
70
70
|
"eslint-plugin-require-extensions": "^0.1.3",
|
|
71
|
-
"eslint-plugin-sonarjs": "^
|
|
71
|
+
"eslint-plugin-sonarjs": "^4.0.2",
|
|
72
72
|
"eslint-plugin-unicorn": "^63.0.0",
|
|
73
73
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
74
74
|
"markdown-code-example-inserter": "^3.0.3",
|
|
75
|
-
"npm-check-updates": "^19.
|
|
75
|
+
"npm-check-updates": "^19.6.5",
|
|
76
76
|
"prettier": "~3.3.3",
|
|
77
77
|
"prettier-plugin-interpolated-html-tags": "^2.0.1",
|
|
78
78
|
"prettier-plugin-jsdoc": "^1.8.0",
|
|
79
|
-
"prettier-plugin-multiline-arrays": "^4.1.
|
|
79
|
+
"prettier-plugin-multiline-arrays": "^4.1.5",
|
|
80
80
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
81
|
-
"prettier-plugin-packagejson": "^3.0.
|
|
81
|
+
"prettier-plugin-packagejson": "^3.0.2",
|
|
82
82
|
"prettier-plugin-sort-json": "^4.2.0",
|
|
83
83
|
"prettier-plugin-toml": "^2.0.6",
|
|
84
84
|
"runstorm": "^1.0.0",
|
|
85
85
|
"typedoc": "^0.28.17",
|
|
86
86
|
"typescript": "^5.9.3",
|
|
87
|
-
"typescript-eslint": "^8.
|
|
88
|
-
"virmator": "^14.
|
|
87
|
+
"typescript-eslint": "^8.57.1",
|
|
88
|
+
"virmator": "^14.9.1"
|
|
89
89
|
},
|
|
90
90
|
"engines": {
|
|
91
91
|
"node": ">=22"
|
package/src/config.ts
CHANGED
|
@@ -57,6 +57,16 @@ export type SlackNotificationConfig = {
|
|
|
57
57
|
// eslint-disable-next-line sonarjs/redundant-type-aliases
|
|
58
58
|
export type NotificationConfig = SlackNotificationConfig;
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* A deploy-level notification override. Same as {@link NotificationConfig} but `webhookUrl` is
|
|
62
|
+
* optional — when omitted, the first matching top-level notification's `webhookUrl` is used.
|
|
63
|
+
*
|
|
64
|
+
* @category Config
|
|
65
|
+
*/
|
|
66
|
+
export type DeployNotificationConfig = Omit<SlackNotificationConfig, 'webhookUrl'> & {
|
|
67
|
+
webhookUrl?: string | undefined;
|
|
68
|
+
};
|
|
69
|
+
|
|
60
70
|
/**
|
|
61
71
|
* A repo config for deploying.
|
|
62
72
|
*
|
|
@@ -102,6 +112,14 @@ export type DeployVirBranchConfig = {
|
|
|
102
112
|
toBranch: string;
|
|
103
113
|
enableNotifications?: boolean | undefined;
|
|
104
114
|
}[];
|
|
115
|
+
enableNotifications?: boolean | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Deploy-level notification overrides. When set, these are used instead of the top-level
|
|
118
|
+
* notifications. If a notification here omits `webhookUrl`, the first top-level notification
|
|
119
|
+
* with the same `target` provides it. Setting this also implicitly enables notifications for
|
|
120
|
+
* this deploy.
|
|
121
|
+
*/
|
|
122
|
+
notifications?: DeployNotificationConfig[] | undefined;
|
|
105
123
|
};
|
|
106
124
|
|
|
107
125
|
/**
|
package/src/git.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {awaitedBlockingMap, log, logColors} from '@augment-vir/common';
|
|
|
3
3
|
import {confirm} from '@inquirer/prompts';
|
|
4
4
|
import {type DefaultLogFields, type ListLogLine, type SimpleGit} from 'simple-git';
|
|
5
5
|
import {
|
|
6
|
+
type DeployNotificationConfig,
|
|
6
7
|
type DeployVirBranchConfig,
|
|
7
8
|
type DeployVirRepoConfig,
|
|
8
9
|
type NotificationConfig,
|
|
@@ -208,8 +209,15 @@ export async function pushDeploy(
|
|
|
208
209
|
},
|
|
209
210
|
};
|
|
210
211
|
|
|
211
|
-
|
|
212
|
-
|
|
212
|
+
const resolvedNotifications = resolveNotifications({
|
|
213
|
+
branchConfig,
|
|
214
|
+
enableNotifications,
|
|
215
|
+
globalNotifications: notifications,
|
|
216
|
+
repoConfig,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
if (resolvedNotifications.length) {
|
|
220
|
+
await sendNotifications(resolvedNotifications, {
|
|
213
221
|
branchConfig,
|
|
214
222
|
deployResult,
|
|
215
223
|
repoConfig,
|
|
@@ -220,3 +228,52 @@ export async function pushDeploy(
|
|
|
220
228
|
},
|
|
221
229
|
);
|
|
222
230
|
}
|
|
231
|
+
|
|
232
|
+
function resolveNotifications({
|
|
233
|
+
branchConfig,
|
|
234
|
+
enableNotifications,
|
|
235
|
+
globalNotifications,
|
|
236
|
+
repoConfig,
|
|
237
|
+
}: Readonly<{
|
|
238
|
+
branchConfig: Readonly<DeployVirBranchConfig>;
|
|
239
|
+
enableNotifications: boolean | undefined;
|
|
240
|
+
globalNotifications: ReadonlyArray<Readonly<NotificationConfig>> | undefined;
|
|
241
|
+
repoConfig: Readonly<DeployVirRepoConfig>;
|
|
242
|
+
}>): NotificationConfig[] {
|
|
243
|
+
if (branchConfig.notifications?.length) {
|
|
244
|
+
return resolveDeployNotifications(branchConfig.notifications, globalNotifications);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const notificationsEnabled =
|
|
248
|
+
repoConfig.enableNotifications || enableNotifications || branchConfig.enableNotifications;
|
|
249
|
+
|
|
250
|
+
if (notificationsEnabled && globalNotifications?.length) {
|
|
251
|
+
return [...globalNotifications];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function resolveDeployNotifications(
|
|
258
|
+
deployNotifications: ReadonlyArray<Readonly<DeployNotificationConfig>>,
|
|
259
|
+
globalNotifications: ReadonlyArray<Readonly<NotificationConfig>> | undefined,
|
|
260
|
+
): NotificationConfig[] {
|
|
261
|
+
return deployNotifications.map((deployNotification): NotificationConfig => {
|
|
262
|
+
if (deployNotification.webhookUrl) {
|
|
263
|
+
return deployNotification as NotificationConfig;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const globalWebhookUrl = globalNotifications?.[0]?.webhookUrl;
|
|
267
|
+
|
|
268
|
+
if (!globalWebhookUrl) {
|
|
269
|
+
throw new KnownError(
|
|
270
|
+
`Deploy notification for target '${deployNotification.target}' is missing webhookUrl and no top-level notification was found to fall back on.`,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
...deployNotification,
|
|
276
|
+
webhookUrl: globalWebhookUrl,
|
|
277
|
+
};
|
|
278
|
+
});
|
|
279
|
+
}
|
|
@@ -39,7 +39,10 @@ function chunkSectionLines(lines: ReadonlyArray<string>): string[][] {
|
|
|
39
39
|
const currentSection =
|
|
40
40
|
latestSection && latestSection.length + line.length < slackMaxSectionLength
|
|
41
41
|
? latestSection
|
|
42
|
-
: pushAndGet(sectionLines, {
|
|
42
|
+
: pushAndGet(sectionLines, {
|
|
43
|
+
length: 0,
|
|
44
|
+
lines: [],
|
|
45
|
+
});
|
|
43
46
|
currentSection.length += line.length;
|
|
44
47
|
currentSection.lines.push(line);
|
|
45
48
|
});
|
|
@@ -139,7 +142,10 @@ export async function sendNotificationToSlack({
|
|
|
139
142
|
|
|
140
143
|
await sendSlackMessage(notification, {
|
|
141
144
|
attachments: [],
|
|
142
|
-
channel: addPrefix({
|
|
145
|
+
channel: addPrefix({
|
|
146
|
+
value: notification.channelName,
|
|
147
|
+
prefix: '#',
|
|
148
|
+
}),
|
|
143
149
|
blocks,
|
|
144
150
|
});
|
|
145
151
|
}
|