Skip to content

Commit

Permalink
feat: allow including only failed jobs
Browse files Browse the repository at this point in the history
  • Loading branch information
atammy-narmi committed Feb 26, 2024
1 parent 68bf00d commit 21995f5
Show file tree
Hide file tree
Showing 8 changed files with 38,157 additions and 13,340 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use nvm --auto
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v20.11
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ This action will post workflow status notifications into your Slack channel. The
| **slack_webhook_url** | _required_ | Create a Slack Webhook URL using the [Incoming Webhooks App](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks?next_id=0). It is recommended that you create a new secret on your repo `SLACK_WEBHOOK_URL` for holding this value, and passing it to the action with `${{secrets.SLACK_WEBHOOK_URL}}`.
| **repo_token** | _required_ | A token is automatically available in your workflow secrets var. `${{secrets.GITHUB_TOKEN}}`. You can optionally send an alternative self-generated token.
| **include_jobs** | _optional_ | When set to `true`, include individual job status and durations in the slack notification. When `false` only the event status and workflow status lines are included. When set to `on-failure` — individual job status is reported only if workflow failed. Default is `true`.
| **jobs_to_fetch** | _optional_ | Sets the number of jobs to fetch (for workflows with big number of jobs). Default is 30.
| **jobs_to_fetch** | _optional_ | Sets the number of jobs to fetch (for workflows with big number of jobs). Default is 100.
| **jobs_to_include** | _optional_ | Should all jobs be included or only the ones that failed. When set to `failed` only the failed jobs are included in the message. the Default is `all`.
| **include_commit_message** | _optional_ | When set to `true`, include the workflow head commit message title in the slack notification. Default is `false`.
| **channel** | _optional_ | Accepts a Slack channel name where you would like the notifications to appear. Overrides the default channel created with your webhook.
| **name** | _optional_ | Allows you to provide a name for the slack bot user posting the notifications. Overrides the default name created with your webhook.
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ inputs:
description: 'Should the slack notification include individual job status and run times'
required: true
default: "true"
jobs_to_include:
description: 'Should all jobs be included or only the ones that failed'
required: true
default: "all"
include_commit_message:
description: 'Should the slack notification include the head commit message'
required: true
Expand Down
45,158 changes: 35,529 additions & 9,629 deletions dist/index.js

Large diffs are not rendered by default.

6,267 changes: 2,581 additions & 3,686 deletions package-lock.json

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "slack-workflow-status",
"description": "A Github Action for sending Workflow run results to Slack",
"version": "1.1.0",
"version": "1.3.0",
"author": "Anthony Kinson",
"license": "MIT",
"main": "dist/index.js",
Expand All @@ -23,20 +23,20 @@
"test": "jest"
},
"dependencies": {
"@actions/core": ">= 1.10.0",
"@actions/github": ">= 4.0.0",
"@actions/core": ">= 1.10.1",
"@actions/github": ">= 6.0.0",
"@slack/webhook": "^7.0.2"
},
"devDependencies": {
"@types/node": "^14.14.9",
"@typescript-eslint/parser": "^4.8.1",
"@vercel/ncc": "^0.25.1",
"eslint": "^7.13.0",
"eslint-plugin-github": "^4.1.1",
"husky": "^7.0.4",
"js-yaml": "^3.14.0",
"prettier": "2.1.1",
"typescript": "^4.0.2"
"@types/node": "^20.11.20",
"@typescript-eslint/parser": "^7.1.0",
"@vercel/ncc": "^0.38.1",
"eslint": "^8.57.0",
"eslint-plugin-github": "^4.10.1",
"husky": "^9.0.11",
"js-yaml": "^4.1.0",
"prettier": "3.2.5",
"typescript": "^5.3.3"
},
"husky": {
"hooks": {
Expand Down
39 changes: 27 additions & 12 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ interface PullRequest {
}

type IncludeJobs = 'true' | 'false' | 'on-failure'
type JobsToInclude = 'all' | 'failed'
type SlackMessageAttachementFields = MessageAttachment['fields']

process.on('unhandledRejection', handleError)
Expand All @@ -58,6 +59,9 @@ async function main(): Promise<void> {
const include_jobs = core.getInput('include_jobs', {
required: true
}) as IncludeJobs
const jobs_to_include = core.getInput('jobs_to_include', {
required: true
}) as JobsToInclude
const include_commit_message =
core.getInput('include_commit_message', {
required: true
Expand All @@ -72,23 +76,34 @@ async function main(): Promise<void> {
// Auth github with octokit module
const octokit = getOctokit(github_token)
// Fetch workflow run data
const {data: workflow_run} = await octokit.actions.getWorkflowRun({
const {data: workflow_run} = await octokit.rest.actions.getWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
})

// Fetch workflow job information
const {data: jobs_response} = await octokit.actions.listJobsForWorkflowRun({
let included_jobs: any[] = []
await octokit.paginate(octokit.rest.actions.listJobsForWorkflowRun, {
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId,
per_page: parseInt(jobs_to_fetch, 30),
})
per_page: parseInt(jobs_to_fetch, 100),
}).then((jobs_response) => {
if (!jobs_response.jobs || jobs_response.jobs.length === 0) {
return
}

const completed_jobs = jobs_response.jobs.filter(
job => job.status === 'completed'
)
if (jobs_to_include === 'failed') {
included_jobs.push(...jobs_response.jobs.filter(
job => job.conclusion === 'failure'
))
} else {
included_jobs.push(...jobs_response.jobs.filter(
job => job.status === 'completed'
))
}
})

// Configure slack attachment styling
let workflow_color // can be good, danger, warning or a HEX colour (#00FF00)
Expand All @@ -97,14 +112,14 @@ async function main(): Promise<void> {
let job_fields: SlackMessageAttachementFields

if (
completed_jobs.every(job => ['success', 'skipped'].includes(job.conclusion))
included_jobs.every(job => job.conclusion && ['success', 'skipped'].includes(job.conclusion))
) {
workflow_color = 'good'
workflow_msg = 'Success:'
if (include_jobs === 'on-failure') {
job_fields = []
}
} else if (completed_jobs.some(job => job.conclusion === 'cancelled')) {
} else if (included_jobs.some(job => job.conclusion === 'cancelled')) {
workflow_color = 'warning'
workflow_msg = 'Cancelled:'
if (include_jobs === 'on-failure') {
Expand All @@ -121,7 +136,7 @@ async function main(): Promise<void> {
}

// Build Job Data Fields
job_fields ??= completed_jobs.map(job => {
job_fields ??= included_jobs.map(job => {
let job_status_icon

switch (job.conclusion) {
Expand All @@ -139,7 +154,7 @@ async function main(): Promise<void> {

const job_duration = compute_duration({
start: new Date(job.started_at),
end: new Date(job.completed_at)
end: job.completed_at ? new Date(job.completed_at) : new Date(job.started_at)
})

return {
Expand Down Expand Up @@ -178,7 +193,7 @@ async function main(): Promise<void> {
status_string = `${workflow_msg} ${context.actor}'s \`pull_request\` ${pull_requests}`
}

const commit_message = `Commit: ${workflow_run.head_commit.message}`
const commit_message = `Commit: ${workflow_run.head_commit ? workflow_run.head_commit.message : ''}`

// We're using old style attachments rather than the new blocks because:
// - Blocks don't allow colour indicators on messages
Expand Down

0 comments on commit 21995f5

Please sign in to comment.