Skip to content

Commit

Permalink
Add custom handlebars helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
satterly committed Nov 9, 2021
1 parent cd386bf commit 0d59e96
Show file tree
Hide file tree
Showing 12 changed files with 281 additions and 56 deletions.
4 changes: 2 additions & 2 deletions .github/slack.yml
@@ -1,7 +1,7 @@
username: GitHub-CI
icon_url: https://octodex.github.com/images/femalecodertocat.png

pretext: Triggered via {{eventName}} by {{actor}} {{or action "action"}} {{ref}} `{{diffRef}}`
pretext: Triggered via {{eventName}} by {{actor}} {{default action "action"}} {{ref}} `{{diffRef}}`
title: GitHub Actions
title_link: https://support.github.com

Expand All @@ -11,7 +11,7 @@ text: |
{{#if payload.commits}}
*Commits*
{{#each payload.commits}}
<{{this.url}}|`{{limitTo this.id 8}}`> - {{this.message}}
<{{this.url}}|`{{truncate this.id 8}}`> - {{this.message}}
{{/each}}
{{/if}}
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Expand Up @@ -27,6 +27,10 @@ test:
test.only:
npm test -- $(TEST_REGEX)

## test.package - Run ncc compiled code.
test.package:
npm run package:test

## build - Build and package.
build:
npm run build && npm run package
Expand Down
10 changes: 7 additions & 3 deletions README.md
Expand Up @@ -112,8 +112,12 @@ ones:

- `icon` converts a job status into an icon eg. `{{icon jobStatus}}`
- `json` dumps the value as a JSON string eg. `{{json payload.commits}}`
- `limitTo` cuts the string at the limit eg. `{{limitTo sha 8}}`
- `or` allows a alternative or default value eg. `{{or headRef baseRef}}`
- `truncate` cuts the string at the limit eg. `{{truncate sha 8}}`
- `default` allows a alternative or default value eg. `{{default headRef "master"}}`
- `pluralize` outputs different text based on item count eg. `{{pluralize requested_reviewers "reviewer" "reviewers"}}` (if only singular form is given plural is derived by adding an "s")

- `eq`, `neq`, `not`, `and`, and `or` can be used as logical operators eg. `{{#if (and (not has_issues) (or has_pages has_wiki))}}yes{{else}}no{{/if}}`
- `#ifeq` and `#ifneq` test for variable equality or not eg. `{{#ifneq event_name "create"}}yes{{else}}no{{/ifneq}}`

**Example Using Config File**

Expand Down Expand Up @@ -188,7 +192,7 @@ icons:
*Notes:*

* If template expressions occur at the start of a string the string must be double-quoted eg. `pretext: "{{eventName}} triggered by {{actor}}"`
* Use [YAML multiline string formats](https://yaml-multiline.info/) `|`, `>`, `|-` and `>-` or double-quotes `"\n"` to control how new lines
* Use [YAML multiline string formats](https://yaml-multiline.info/) `|`, `>`, `|-` and `>-` or double-quotes `"\n"` to control new lines
* Use `~` (tilde) character to control whitepace when looping see [Whitespace control](https://handlebarsjs.com/guide/expressions.html#whitespace-control)

### Conditionals (`if`)
Expand Down
19 changes: 9 additions & 10 deletions __tests__/config.test.ts
Expand Up @@ -11,18 +11,18 @@ const jobStatus = 'failure'
const jobSteps = {
'install-deps': {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
outcome: 'success',
conclusion: 'success'
},
hooks: {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
outcome: 'cancelled',
conclusion: 'cancelled'
},
lint: {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
outcome: 'failure',
conclusion: 'failure'
},
types: {
outputs: {},
Expand All @@ -36,8 +36,8 @@ const jobSteps = {
},
'integration-test': {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
outcome: 'failure',
conclusion: 'failure'
}
}
const channel = '#github-ci'
Expand Down Expand Up @@ -122,8 +122,7 @@ test('custom config of slack action', async () => {
{
short: false,
title: 'Job Steps',
value:
':heavy_minus_sign: install-deps\n:heavy_minus_sign: hooks\n:heavy_minus_sign: lint\n:heavy_minus_sign: types\n:heavy_minus_sign: unit-test\n:heavy_minus_sign: integration-test\n'
value: ':white_check_mark: install-deps\n:x: hooks\n:grimacing: lint\n:grimacing: integration-test\n'
},
{
short: true,
Expand Down
8 changes: 5 additions & 3 deletions __tests__/fixtures/slack.yml
@@ -1,7 +1,7 @@
username: GitHub-CI
icon_url: https://octodex.github.com/images/mona-the-rivetertocat.png

pretext: Triggered via {{eventName}} by {{actor}} {{or action "action"}} {{ref}} `{{diffRef}}`
pretext: Triggered via {{eventName}} by {{actor}} {{default action "action"}} {{ref}} `{{diffRef}}`
title: GitHub Actions
title_link: https://support.github.com

Expand All @@ -11,7 +11,7 @@ text: |
{{#if payload.commits}}
*Commits*
{{#each payload.commits}}
<{{this.url}}|`{{limitTo this.id 8}}`> - {{this.message}}
<{{this.url}}|`{{truncate this.id 8}}`> - {{this.message}}
{{/each}}
{{/if}}
Expand All @@ -20,7 +20,9 @@ fallback: |-
fields:
- title: Job Steps
value: "{{#each jobSteps}}{{icon this.outcome}} {{@key}}\n{{/each}}"
value: |-
{{#each jobSteps}}{{#ifneq this.outcome 'skipped'}}{{icon this.outcome}} {{@key}}
{{/ifneq}}{{/each}}
short: false
- title: Workflow
value: "<{{{workflowUrl}}}|{{workflow}}>"
Expand Down
157 changes: 157 additions & 0 deletions __tests__/handlebars.test.ts
@@ -0,0 +1,157 @@
import Handlebars from '../src/handlebars'

const data = {
foo: 'bar',
fu: 'bar',
obj: {
a: 'b',
c: 123,
d: ['x', 'y', 'z']
},
text: 'this is a long line of text',
uuid: 'CFE20509-E7CF-4401-9733-7615EF3E8A25',
want: 0,
t: true,
f: false,
empty: [],
commits: ['088fcd5a5bc73a6733edcc58d0d30869ddbe2e2f'],
numbers: [1, 2, 3, 4],
letters: ['abc', 'def', 'ghi'],
foobars: [
{foo: true, bar: 1},
{foo: false, bar: 3},
{foo: true, bar: 3}
],
attendees: ['dave', 'mike', 'jane', 'betty'],
items: [1, 2, 3]
}

// utilities
test('json stringify', () => {
const template = Handlebars.compile('{{{json obj}}}')
const text = template(data)
expect(text).toStrictEqual('{"a":"b","c":123,"d":["x","y","z"]}')
})

test('truncate uuid', () => {
const template = Handlebars.compile('{{truncate uuid 8}}')
const text = template(data)
expect(text).toStrictEqual('CFE20509')
})

test('default is not needed', () => {
const template = Handlebars.compile('{{default want "fallback"}}')
const text = template(data)
expect(text).toStrictEqual('0')
})

test('default is needed', () => {
const template = Handlebars.compile('{{default fallback "fallback"}}')
const text = template(data)
expect(text).toStrictEqual('fallback')
})

test('pluralize empty list', () => {
const template = Handlebars.compile('{{pluralize empty}}')
const text = template(data)
expect(text).toStrictEqual('no items')
})

test('pluralize commits', () => {
const template = Handlebars.compile('{{pluralize commits "commit"}}')
const text = template(data)
expect(text).toStrictEqual('1 commit')
})

test('pluralize attendees', () => {
const template = Handlebars.compile('{{pluralize attendees "attendee"}}')
const text = template(data)
expect(text).toStrictEqual('4 attendees')
})

test('pluralize people', () => {
const template = Handlebars.compile('{{pluralize attendees "person" "people"}}')
const text = template(data)
expect(text).toStrictEqual('4 people')
})

// equality
test('eq is true', () => {
const template = Handlebars.compile('{{#if (eq foo fu)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('eq is false', () => {
const template = Handlebars.compile('{{#if (eq foo "foo")}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('neq is true', () => {
const template = Handlebars.compile('{{#if (neq foo fu)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('neq is false', () => {
const template = Handlebars.compile('{{#if (neq foo "foo")}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

// boolean operators
test('not false', () => {
const template = Handlebars.compile('{{#if (not f)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('not true', () => {
const template = Handlebars.compile('{{#if (not t)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('not false and (true or false)', () => {
const template = Handlebars.compile('{{#if (and (not f) (or t f))}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('or is true', () => {
const template = Handlebars.compile('{{#if (or t f)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('and is false', () => {
const template = Handlebars.compile('{{#if (and t f)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

// conditionals
test('#ifeq is true', () => {
const template = Handlebars.compile('{{#ifeq foo fu}}yes{{else}}no{{/ifeq}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('#ifeq is false', () => {
const template = Handlebars.compile('{{#ifeq foo "foo"}}yes{{else}}no{{/ifeq}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('#ifneq is true', () => {
const template = Handlebars.compile('{{#ifneq foo fu}}yes{{else}}no{{/ifneq}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('#ifneq is false', () => {
const template = Handlebars.compile('{{#ifneq foo "foo"}}yes{{else}}no{{/ifneq}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})
15 changes: 7 additions & 8 deletions __tests__/inputs.test.ts
Expand Up @@ -11,8 +11,8 @@ const jobStatus = 'in progress'
const jobSteps = {
'install-deps': {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
outcome: 'success',
conclusion: 'success'
},
hooks: {
outputs: {},
Expand All @@ -31,13 +31,13 @@ const jobSteps = {
},
'unit-test': {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
outcome: 'failure',
conclusion: 'failure'
},
'integration-test': {
outputs: {},
outcome: 'skipped',
conclusion: 'skipped'
outcome: 'cancelled',
conclusion: 'cancelled'
}
}
const channel = '#deploy'
Expand Down Expand Up @@ -115,8 +115,7 @@ test('custom config of slack action', async () => {
{
short: false,
title: 'Job Steps',
value:
':heavy_minus_sign: install-deps\n:heavy_minus_sign: hooks\n:heavy_minus_sign: lint\n:heavy_minus_sign: types\n:heavy_minus_sign: unit-test\n:heavy_minus_sign: integration-test\n'
value: ':white_check_mark: install-deps\n:grimacing: unit-test\n:x: integration-test\n'
},
{
short: true,
Expand Down

0 comments on commit 0d59e96

Please sign in to comment.