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
typefor 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:v1local://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:latestA 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@v1A 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@mainThe blog post Package GitHub Actions automatically with GitHub Actions describes how this achieved.