@stacksjs/buddy 0.72.56 → 0.72.57
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/deploy-notify.d.ts +8 -0
- package/dist/deploy-notify.js +1 -1
- package/package.json +51 -51
package/dist/deploy-notify.d.ts
CHANGED
|
@@ -16,6 +16,14 @@ export declare function buildDeployMessage(outcome: DeployOutcome, env?: Record<
|
|
|
16
16
|
* actually delivered, which is what the tests assert on.
|
|
17
17
|
*/
|
|
18
18
|
export declare function notifyDeployOutcome(outcome: DeployOutcome, config?: DeployNotifyConfig): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* A message for the terminal, however the failure was thrown.
|
|
21
|
+
*
|
|
22
|
+
* A thrown string, a rejected promise carrying an object, and an Error with an
|
|
23
|
+
* empty message all reach here, and "undefined" on the way out is barely
|
|
24
|
+
* better than the silence this replaced.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getDeployErrorMessage(error: unknown): string;
|
|
19
27
|
/**
|
|
20
28
|
* Wrap a deploy command handler so its outcome is announced exactly once,
|
|
21
29
|
* whatever provider ran and however it failed.
|
package/dist/deploy-notify.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import process from"node:process";import{sendToDiscord,sendToSlack,sendToTeams}from"@stacksjs/chat";import{log}from"@stacksjs/logging";import{ExitCode}from"@stacksjs/types";export function driverForWebhookUrl(url){let host="";try{host=new URL(url).hostname.toLowerCase()}catch{return"slack"}if(host.endsWith("discord.com")||host.endsWith("discordapp.com"))return"discord";if(host.endsWith("office.com")||host.endsWith("office365.com")||host.endsWith("outlook.com"))return"teams";return"slack"}export function resolveDeployNotifyConfig(env=process.env){const url=env.DEPLOY_WEBHOOK_URL?.trim();if(!url)return{};const rawDriver=env.DEPLOY_WEBHOOK_DRIVER?.trim().toLowerCase();return{url,driver:(rawDriver==="slack"||rawDriver==="discord"||rawDriver==="teams"?rawDriver:void 0)??driverForWebhookUrl(url),notifyOn:env.DEPLOY_WEBHOOK_NOTIFY?.trim().toLowerCase()==="all"?"all":"failure"}}function summarizeError(error,limit=1200){if(error==null)return"No error detail was captured.";const trimmed=(error instanceof Error?error.stack||error.message:String(error)).trim();return trimmed.length>limit?`${trimmed.slice(0,limit)}
|
|
2
2
|
\u2026 (truncated)`:trimmed}function formatDuration(ms){if(typeof ms!=="number"||!Number.isFinite(ms)||ms<0)return null;const total=Math.round(ms/1000);return total<60?`${total}s`:`${Math.floor(total/60)}m ${total%60}s`}function ciContext(env=process.env){const lines=[],repo=env.GITHUB_REPOSITORY,sha=env.GITHUB_SHA;if(repo&&sha)lines.push(`Commit: ${repo}@${sha.slice(0,7)}`);else if(sha)lines.push(`Commit: ${sha.slice(0,7)}`);if(repo&&env.GITHUB_RUN_ID)lines.push(`Run: ${env.GITHUB_SERVER_URL||"https://github.com"}/${repo}/actions/runs/${env.GITHUB_RUN_ID}`);return lines}export function buildDeployMessage(outcome,env=process.env){const failed=outcome.status==="failed",target=[outcome.project,outcome.environment].filter(Boolean).join(" \xB7 ")||"project",lines=[failed?`\uD83D\uDD34 Deploy FAILED - ${target}`:`\u2705 Deploy succeeded - ${target}`];if(outcome.provider)lines.push(`Provider: ${outcome.provider}`);const duration=formatDuration(outcome.durationMs);if(duration)lines.push(`Duration: ${duration}`);lines.push(...ciContext(env));if(failed){lines.push("");lines.push("```");lines.push(summarizeError(outcome.error));lines.push("```");const envLabel=outcome.environment||"The target environment";lines.push(`${envLabel==="production"?"Production":envLabel} is still serving the previous release.`)}return lines.join(`
|
|
3
|
-
`)}export async function notifyDeployOutcome(outcome,config=resolveDeployNotifyConfig()){try{if(!config.url){log.debug("[deploy] no DEPLOY_WEBHOOK_URL set - skipping deploy notification");return!1}const notifyOn=config.notifyOn??"failure";if(outcome.status==="succeeded"&¬ifyOn!=="all"){log.debug('[deploy] deploy succeeded and DEPLOY_WEBHOOK_NOTIFY is not "all" - not notifying');return!1}const driver=config.driver??driverForWebhookUrl(config.url),message=buildDeployMessage(outcome),result=driver==="discord"?await sendToDiscord(config.url,message):driver==="teams"?await sendToTeams(config.url,message):await sendToSlack(config.url,message);if(!result?.success){log.warn(`[deploy] deploy notification to ${driver} failed: ${result?.message??"unknown error"}`);return!1}log.debug(`[deploy] deploy ${outcome.status} notification sent via ${driver}`);return!0}catch(error){log.warn(`[deploy] deploy notification could not be sent: ${error instanceof Error?error.message:String(error)}`);return!1}}export function withDeployNotification(action){return async(...args)=>{const startedAt=Date.now(),
|
|
3
|
+
`)}export async function notifyDeployOutcome(outcome,config=resolveDeployNotifyConfig()){try{if(!config.url){log.debug("[deploy] no DEPLOY_WEBHOOK_URL set - skipping deploy notification");return!1}const notifyOn=config.notifyOn??"failure";if(outcome.status==="succeeded"&¬ifyOn!=="all"){log.debug('[deploy] deploy succeeded and DEPLOY_WEBHOOK_NOTIFY is not "all" - not notifying');return!1}const driver=config.driver??driverForWebhookUrl(config.url),message=buildDeployMessage(outcome),result=driver==="discord"?await sendToDiscord(config.url,message):driver==="teams"?await sendToTeams(config.url,message):await sendToSlack(config.url,message);if(!result?.success){log.warn(`[deploy] deploy notification to ${driver} failed: ${result?.message??"unknown error"}`);return!1}log.debug(`[deploy] deploy ${outcome.status} notification sent via ${driver}`);return!0}catch(error){log.warn(`[deploy] deploy notification could not be sent: ${error instanceof Error?error.message:String(error)}`);return!1}}export function getDeployErrorMessage(error){if(error instanceof Error&&error.message)return error.message;if(typeof error==="string"&&error)return error;try{const rendered=JSON.stringify(error);if(rendered&&rendered!=="{}"&&rendered!=="null")return rendered}catch{}return`${String(error)} (no message; re-run with --verbose for the stack)`}export function withDeployNotification(action){return async(...args)=>{const startedAt=Date.now(),environment=typeof args[0]==="string"&&args[0]?args[0]:"production",context={environment,provider:process.env.CLOUD_PROVIDER||void 0,project:process.env.APP_NAME||void 0};try{await action(...args)}catch(error){log.error(`Deploy to ${environment} failed: ${getDeployErrorMessage(error)}`);const stack=error instanceof Error?error.stack:void 0;if(stack)log.debug(stack);await notifyDeployOutcome({...context,status:"failed",durationMs:Date.now()-startedAt,error});process.exit(ExitCode.FatalError)}await notifyDeployOutcome({...context,status:"succeeded",durationMs:Date.now()-startedAt})}}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/buddy",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.72.
|
|
5
|
+
"version": "0.72.57",
|
|
6
6
|
"description": "Meet Buddy. The Stacks runtime.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -95,62 +95,62 @@
|
|
|
95
95
|
"prepublishOnly": "bun run build"
|
|
96
96
|
},
|
|
97
97
|
"dependencies": {
|
|
98
|
-
"@stacksjs/actions": "^0.72.
|
|
99
|
-
"@stacksjs/ai": "^0.72.
|
|
100
|
-
"@stacksjs/alias": "^0.72.
|
|
101
|
-
"@stacksjs/analytics": "^0.72.
|
|
102
|
-
"@stacksjs/arrays": "^0.72.
|
|
103
|
-
"@stacksjs/auth": "^0.72.
|
|
104
|
-
"@stacksjs/browser-extension": "^0.72.
|
|
105
|
-
"@stacksjs/build": "^0.72.
|
|
106
|
-
"@stacksjs/cache": "^0.72.
|
|
107
|
-
"@stacksjs/chat": "^0.72.
|
|
98
|
+
"@stacksjs/actions": "^0.72.57",
|
|
99
|
+
"@stacksjs/ai": "^0.72.57",
|
|
100
|
+
"@stacksjs/alias": "^0.72.57",
|
|
101
|
+
"@stacksjs/analytics": "^0.72.57",
|
|
102
|
+
"@stacksjs/arrays": "^0.72.57",
|
|
103
|
+
"@stacksjs/auth": "^0.72.57",
|
|
104
|
+
"@stacksjs/browser-extension": "^0.72.57",
|
|
105
|
+
"@stacksjs/build": "^0.72.57",
|
|
106
|
+
"@stacksjs/cache": "^0.72.57",
|
|
107
|
+
"@stacksjs/chat": "^0.72.57",
|
|
108
108
|
"@stacksjs/clapp": "^0.2.12",
|
|
109
|
-
"@stacksjs/cli": "^0.72.
|
|
110
|
-
"@stacksjs/cloud": "^0.72.
|
|
111
|
-
"@stacksjs/cms": "^0.72.
|
|
112
|
-
"@stacksjs/collections": "^0.72.
|
|
113
|
-
"@stacksjs/config": "^0.72.
|
|
114
|
-
"@stacksjs/database": "^0.72.
|
|
115
|
-
"@stacksjs/desktop-build": "^0.72.
|
|
116
|
-
"@stacksjs/dns": "^0.72.
|
|
109
|
+
"@stacksjs/cli": "^0.72.57",
|
|
110
|
+
"@stacksjs/cloud": "^0.72.57",
|
|
111
|
+
"@stacksjs/cms": "^0.72.57",
|
|
112
|
+
"@stacksjs/collections": "^0.72.57",
|
|
113
|
+
"@stacksjs/config": "^0.72.57",
|
|
114
|
+
"@stacksjs/database": "^0.72.57",
|
|
115
|
+
"@stacksjs/desktop-build": "^0.72.57",
|
|
116
|
+
"@stacksjs/dns": "^0.72.57",
|
|
117
117
|
"@stacksjs/dnsx": "^0.2.3",
|
|
118
|
-
"@stacksjs/email": "^0.72.
|
|
119
|
-
"@stacksjs/enums": "^0.72.
|
|
120
|
-
"@stacksjs/env": "^0.72.
|
|
121
|
-
"@stacksjs/error-handling": "^0.72.
|
|
122
|
-
"@stacksjs/events": "^0.72.
|
|
123
|
-
"@stacksjs/git": "^0.72.
|
|
118
|
+
"@stacksjs/email": "^0.72.57",
|
|
119
|
+
"@stacksjs/enums": "^0.72.57",
|
|
120
|
+
"@stacksjs/env": "^0.72.57",
|
|
121
|
+
"@stacksjs/error-handling": "^0.72.57",
|
|
122
|
+
"@stacksjs/events": "^0.72.57",
|
|
123
|
+
"@stacksjs/git": "^0.72.57",
|
|
124
124
|
"@stacksjs/gitit": "^0.2.5",
|
|
125
|
-
"@stacksjs/health": "^0.72.
|
|
125
|
+
"@stacksjs/health": "^0.72.57",
|
|
126
126
|
"@stacksjs/httx": "^0.1.10",
|
|
127
|
-
"@stacksjs/image": "^0.72.
|
|
128
|
-
"@stacksjs/lint": "^0.72.
|
|
129
|
-
"@stacksjs/logging": "^0.72.
|
|
130
|
-
"@stacksjs/notifications": "^0.72.
|
|
131
|
-
"@stacksjs/objects": "^0.72.
|
|
132
|
-
"@stacksjs/orm": "^0.72.
|
|
133
|
-
"@stacksjs/path": "^0.72.
|
|
134
|
-
"@stacksjs/payments": "^0.72.
|
|
135
|
-
"@stacksjs/realtime": "^0.72.
|
|
136
|
-
"@stacksjs/router": "^0.72.
|
|
127
|
+
"@stacksjs/image": "^0.72.57",
|
|
128
|
+
"@stacksjs/lint": "^0.72.57",
|
|
129
|
+
"@stacksjs/logging": "^0.72.57",
|
|
130
|
+
"@stacksjs/notifications": "^0.72.57",
|
|
131
|
+
"@stacksjs/objects": "^0.72.57",
|
|
132
|
+
"@stacksjs/orm": "^0.72.57",
|
|
133
|
+
"@stacksjs/path": "^0.72.57",
|
|
134
|
+
"@stacksjs/payments": "^0.72.57",
|
|
135
|
+
"@stacksjs/realtime": "^0.72.57",
|
|
136
|
+
"@stacksjs/router": "^0.72.57",
|
|
137
137
|
"@stacksjs/rpx": "^0.11.42",
|
|
138
|
-
"@stacksjs/scheduler": "^0.72.
|
|
139
|
-
"@stacksjs/search-engine": "^0.72.
|
|
140
|
-
"@stacksjs/security": "^0.72.
|
|
141
|
-
"@stacksjs/server": "^0.72.
|
|
142
|
-
"@stacksjs/sites": "^0.72.
|
|
143
|
-
"@stacksjs/skills": "^0.72.
|
|
144
|
-
"@stacksjs/storage": "^0.72.
|
|
145
|
-
"@stacksjs/strings": "^0.72.
|
|
146
|
-
"@stacksjs/testing": "^0.72.
|
|
147
|
-
"@stacksjs/tinker": "^0.72.
|
|
138
|
+
"@stacksjs/scheduler": "^0.72.57",
|
|
139
|
+
"@stacksjs/search-engine": "^0.72.57",
|
|
140
|
+
"@stacksjs/security": "^0.72.57",
|
|
141
|
+
"@stacksjs/server": "^0.72.57",
|
|
142
|
+
"@stacksjs/sites": "^0.72.57",
|
|
143
|
+
"@stacksjs/skills": "^0.72.57",
|
|
144
|
+
"@stacksjs/storage": "^0.72.57",
|
|
145
|
+
"@stacksjs/strings": "^0.72.57",
|
|
146
|
+
"@stacksjs/testing": "^0.72.57",
|
|
147
|
+
"@stacksjs/tinker": "^0.72.57",
|
|
148
148
|
"@stacksjs/ts-cloud": "^0.11.4",
|
|
149
|
-
"@stacksjs/tunnel": "^0.72.
|
|
150
|
-
"@stacksjs/types": "^0.72.
|
|
151
|
-
"@stacksjs/ui": "^0.72.
|
|
152
|
-
"@stacksjs/utils": "^0.72.
|
|
153
|
-
"@stacksjs/validation": "^0.72.
|
|
149
|
+
"@stacksjs/tunnel": "^0.72.57",
|
|
150
|
+
"@stacksjs/types": "^0.72.57",
|
|
151
|
+
"@stacksjs/ui": "^0.72.57",
|
|
152
|
+
"@stacksjs/utils": "^0.72.57",
|
|
153
|
+
"@stacksjs/validation": "^0.72.57",
|
|
154
154
|
"ajv": "^8.20.0",
|
|
155
155
|
"ajv-formats": "^3.0.1",
|
|
156
156
|
"ts-pantry": "^0.11.35"
|