Skip to content

Commit

Permalink
Adds action testing (#609)
Browse files Browse the repository at this point in the history
Adds a super straightforward framework for testing Trunk Actions in this
repo. Instantiate a `TrunkActionDriver` the same as the other tests, and
then call a `preCheck` if necessary, and then pass assertions to
`testCallback` (parametrized since action functionality is diverse).

In this callback either invoke `driver.runAction()` or use the simpleGit
`driver.gitDriver()` and assert based on its error handler or based on
`driver.readGitStderr()`.

I've added 2 tests to demonstrate this:
- `hello_world` (currently disabled for speed, especially since it's
just a sample)
- `commitlint` (only added a test for a standard failure case. We may
want to expand the test coverage for it in the future, including via
`trunk run`)

We can backfill the remaining actions with tests whenever we feel the
need to, but this will help us prevent any action regressions,
particularly with commitlint.

Example successful
[run](https://github.com/trunk-io/plugins/actions/runs/7403264485/job/20142746117?pr=609)
  • Loading branch information
TylerJang27 authored Jan 4, 2024
1 parent 329e676 commit e6ed22c
Show file tree
Hide file tree
Showing 13 changed files with 404 additions and 40 deletions.
73 changes: 73 additions & 0 deletions .github/actions/action_tests/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Action Tests
description: Run tests against plugin actions

inputs:
cli-version:
description: Trunk cli version to run test against. Mutually exclusive with `cli-path`
required: false
cli-path:
description: Trunk cli path to run test against. Overrides `cli-version` if set.
required: false
path:
description: The cwd from which to run plugin commands
required: false
default: .
append-args:
description: Additional args to append to the test invocation
required: false
default: actions --
trunk-token:
description: CI debugger api token
required: true

runs:
# TODO(Tyler): See if this can be converted to a js action
using: composite
steps:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 18

- name: Specify defaults
run: |
echo "CLI_PATH=${{ inputs.cli-path }}" >> "$GITHUB_ENV"

case "$RUNNER_OS" in
Windows)
echo "PLATFORM_APPEND_ARGS=--maxWorkers=5" >> "$GITHUB_ENV"
if [[ "${{ inputs.cli-path }}" == "" ]]; then
echo "CLI_PATH=${{ github.workspace }}\trunk.ps1" >> "$GITHUB_ENV"
fi
;;
esac
shell: bash

- name: Install dependencies
run: npm ci
shell: bash
working-directory: ${{ inputs.path }}

- name: Run action tests
if: runner.os == 'Windows'
run: npm test ${{ inputs.append-args }} ${{ env.PLATFORM_APPEND_ARGS }} --passWithNoTests --ci
shell: bash
working-directory: ${{ inputs.path }}
env:
PLUGINS_TEST_CLI_VERSION: ${{ inputs.cli-version }}
PLUGINS_TEST_CLI_PATH: ${{ env.CLI_PATH }}

- name: Run action tests
if: runner.os != 'Windows'
uses: trunk-io/[email protected]
with:
breakpoint-id: trunk-plugins-action-tests
shell: bash
working-directory: ${{ inputs.path }}
trunk-token: ${{ inputs.trunk-token }}
org: trunk-staging-org
run:
npm test ${{ inputs.append-args }} ${{ env.PLATFORM_APPEND_ARGS }} --passWithNoTests --ci
env:
PLUGINS_TEST_CLI_VERSION: ${{ inputs.cli-version }}
PLUGINS_TEST_CLI_PATH: ${{ env.CLI_PATH }}
8 changes: 8 additions & 0 deletions .github/filters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ all-tools:
- runtimes/**
- tests/driver/!(lint_driver.ts)

all-actions:
- *framework
- runtimes/**
- tests/driver/!(action_driver.ts)

# Run tests against specific linters if existing linters have been modified or updated.
# These test will be run with KnownGoodVersion and Latest to verify linter integrity at the latest and fallback version.
# Someone should not be able to add a new linter without verifying that it also works on the latest version.
Expand All @@ -31,6 +36,9 @@ linters:
tools:
- added|modified: tools/**

actions:
- added|modified: actions/**

# Run tests against the health and configuration of the repo if any plugin definition
# or testing framework change is made.
# e.g. `npm test tests/repo_tests`
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/nightly.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,16 @@ jobs:
repo_tests:
name: Repo Tests
uses: ./.github/workflows/repo_tests.reusable.yaml

action_tests_main:
name: Action Tests Main
runs-on: [self-hosted, Linux]
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Action Tests
uses: ./.github/actions/action_tests
with:
trunk-token: ${{ secrets.TRUNK_DEBUGGER_TOKEN }}
54 changes: 44 additions & 10 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
tools: ${{ steps.filter.outputs.tools }}
all-tools: ${{ steps.post-filter-tools.outputs.out }}
tools-files: ${{ steps.post-filter-tools-paths.outputs.out }}
actions: ${{ steps.filter.outputs.actions }}
all-actions: ${{ steps.post-filter-actions.outputs.out }}
actions-files: ${{ steps.post-filter-actions-paths.outputs.out }}

steps:
- name: Checkout
Expand Down Expand Up @@ -65,14 +68,21 @@ jobs:
if: steps.filter.outputs.all-linters == 'true'
run: |
echo "Run all linter tests"
echo "out=linters" >> "$GITHUB_OUTPUT"
echo "out=linters/" >> "$GITHUB_OUTPUT"

- name: Suggest all tool tests
id: post-filter-tools
if: steps.filter.outputs.all-tools == 'true'
run: |
echo "Run all tool tests"
echo "out=tools" >> "$GITHUB_OUTPUT"
echo "out=tools/" >> "$GITHUB_OUTPUT"

- name: Suggest all action tests
id: post-filter-actions
if: steps.filter.outputs.all-actions == 'true'
run: |
echo "Run all action tests"
echo "out=actions/" >> "$GITHUB_OUTPUT"

- name: Suggest normalized individual linter paths
id: post-filter-paths
Expand All @@ -94,14 +104,24 @@ jobs:
echo "Running tests on individual tools: ${tool_files}"
echo "out=${tool_files}" >> "$GITHUB_OUTPUT"

- name: Suggest normalized individual action paths
id: post-filter-actions-paths
if: steps.filter.outputs.actions
run: |
action_files=$(echo ${{steps.filter.outputs.actions_files}} |
grep -oP "\Kactions/.*?(?=/)" |
uniq | tr '\n' ' ')
echo "Running tests on individual actions: ${action_files}"
echo "out=${action_files}" >> "$GITHUB_OUTPUT"

# Run tests against all linters for known_good_version and latest version
linter_tests:
name: Linter Tests ${{ matrix.os }}
runs-on: [self-hosted, "${{ matrix.os }}"]
needs: detect_changes
if:
needs.detect_changes.outputs.linters == 'true' || needs.detect_changes.outputs.all-linters ==
'linters'
'linters/'
timeout-minutes: 90
strategy:
fail-fast: false
Expand All @@ -114,9 +134,6 @@ jobs:
- name: Linter Tests
# Run tests using KnownGoodVersion with any modified linters and conditionally all linters
uses: ./.github/actions/linter_tests
if:
needs.detect_changes.outputs.linters == 'true' || needs.detect_changes.outputs.all-linters
== 'linters'
with:
linter-version: KnownGoodVersion
sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }}
Expand All @@ -143,7 +160,7 @@ jobs:
needs: detect_changes
if:
needs.detect_changes.outputs.tools == 'true' || needs.detect_changes.outputs.all-tools ==
'tools'
'tools/'
timeout-minutes: 60
strategy:
fail-fast: false
Expand All @@ -157,15 +174,32 @@ jobs:
# Run tests using KnownGoodVersion with any modified tools and conditionally all tools. Don't run when cancelled.
# TODO(Tyler): Wire up Latest tests and ReleaseVersionService
uses: ./.github/actions/tool_tests
if:
(failure() || success()) && needs.detect_changes.outputs.tools == 'true' ||
needs.detect_changes.outputs.all-tools == 'tools'
with:
append-args:
${{ needs.detect_changes.outputs.all-tools }} ${{
needs.detect_changes.outputs.tools-files }}
trunk-token: ${{ secrets.TRUNK_DEBUGGER_TOKEN }}

action_tests:
name: Action Tests
runs-on: [self-hosted, Linux]
needs: detect_changes
if:
needs.detect_changes.outputs.actions == 'true' || needs.detect_changes.outputs.all-actions ==
'actions/'
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Action Tests
uses: ./.github/actions/action_tests
with:
append-args:
${{ needs.detect_changes.outputs.all-actions }} ${{
needs.detect_changes.outputs.actions-files }} --
trunk-token: ${{ secrets.TRUNK_DEBUGGER_TOKEN }}

trunk_check_runner:
name: Trunk Check runner [linux]
runs-on: ubuntu-latest
Expand Down
37 changes: 37 additions & 0 deletions actions/commitlint/commitlint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* trunk-ignore-all(eslint/import/no-extraneous-dependencies) */
import { actionRunTest } from "tests";
import { TrunkActionDriver } from "tests/driver";

const preCheck = (driver: TrunkActionDriver) => {
driver.writeFile(
"commitlint.config.js",
"module.exports = {extends: ['@commitlint/config-conventional']}",
);
};

const testCallback = async (driver: TrunkActionDriver) => {
try {
await driver.gitDriver?.commit(
"Test commit",
[],
{ "--allow-empty": null },
(error, result) => {
expect(error?.message).toContain("subject may not be empty [subject-empty]");
expect(error?.message).toContain("type may not be empty [type-empty]");
expect(result).toBeUndefined();
},
);

// Commit step should throw
expect(1).toBe(2);
} catch (_err) {
// Intentionally empty
}
};

actionRunTest({
actionName: "commitlint",
syncGitHooks: true,
testCallback,
preCheck,
});
19 changes: 19 additions & 0 deletions actions/hello-world/python/hello_world.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { actionRunTest } from "tests";
import { TrunkActionDriver } from "tests/driver";

const testCallback = async (driver: TrunkActionDriver) => {
await driver.gitDriver?.commit("Test commit", [], { "--allow-empty": null }, (error, result) => {
expect(error).toBeNull();
expect(result).toBeTruthy();
});

expect(driver.readGitStderr()).toContain("Hello World");
};

// NOTE(Tyler): This test is currently skipped. To demonstrate its functionality, remove the skipTestIf
actionRunTest({
actionName: "hello-world-python",
syncGitHooks: true,
testCallback,
skipTestIf: () => true,
});
Loading

0 comments on commit e6ed22c

Please sign in to comment.