diff --git a/.github/images/build-failed.png b/.github/images/build-failed.png index 71a8ace..a65ee40 100644 Binary files a/.github/images/build-failed.png and b/.github/images/build-failed.png differ diff --git a/.github/images/old-build-failed.png b/.github/images/old-build-failed.png new file mode 100644 index 0000000..71a8ace Binary files /dev/null and b/.github/images/old-build-failed.png differ diff --git a/README.md b/README.md index 230e555..061abee 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Generate API Token go to https://dash.cloudflare.com/profile/api-tokens ## Usage ```yml - name: Await CF Pages and send Slack notification - uses: arddluma/cloudflare-pages-slack-notification@v3.1 + uses: arddluma/cloudflare-pages-slack-notification@v4 with: # Uncomment these two lines if you wish to use the Global API Key (Not recommended!) # accountEmail: ${{ secrets.CF_ACCOUNT_EMAIL }} @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@v3 - name: Await CF Pages and send Slack notification id: cf-pages - uses: arddluma/cloudflare-pages-slack-notification@v3.1 + uses: arddluma/cloudflare-pages-slack-notification@v4 with: # Uncomment these two lines if you wish to use the Global API Key (Not recommended!) # accountEmail: ${{ secrets.CF_ACCOUNT_EMAIL }} diff --git a/dist/action.js b/dist/action.js index 561c3cf..75aba38 100644 --- a/dist/action.js +++ b/dist/action.js @@ -12767,6 +12767,7 @@ var waiting = true; var ghDeployment; var markedAsInProgress = false; async function run() { + var _a2, _b, _c; const accountEmail = core.getInput("accountEmail", { required: false, trimWhitespace: true }); const apiKey = core.getInput("apiKey", { required: false, trimWhitespace: true }); const apiToken = core.getInput("apiToken", { required: false, trimWhitespace: true }); @@ -12776,6 +12777,8 @@ async function run() { const commitHash = core.getInput("commitHash", { required: false, trimWhitespace: true }); const slackWebHook = core.getInput("slackWebHook", { required: false, trimWhitespace: true }); const slack = esm_default(slackWebHook); + const commitUrl = ((_b = (_a2 = import_utils.context.payload) == null ? void 0 : _a2.head_commit) == null ? void 0 : _b.url) || ""; + const actor = ((_c = import_utils.context) == null ? void 0 : _c.actor) || ""; if (!validateAuthInputs(apiToken, accountEmail, apiKey)) { return; } @@ -12806,20 +12809,54 @@ async function run() { } if (latestStage.status === "failed" || latestStage.status === "failure") { waiting = false; - slack.send(`:x: CloudFlare Pages \`${latestStage.name}\` pipeline for project *${project}* \`FAILED\`! + if (slackWebHook) { + const logs = await getCloudflareLogs(authHeaders, accountId, project, deployment.id); + slack.send(`:x: CloudFlare Pages \`${latestStage.name}\` pipeline for project *${project}* \`FAILED\`! Environment: *${deployment.environment}* -Commit: ${import_utils.context.payload.head_commit.url} -Actor: *${import_utils.context.actor}* +Commit: ${commitUrl} +Actor: *${actor}* Deployment ID: *${deployment.id}* -Checkout `).then(() => { - console.log(`Slack message for ${latestStage.name} failed pipeline sent!`); - }).catch((err) => { - console.error(err); - }); +Deployment Logs: ${logs} +`).then(() => { + console.log(`Slack message for ${latestStage.name} failed pipeline sent!`); + }).catch((err) => { + console.error(err); + }); + } core.setFailed(`Deployment failed on step: ${latestStage.name}!`); await updateDeployment(token, deployment, "failure"); return; } + async function getCloudflareLogs(authHeaders2, accountId2, project2, deploymentId) { + var _a3; + try { + const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId2}/pages/projects/${project2}/deployments/${deploymentId}/history/logs`, { + headers: { ...authHeaders2 } + }); + if (!res.ok) { + console.error(`Failed to fetch Cloudflare logs - Status code: ${res.status} (${res.statusText})`); + return ""; + } + const body = await res.json(); + if (Array.isArray((_a3 = body.result) == null ? void 0 : _a3.data) && body.result.data.length > 0) { + const logs = body.result.data.map((log) => { + return { + line: log.line + }; + }); + const last20Logs = logs.slice(-20); + const formattedLogs = last20Logs.map((log) => { + return `${log.line}`; + }); + return "```" + formattedLogs.join("\n") + "\n```"; + } else { + return ""; + } + } catch (error2) { + console.error(`Failed to fetch Cloudflare logs: ${error2.message}`); + return ""; + } + } if (latestStage.name === "deploy" && ["success", "failed"].includes(latestStage.status)) { waiting = false; const aliasUrl = deployment.aliases && deployment.aliases.length > 0 ? deployment.aliases[0] : deployment.url; @@ -12831,8 +12868,8 @@ Checkout `).then(() => { - console.log(`Slack message for ${latestStage.name} failed pipeline sent!`); - }).catch((err) => { - console.error(err); - }); + + if (slackWebHook) { + const logs = await getCloudflareLogs(authHeaders, accountId, project, deployment.id); + slack.send(`:x: CloudFlare Pages \`${latestStage.name}\` pipeline for project *${project}* \`FAILED\`!\nEnvironment: *${deployment.environment}*\nCommit: ${commitUrl}\nActor: *${actor}*\nDeployment ID: *${deployment.id}*\nDeployment Logs: ${logs}\n`).then(() => { + console.log(`Slack message for ${latestStage.name} failed pipeline sent!`); + }).catch((err) => { + console.error(err); + }); + } core.setFailed(`Deployment failed on step: ${latestStage.name}!`); await updateDeployment(token, deployment, 'failure'); return; } + async function getCloudflareLogs(authHeaders: AuthHeaders, accountId: string, project: string, deploymentId: string): Promise { + try { + const res: Response = await fetch(`https://api.cloudflare.com/client/v4/accounts/${accountId}/pages/projects/${project}/deployments/${deploymentId}/history/logs`, { + headers: { ...authHeaders }, + }); + + if (!res.ok) { + console.error(`Failed to fetch Cloudflare logs - Status code: ${res.status} (${res.statusText})`); + return ''; + } + const body = await res.json(); + + if (Array.isArray(body.result?.data) && body.result.data.length > 0) { + const logs = body.result.data.map((log: any) => { + return { + line: log.line, + }; + }); + + const last20Logs = logs.slice(-20); + + const formattedLogs = last20Logs.map((log) => { + return `${log.line}`; + }); + + return '```' + formattedLogs.join('\n') + '\n```'; + } else { + return ''; + } + } catch (error) { + console.error(`Failed to fetch Cloudflare logs: ${error.message}`); + return ''; + } + } + if (latestStage.name === 'deploy' && ['success', 'failed'].includes(latestStage.status)) { waiting = false; @@ -87,7 +128,7 @@ export default async function run() { core.setOutput('success', deployment.latest_stage.status === 'success' ? true : false); if (deployment.latest_stage.status === 'success' && true) { - slack.send(`:white_check_mark: CloudFlare Pages \`Deployment\` pipeline for project *${project}* \`SUCCEEDED\`!\nEnvironment: *${deployment.environment}*\nCommit: ${context.payload.head_commit.url}\nActor: *${context.actor}*\nDeployment ID: *${deployment.id}*\nAlias URL: ${aliasUrl}\nDeployment URL: ${deployment.url}\nCheckout `).then(() => { + slack.send(`:white_check_mark: CloudFlare Pages \`Deployment\` pipeline for project *${project}* \`SUCCEEDED\`!\nEnvironment: *${deployment.environment}*\nCommit: ${commitUrl}\nActor: *${actor}*\nDeployment ID: *${deployment.id}*\nAlias URL: ${aliasUrl}\nDeployment URL: ${deployment.url}\nCheckout `).then(() => { console.log('Slack message for DEPLOYMENT succedded pipeline sent!'); }).catch((err) => { console.error(err); @@ -211,4 +252,4 @@ try { core.setFailed(e); // @ts-ignore console.error(e.message + '\n' + e.stack); -} \ No newline at end of file +}