A GitHub Action for asserting actual is expected in GitHub Workflows, designed for GitHub Action integration tests and robust build pipelines.
- Cast action input values from strings to
type
for type safety - Distribute reusable assertions via npm
- Write local Javascript assertions to meet project-specific testing needs
- Run tests against multiple values using
each
jobs:
test-actor:
runs-on: ubuntu-latest
steps:
- name: Test actor is @shrink
uses: prompt/actions-assert@v4
with:
assertion: npm://@assertions/is-equal:v1
actual: "${{ github.actor }}"
expected: shrink
Name | Description | Example |
---|---|---|
message |
Human readable result of the assertion | Value is equal to expected "Hello, World!" |
passed |
Boolean describing whether the assertion passed | true |
failed |
Boolean describing whether the assertion failed | false |
Name | Description | Default | Examples |
---|---|---|---|
assertion |
Reference to a supported assertion in source://name format |
npm://@assertions/is-equal:v1 local://is-even |
|
expected |
Value the assertion is looking for | Hello, World! |
|
actual |
Value the assertion will test against the expected value | ${{steps.fields.outputs.greeting}} |
|
error-message |
Error message to output when assertion fails | Commit does not include a distributable build |
|
type |
A supported data type that actual and expected will be cast to before performing assertion |
string |
string json number |
each |
Parse multi-line actual into many values and perform assertion against each |
false |
true false |
local-path |
Path to directory containing local assertion |
${{github.workspace}} |
.github/workflows/assertions |
error-on-fail |
Report error in step when assertion fails | true |
false |
convert-empty-to-null [1] |
Convert empty input values to null | true |
false |
[1] convert-empty-to-null
is a workaround for a
GitHub Actions Runner bug #924
Name | Description |
---|---|
string |
A Javascript String ⇗ |
number |
A Javascript Number ⇗ |
json |
JavaScript value or object from JSON.parse() ⇗ |
When each
is enabled, the Action splits actual
by new-line into multiple
values and asserts against each value. The final result is an aggregate of each
result: all individual assertions must pass for the aggregate to pass.
An assertion
is a Javascript function that accepts expected
and actual
parameters and then returns a Result
. A Result
has a boolean pass
parameter and a message
string.
module.exports = function (expected, actual) {
return {
pass: actual === expected,
message: `compared ${actual} to ${expected}`
}
}
The test builder resolves assertion references using source
and name
accepted in source://name
format.
Source | Resolved To | Example |
---|---|---|
npm |
An npm⇗ package with an assertion as the main exported module⇗ | npm://@assertions/is-equal:v1 |
local |
A Javascript file (on the runner's filesystem) that exports an assertion as default | local://is-equal |
📌 An npm assertion reference should include a valid npm package
version. Unlike npm itself, an npm assertion reference without a version will
default to v1
instead of latest
.
ℹ️ assertion: npm://@assertions/is-equal
✅ assertion: npm://@assertions/is-equal:1
✅ assertion: npm://@assertions/is-equal:v1
✅ assertion: npm://@assertions/is-equal:v1.0.0
✅ assertion: npm://@assertions/is-equal:latest
A collection of first-party assertions is available on npm within the
@assertions
⇗ organisation.
Package | Test |
---|---|
@assertions/is-equal | actual is equal in value to expected |
@assertions/is-strictly-equal | actual is equal in value and type to expected |
@assertions/starts-with | actual starts with expected |
@assertions/directory-exists | path expected exists and is a directory |
Third-party assertions are discoverable via
🔎 actions-assert
on npm.
Add 🔖 actions-assert
to
package.json keywords
⇗ for an
assertion to be discoverable via npm search⇗.
prompt/actions-semver-aliases generates aliases for a Semantic Version with an optional prefix, in this example, the job tests that the optional prefix is applied to each alias.
on: push
jobs:
test-aliases-are-prefixed:
runs-on: ubuntu-latest
steps:
- name: Generate SemVer aliases with prefix
id: prefixed
uses: prompt/actions-semver-aliases@v1
with:
version: "3.14.1"
prefix: "v"
major: true
minor: false
- name: Assert alias is prefixed
uses: prompt/actions-assert@v4
with:
assertion: npm://@assertions/starts-with:v1
each: true
actual: "${{ steps.prefixed.outputs.list }}"
expected: "v"
error-message: "SemVer Alias is not prefixed with v"
A complete test Workflow for prompt/actions-semver-aliases using multiple
assertions is available in
.github/workflows/test.yml
.
A repository may restrict tags to commits that include a specific file; in this
example, the job deletes a newly created tag if the distributable directory
(dist
) does not exist.
on:
push:
tags:
- "**"
jobs:
validate-tag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: prompt/actions-assert@v4
with:
assertion: npm://@assertions/directory-exists:v1
expected: dist
error-message: "A commit without a dist is not allowed to be tagged"
- if: failure()
name: Delete tag
uses: prompt/actions-delete-tag@v1
A Workflow packages the Action automatically when a collaborator created a new tag. Any reference to this Action in a Workflow must use a tag (mutable) or the commit hash of a tag (immutable).
✅ uses: prompt/actions-assert@v2
✅ uses: prompt/[email protected]
✅ uses: prompt/actions-assert@0d888b7601af756fff1ffc9d0d0dca8fcc214f0a
❌ uses: prompt/actions-assert@main
The blog post Package GitHub Actions automatically with GitHub Actions describes how this achieved.