Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable blocks #221

Merged
merged 1 commit into from Nov 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/slack.yml
Expand Up @@ -42,6 +42,59 @@ fields:
value: "{{jobStatus}}"
short: true

blocks:
# author
- type: context
elements:
- type: image
image_url: '{{sender.html_url}}'
alt_text: '{{sender.login}}'
- type: mrkdwn
text: "*<{{sender.html_url}}|{{sender.login}}>*"

# title
- type: section
text:
type: mrkdwn
text: |
*<{{title_link}}|{{title}}>*

# text
- type: section
text:
type: mrkdwn
text: *text

# fields
- type: section
fields:
- type: mrkdwn
text: |-
*Job Steps*
{{#each jobSteps}}{{#ifneq this.outcome 'skipped'}}{{icon this.outcome}} {{@key}}
{{/ifneq}}{{/each}}
- type: mrkdwn
text: "*Workflow*\n<{{{workflowUrl}}}|{{workflow}}>"
- type: mrkdwn
text: "*Git Ref*\n{{ref}} ({{refType}})"
- type: mrkdwn
text: |-
*Run ID*
<{{workflowRunUrl}}|{{runId}}>
- type: mrkdwn
text: "*Run Number*\n{{runNumber}}"
- type: mrkdwn
text: "*Actor*\n{{actor}}"

# footer
- type: context
elements:
- type: image
image_url: '{{footer_icon}}'
alt_text: satterly
- type: mrkdwn
text: '{{{footer}}} | <!date^{{ts}}^{date_short_pretty} at {time}|{{ts}}>'

footer: >-
<{{repositoryUrl}}|{{repositoryName}}> {{workflow}} #{{runNumber}}

Expand Down
37 changes: 29 additions & 8 deletions .github/workflows/test.yml
Expand Up @@ -2,9 +2,11 @@ name: "build-test"
on: # rebuild any PRs and main branch changes
pull_request:
push:
# branches:
# - master
# - 'releases/*'
branches:
- master
- 'releases/*'
tags:
- 'v*'

env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Expand All @@ -18,8 +20,19 @@ jobs:
- id: build
run: |
npm install
- id: format-check
run: |
npm run format-check
- id: lint
run: |
npm run lint
- uses: ./
with:
status: ${{ job.status }}
channel: '#actions'
message: lint error
if: failure()

test:
runs-on: ubuntu-latest
steps:
Expand All @@ -41,21 +54,30 @@ jobs:
env:
JOB_CONTEXT: ${{ toJson(job) }}
run: echo "$JOB_CONTEXT"
- uses: ./
with:
status: in progress
channel: '#actions'
- id: dump_steps
name: Dump steps context
env:
STEPS_CONTEXT: ${{ toJson(steps) }}
run: echo "$STEPS_CONTEXT"
- id: test
run: |
npm install
npm run test
- uses: ./
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#actions'
config: __tests__/fixtures/slack-legacy.yml
if: always()
- uses: ./
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#actions'
config: __tests__/fixtures/slack-block.yml
if: always()

build:
runs-on: ubuntu-latest
steps:
Expand All @@ -72,5 +94,4 @@ jobs:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#actions'
# message: '[{{shortSha}}] {{title}} -> {{jobStatus}}'
if: always()
180 changes: 180 additions & 0 deletions __tests__/blocks.test.ts
@@ -0,0 +1,180 @@
import * as github from '@actions/github'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
import {send, ConfigOptions} from '../src/slack'
import {readFileSync} from 'fs'
import * as yaml from 'js-yaml'

const url = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
const jobName = 'CI Tests'
const jobStatus = 'failure'
const jobSteps = {
'install-deps': {
outputs: {},
outcome: 'success',
conclusion: 'success'
},
hooks: {
outputs: {},
outcome: 'cancelled',
conclusion: 'cancelled'
},
lint: {
outputs: {},
outcome: 'failure',
conclusion: 'failure'
},
types: {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
},
'unit-test': {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
},
'integration-test': {
outputs: {},
outcome: 'failure',
conclusion: 'failure'
}
}
const channel = '#github-ci'

// mock github context
const dump = JSON.parse(readFileSync('./__tests__/fixtures/push.json', 'utf-8'))

github.context.payload = dump.event
github.context.eventName = dump.event_name
github.context.sha = dump.sha
github.context.ref = dump.ref
github.context.workflow = dump.workflow
github.context.action = dump.action
github.context.actor = dump.actor

process.env.CI = 'true'
process.env.GITHUB_WORKFLOW = 'build-test'
process.env.GITHUB_RUN_ID = '100143423'
process.env.GITHUB_RUN_NUMBER = '8'
process.env.GITHUB_ACTION = 'self2'
process.env.GITHUB_ACTIONS = 'true'
process.env.GITHUB_ACTOR = 'satterly'
process.env.GITHUB_REPOSITORY = 'act10ns/slack'
process.env.GITHUB_EVENT_NAME = 'push'
process.env.GITHUB_EVENT_PATH = '/home/runner/work/_temp/_github_workflow/event.json'
process.env.GITHUB_WORKSPACE = '/home/runner/work/slack/slack'
process.env.GITHUB_SHA = '68d48876e0794fba714cb331a1624af6b20942d8'
process.env.GITHUB_REF = 'refs/heads/master'
process.env.GITHUB_REF_TYPE = 'branch'
process.env.GITHUB_REF_NAME = 'master'
process.env.GITHUB_HEAD_REF = ''
process.env.GITHUB_BASE_REF = ''
process.env.GITHUB_SERVER_URL = 'https://github.com'
process.env.GITHUB_API_URL = 'https://github.com'
process.env.GITHUB_GRAPHQL_URL = 'https://api.github.com/graphql'

test('custom config of slack action using legacy and blocks', async () => {
const mockAxios = new MockAdapter(axios, {delayResponse: 200})

mockAxios
.onPost()
.reply(config => {
console.log(config.data)
return [200, {status: 'ok'}]
})
.onAny()
.reply(500)

let message = undefined

let config = yaml.load(readFileSync('./__tests__/fixtures/slack-blocks.yml', 'utf-8'), {
schema: yaml.FAILSAFE_SCHEMA
}) as ConfigOptions

let res = await send(url, jobName, jobStatus, jobSteps, channel, message, config)
await expect(res).toStrictEqual({text: {status: 'ok'}})

expect(JSON.parse(mockAxios.history.post[0].data)).toStrictEqual({
username: 'GitHub-CI',
icon_url: 'https://octodex.github.com/images/mona-the-rivetertocat.png',
channel: '#github-ci',
attachments: [
{
mrkdwn_in: ['pretext', 'text', 'fields'],
color: '#884EA0',
pretext: 'Triggered via push by satterly action master `68d48876`',
author_name: 'satterly',
author_link: 'https://github.com/satterly',
author_icon: 'https://avatars0.githubusercontent.com/u/615057?v=4',
title: 'GitHub Actions',
title_link: 'https://support.github.com',
text: '*<https://github.com/act10ns/slack/actions/runs/100143423|Workflow _build-test_ job _CI Tests_ triggered by _push_ is _failure_>* for <https://github.com/act10ns/slack/commits/master|`master`>\n<https://github.com/act10ns/slack/compare/db9fe60430a6...68d48876e079|`68d48876`> - 4 commits\n*Commits*\n<https://github.com/act10ns/slack/commit/b1f512300ea6e925e095c51a441fcf30104523aa|`b1f51230`> - wip\n<https://github.com/act10ns/slack/commit/b246b5fdcc2722909503d5a43eb635885aa5fd25|`b246b5fd`> - wip\n<https://github.com/act10ns/slack/commit/553c22356fadc36947653de987dabd8da40cb06b|`553c2235`> - wip\n<https://github.com/act10ns/slack/commit/68d48876e0794fba714cb331a1624af6b20942d8|`68d48876`> - wip\n',
fields: [
{
title: 'Job Steps',
value: ':white_check_mark: install-deps\n:x: hooks\n:grimacing: lint\n:grimacing: integration-test\n',
short: false
}
],
fallback: '[GitHub] build-test #8 CI Tests is failure',
footer: '<https://github.com/act10ns/slack|act10ns/slack> build-test #8',
footer_icon: 'https://github.githubassets.com/favicon.ico',
ts: expect.stringMatching(/[0-9]+/)
},
{
color: '#884EA0',
fallback: '[GitHub] build-test #8 CI Tests is failure',
blocks: [
{
type: 'context',
elements: [
{type: 'image', image_url: 'https://github.com/satterly', alt_text: 'satterly'},
{type: 'mrkdwn', text: '*<https://github.com/satterly|satterly>*'}
]
},
{type: 'section', text: {type: 'mrkdwn', text: '*<https://support.github.com|GitHub Actions>*\n'}},
{
type: 'section',
text: {
type: 'mrkdwn',
text: '*<https://github.com/act10ns/slack/actions/runs/100143423|Workflow _build-test_ job _CI Tests_ triggered by _push_ is _failure_>* for <https://github.com/act10ns/slack/commits/master|`master`>\n<https://github.com/act10ns/slack/compare/db9fe60430a6...68d48876e079|`68d48876`> - 4 commits\n\n*Commits*\n\n<https://github.com/act10ns/slack/commit/b1f512300ea6e925e095c51a441fcf30104523aa|`b1f51230`> - wip\n\n<https://github.com/act10ns/slack/commit/b246b5fdcc2722909503d5a43eb635885aa5fd25|`b246b5fd`> - wip\n\n<https://github.com/act10ns/slack/commit/553c22356fadc36947653de987dabd8da40cb06b|`553c2235`> - wip\n\n<https://github.com/act10ns/slack/commit/68d48876e0794fba714cb331a1624af6b20942d8|`68d48876`> - wip\n\n\n'
}
},
{
type: 'section',
fields: [
{
type: 'mrkdwn',
text: '*Job Steps*\n:white_check_mark: install-deps\n:x: hooks\n:grimacing: lint\n:grimacing: integration-test\n'
},
{
type: 'mrkdwn',
text: '*Workflow*\n<https://github.com/act10ns/slack/actions?query=build-test|build-test>'
},
{type: 'mrkdwn', text: '*Git Ref*\nmaster (branch)'},
{type: 'mrkdwn', text: '*Run ID*\n<https://github.com/act10ns/slack/actions/runs/100143423|100143423>'},
{type: 'mrkdwn', text: '*Run Number*\n8'},
{type: 'mrkdwn', text: '*Actor*\nsatterly'}
]
},
{
type: 'context',
elements: [
{type: 'image', image_url: 'https://github.githubassets.com/favicon.ico', alt_text: 'satterly'},
{
type: 'mrkdwn',
text: expect.stringMatching(
/<https:\/\/github.com\/act10ns\/slack|act10ns\/slack> build-test #8 | <!date^[0-9]+^{date_short_pretty} at {time}|[0-9]+>/
)
}
]
}
]
}
]
})

mockAxios.resetHistory()
mockAxios.reset()
})
4 changes: 2 additions & 2 deletions __tests__/config.test.ts
Expand Up @@ -74,7 +74,7 @@ process.env.GITHUB_SERVER_URL = 'https://github.com'
process.env.GITHUB_API_URL = 'https://github.com'
process.env.GITHUB_GRAPHQL_URL = 'https://api.github.com/graphql'

test('custom config of slack action', async () => {
test('custom config of slack action using legacy attachments', async () => {
const mockAxios = new MockAdapter(axios, {delayResponse: 200})

mockAxios
Expand All @@ -88,7 +88,7 @@ test('custom config of slack action', async () => {

let message = undefined

let config = yaml.load(readFileSync('./__tests__/fixtures/slack.yml', 'utf-8'), {
let config = yaml.load(readFileSync('./__tests__/fixtures/slack-legacy.yml', 'utf-8'), {
schema: yaml.FAILSAFE_SCHEMA
}) as ConfigOptions

Expand Down