6.1 KiB
Run Tests
Language-agnostic composite action that executes a project's test suite with optional setup and failure-artifact upload. Designed for Forgejo Actions (works on GitHub Actions too).
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
command |
yes | — | Test command to execute (multiline allowed) |
setup |
no | "" |
Setup commands run before tests (install deps, build, etc.) |
working-directory |
no | . |
Directory to run setup and command in |
shell |
no | bash |
Shell for setup and command |
artifacts-path |
no | "" |
Glob of paths to upload on failure. Empty disables upload. |
artifacts-name |
no | test-artifacts |
Name of the uploaded artifact bundle |
Behavior
- Runs
setupif provided. Non-zero exit fails the job immediately. - Runs
command. Exit code is captured but not yet propagated. - If
commandfailed andartifacts-pathis set, uploads matching files. - Re-exits with failure if
commandfailed.
This ordering ensures artifacts are always uploaded on failure, even though the job ultimately fails.
Usage
Each example below is a complete workflow — drop it into .forgejo/workflows/test.yml (or .github/workflows/test.yml) and adjust runs-on to match a label one of your runners is registered with. See Choosing a runner below.
Node.js
name: PR Tests
on: [pull_request]
jobs:
test:
runs-on: docker-amd64
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1
with:
setup: npm ci
command: npm test
artifacts-path: |
coverage/**
junit.xml
Python (pytest)
name: PR Tests
on: [pull_request]
jobs:
test:
runs-on: docker-amd64
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1
with:
setup: |
python -m pip install --upgrade pip
pip install -e .[test]
command: pytest --junitxml=report.xml
artifacts-path: report.xml
Rust
name: PR Tests
on: [pull_request]
jobs:
test:
runs-on: docker-amd64
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1
with:
command: cargo test --all
Java (Gradle)
name: PR Tests
on: [pull_request]
jobs:
test:
runs-on: docker-amd64
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1
with:
setup: ./gradlew --version
command: ./gradlew test
artifacts-path: |
**/build/reports/tests/**
**/build/test-results/**/*.xml
Java (Maven)
name: PR Tests
on: [pull_request]
jobs:
test:
runs-on: docker-amd64
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1
with:
setup: mvn --version
command: mvn -B test
artifacts-path: |
**/target/surefire-reports/**
**/target/failsafe-reports/**
Multi-line command
Any of the examples above can run multiple commands in a single step by passing a YAML block scalar to command:
- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1
with:
command: |
make lint
make test
make integration-test
Choosing a runner
runs-on must match the labels a runner was registered with — there is no fuzzy match. If your runners are registered as docker-amd64 and docker-arm64, then runs-on: docker will queue forever waiting for a runner that doesn't exist.
Single architecture
Pick the label that matches your runner:
jobs:
test:
runs-on: docker-amd64
Both architectures (matrix)
Run the same job on every arch in parallel. Useful when you ship binaries, link against native libraries, or want to catch arch-specific bugs early:
jobs:
test:
strategy:
fail-fast: false
matrix:
arch: [docker-amd64, docker-arm64]
runs-on: ${{ matrix.arch }}
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1
with:
command: ./run-tests.sh
fail-fast: false lets the other arch finish even if one fails, so you see both results.
Does the architecture matter for the tests?
- Pure JVM, Python, or Node with no native dependencies: only execution speed differs.
- Native code (Rust, C/C++, JNI, Python wheels like
numpy/cryptography, Node modules built withnode-gyp): the compiled artifact is arch-specific. Same source, different binary — running the matrix exercises both. - Container images pulled during setup: must publish a manifest for the runner's arch. Most official images do; some niche ones are amd64-only and will fail on arm64.
Making it a merge gate
This action alone does not block merges. To enforce passing tests before merge on Forgejo:
- Repo → Settings → Branches → Protected Branches
- Add a rule for
main(or your default branch) - Enable Require status checks to pass before merging
- Add the workflow job name (e.g.
test) to the required checks list
After the workflow has run at least once on a PR, the check name will appear in the dropdown.
Notes
runs-onmust match a label your runner was registered with — see Choosing a runner. The GitHub-styleubuntu-latesttypically does not exist on Forgejo.- Action references must use full URLs on Forgejo (
https://code.forgejo.org/actions/checkout@v4), unlike GitHub whereactions/checkout@v4is shorthand. - The failure-artifact upload uses
forgejo/upload-artifact, which is API-compatible withactions/upload-artifactand works on both Forgejo and GitHub.