deploy-vir 3.0.1 → 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 +16 -0
- package/dist/git.js +33 -5
- package/dist/notifications/slack.js +8 -2
- package/package.json +22 -22
- package/src/config.ts +17 -0
- package/src/git.ts +59 -7
- 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
|
*
|
|
@@ -97,6 +106,13 @@ export type DeployVirBranchConfig = {
|
|
|
97
106
|
enableNotifications?: boolean | undefined;
|
|
98
107
|
}[];
|
|
99
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;
|
|
100
116
|
};
|
|
101
117
|
/**
|
|
102
118
|
* Define a type safe deploy-vir config.
|
package/dist/git.js
CHANGED
|
@@ -100,11 +100,14 @@ export async function pushDeploy(git, branchConfig, repoConfig, remoteName, noti
|
|
|
100
100
|
after: afterCommit,
|
|
101
101
|
},
|
|
102
102
|
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
const resolvedNotifications = resolveNotifications({
|
|
104
|
+
branchConfig,
|
|
105
|
+
enableNotifications,
|
|
106
|
+
globalNotifications: notifications,
|
|
107
|
+
repoConfig,
|
|
108
|
+
});
|
|
109
|
+
if (resolvedNotifications.length) {
|
|
110
|
+
await sendNotifications(resolvedNotifications, {
|
|
108
111
|
branchConfig,
|
|
109
112
|
deployResult,
|
|
110
113
|
repoConfig,
|
|
@@ -113,3 +116,28 @@ export async function pushDeploy(git, branchConfig, repoConfig, remoteName, noti
|
|
|
113
116
|
return deployResult;
|
|
114
117
|
});
|
|
115
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.0
|
|
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
|
*
|
|
@@ -103,6 +113,13 @@ export type DeployVirBranchConfig = {
|
|
|
103
113
|
enableNotifications?: boolean | undefined;
|
|
104
114
|
}[];
|
|
105
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;
|
|
106
123
|
};
|
|
107
124
|
|
|
108
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,13 +209,15 @@ export async function pushDeploy(
|
|
|
208
209
|
},
|
|
209
210
|
};
|
|
210
211
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
|
|
212
|
+
const resolvedNotifications = resolveNotifications({
|
|
213
|
+
branchConfig,
|
|
214
|
+
enableNotifications,
|
|
215
|
+
globalNotifications: notifications,
|
|
216
|
+
repoConfig,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
if (resolvedNotifications.length) {
|
|
220
|
+
await sendNotifications(resolvedNotifications, {
|
|
218
221
|
branchConfig,
|
|
219
222
|
deployResult,
|
|
220
223
|
repoConfig,
|
|
@@ -225,3 +228,52 @@ export async function pushDeploy(
|
|
|
225
228
|
},
|
|
226
229
|
);
|
|
227
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
|
}
|