diff --git a/run-tests/README.md b/run-tests/README.md new file mode 100644 index 0000000..7d7f6b4 --- /dev/null +++ b/run-tests/README.md @@ -0,0 +1,92 @@ +# 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 + +1. Runs `setup` if provided. Non-zero exit fails the job immediately. +2. Runs `command`. Exit code is captured but not yet propagated. +3. If `command` failed and `artifacts-path` is set, uploads matching files. +4. Re-exits with failure if `command` failed. + +This ordering ensures artifacts are always uploaded on failure, even though the job ultimately fails. + +## Usage + +### Node.js + +```yaml +name: PR Tests +on: [pull_request] +jobs: + test: + runs-on: docker + 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) + +```yaml +- 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 + +```yaml +- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1 + with: + command: cargo test --all +``` + +### Multi-line command + +```yaml +- uses: https://bitfreedom.net/code/apunkt/actions/run-tests@v1 + with: + command: | + make lint + make test + make integration-test +``` + +## Making it a merge gate + +This action alone does not block merges. To enforce passing tests before merge on Forgejo: + +1. Repo → **Settings → Branches → Protected Branches** +2. Add a rule for `main` (or your default branch) +3. Enable **Require status checks to pass before merging** +4. 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 + +- Forgejo runners often use the `docker` label rather than `ubuntu-latest`. Adjust `runs-on` per your runner setup. +- Action references must use full URLs on Forgejo (`https://code.forgejo.org/actions/checkout@v4`), unlike GitHub where `actions/checkout@v4` is shorthand. +- The failure-artifact upload uses [`forgejo/upload-artifact`](https://code.forgejo.org/forgejo/upload-artifact), which is API-compatible with `actions/upload-artifact` and works on both Forgejo and GitHub. diff --git a/run-tests/action.yml b/run-tests/action.yml new file mode 100644 index 0000000..55e3eff --- /dev/null +++ b/run-tests/action.yml @@ -0,0 +1,56 @@ +name: Run Tests +description: Runs a project's test suite with optional setup and failure-artifact upload. Language-agnostic. + +inputs: + command: + description: Test command to execute (multiline allowed) + required: true + setup: + description: Setup commands to run before tests (install deps, build, etc.) + required: false + default: "" + working-directory: + description: Directory to run setup and command in + required: false + default: "." + shell: + description: Shell to use for setup and command + required: false + default: bash + artifacts-path: + description: Glob of paths to upload on failure (test reports, logs). Empty disables upload. + required: false + default: "" + artifacts-name: + description: Name of the uploaded artifact bundle + required: false + default: test-artifacts + +runs: + using: composite + steps: + - name: Setup + if: inputs.setup != '' + shell: ${{ inputs.shell }} + working-directory: ${{ inputs.working-directory }} + run: ${{ inputs.setup }} + + - name: Run tests + id: tests + shell: ${{ inputs.shell }} + working-directory: ${{ inputs.working-directory }} + run: ${{ inputs.command }} + continue-on-error: true + + - name: Upload failure artifacts + if: inputs.artifacts-path != '' && steps.tests.outcome == 'failure' + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + with: + name: ${{ inputs.artifacts-name }} + path: ${{ inputs.artifacts-path }} + if-no-files-found: ignore + + - name: Propagate failure + if: steps.tests.outcome == 'failure' + shell: bash + run: exit 1