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

action: go conditional tests #709

Merged
merged 13 commits into from
Dec 6, 2024
13 changes: 13 additions & 0 deletions apps/go-test-caching/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "node_modules"],
"overrides": [
{
"files": ["./package.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nrwl/nx/nx-plugin-checks": "error"
}
}
]
}
1 change: 1 addition & 0 deletions apps/go-test-caching/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# go-test-caching
177 changes: 177 additions & 0 deletions apps/go-test-caching/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# go-test-caching
erikburt marked this conversation as resolved.
Show resolved Hide resolved

An action that maintains an index of golang unit test binaries, and can
conditionally execute those binaries when changed.

```mermaid
sequenceDiagram
participant Workflow
participant Action
participant Pipeline
participant Github

box Go-Test-Caching
participant Action
participant Pipeline
end

Workflow->>Github: Checkout repository
Workflow->>Workflow: Setup...

Workflow->>Action: 'Build'
activate Action
Action-->>Pipeline: Start Build Process

Pipeline->>Pipeline: Filter/List Packages
Pipeline->>Pipeline: Build Package Test Binaries
Pipeline-->>Action: Done Build

Action-->>Github: Upload Build Logs
Action->>Workflow: Done Build
deactivate Action

Workflow->>Action: 'Run'
activate Action
Action-->>Pipeline: Start Run Process

Pipeline->>Github: Get Test Hash Index
Github->>Pipeline: Returned
Pipeline->>Pipeline: Hash Test Binaries
Pipeline->>Pipeline: Compare Hashes
Pipeline->>Pipeline: Run Changed Tests
Pipeline-->>Action: Done Execution

Action-->>Github: Upload Run Logs
Action-->>Github: Upload Coverage (if enabled)
Action->>Workflow: Done Execution
deactivate Action

Workflow->>Action: 'Update'
activate Action
Action-->>Pipeline: Start Update Processqm
Pipeline->>Pipeline: Check Update Criteria

opt Criteria Met
Pipeline->>Github: Update Hash Index
Github->>Pipeline: Updated
end
Pipeline-->>Action: Done Update
Action->>Workflow: Done Execution
deactivate Action
```

## Usage

Example workflow job:

```
run-unit-tests:
name: Unit Tests
needs: filter
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
steps:
- name: Checkout the repo
uses: actions/checkout@v4.2.1

- name: Setup
...

- name: Build Tests
uses: smartcontractkit/.github/apps/go-test-caching@<version>
timeout-minutes: 10
with:
pipeline-step: "build"
test-suite: "unit"
module-directory: "./module"
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run Tests
uses: smartcontractkit/.github/apps/go-test-caching@<version>
timeout-minutes: 15
env:
CL_DATABASE_URL: ${{ env.DB_URL }}
with:
pipeline-step: "run"
test-suite: "unit"
module-directory: "./module"
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Update Test Index
uses: smartcontractkit/.github/apps/go-test-caching@<version>
timeout-minutes: 2
with:
pipeline-step: "update"
test-suite: "unit"
github-token: ${{ secrets.GITHUB_TOKEN }}
```

## Action

### Inputs

#### Behavioral Inputs

- `pipeline-step`, `build / run / update / e2e`
- Describes which step of the pipeline to perform. This allows you to separate
the action into multiple steps of a job.
- `build` - finds all the packages and builds the test binary for each
- `run` - given the output from `build`, will hash the binaries, compare those
to the hash index, then run those that have changed.
- `update` - given the output from `run`, it will update the hash index with
the new indexes, if on the repo's main branch.
- `e2e` - performs all of the above as a single step.

### General Inputs

- `test-suite`
- The name of the test suite, used to scope artifacts and the test indexes
- `module-directory`, path (`./`)
- The path to the root module for the tests. Similar to setting
`working-directory`.
- `hashes-branch`, string (`test-hashes`)
- The (ideally orphaned) git branch to store the test hash index json files
on. Used by `run` and `update`.
- `collect-coverage`, true / **false**
- Enables the `build`, and `run` flags for collecting coverage. Then uploads
the coverage files. This will also enable `run-all-tests` and should skip
the update step. This is because the update step should not use hashes from
binaries built with the coverage parameters.

#### `build` inputs

- `build-concurrency`, number (`8`)
- The amount of concurrent builds when building the test binaries. Recommended
to be the number of available CPU cores.
- `build-flags`: string (`""`)
- CLI build flags to pass to the `go test -c ...` command when building the
test binaries

#### `run` inputs

- `run-all-tests`: true / **false**
- Runs every test binary built, ignoring the normal behaviour of conditional
execution based on the different hashes.
- `run-concurrency`, number (`8`)
- The amount of concurrent running tests.

#### `update` inputs

- `force-update-index`, true / **false**
- Allows you to force an update even if not on the default branch.

### Other Inputs

- `github-token`
- Used by `run` and `update` steps to authenticate to github to fetch/update
the test hash index.

### TODO

- Support for config files so not everything has to be passed directly to the
action?
- Ignore certain directories?
- Scrub logs?
- Update the hash index of only successful tests?
64 changes: 64 additions & 0 deletions apps/go-test-caching/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: go-test-caching
description: "Filter, build, run affected Go tests"
inputs:
pipeline-step:
description: |
The step of the pipeline to run. Can be one of:
- build: Build then hash all test binaries
- run: Compare test hashes and run affected tests ('build' must have been run first)
- update: Update the test index file ('run' must have been run first)
- e2e: Run all of the above as a single step
required: true

test-suite:
description: |
The name of the test suite, used to scope the test binary hash index.
Has no effect otherwise.
required: true

module-directory:
description: "Directory containing the go module"
required: true
default: "."

force-update-index:
description: |
Force update the test index file, even when not on the default branch.
default: "false"

run-all-tests:
description: |
Ignore the difference between the current test indexes, and run all tests.
default: "false"

collect-coverage:
description: |
Collect coverage information for the tests. Required during both build and run steps.
default: "false"

build-flags:
description: "Flags to pass when running go test -c"
default: ""

hashes-branch:
description: |
Branch which contains the test-hashes.json file used for
comparing test hashes
default: "test-hashes"

build-concurrency:
description: "Number of concurrent builds to run"
default: "8"

run-concurrency:
description: "Number of concurrent test runs to run"
default: "8"

github-token:
description:
"Github token with read permissions on all smartcontractkit repos"
default: ${{ github.token }}

runs:
using: "node20"
main: "dist/index.js"
Loading
Loading