> ## Documentation Index
> Fetch the complete documentation index at: https://hitspec.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub Actions

> Run hitspec API tests in your GitHub Actions CI/CD pipeline with JUnit reporting, caching, and matrix testing.

hitspec integrates with GitHub Actions through an official action and direct CLI usage. You can run API tests on every push, pull request, or schedule, and report results using JUnit XML.

## Official GitHub Action

The fastest way to add hitspec to your pipeline:

```yaml .github/workflows/api-tests.yml theme={null}
name: API Tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: abdul-hamid-achik/hitspec@v1
        with:
          files: tests/
          output: junit
          output-file: test-results.xml

      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: test-results
          path: test-results.xml
```

### Action Inputs

| Input         | Description                                               | Default    |
| ------------- | --------------------------------------------------------- | ---------- |
| `files`       | Files or directories to test                              | (required) |
| `env`         | Environment name                                          | `dev`      |
| `env-file`    | Path to `.env` file for variable interpolation            | -          |
| `output`      | Output format (`console`, `json`, `junit`, `tap`, `html`) | `junit`    |
| `output-file` | Write output to file                                      | -          |
| `tags`        | Filter by tags (comma-separated)                          | -          |
| `name`        | Filter by request name pattern                            | -          |
| `timeout`     | Global timeout in milliseconds                            | -          |
| `parallel`    | Run requests in parallel                                  | `false`    |
| `concurrency` | Max concurrent requests when `parallel` is enabled        | -          |
| `bail`        | Stop on first failure                                     | `false`    |
| `verbose`     | Show detailed output                                      | `false`    |
| `insecure`    | Disable SSL certificate validation                        | `false`    |
| `proxy`       | Proxy URL for requests                                    | -          |
| `stress`      | Enable stress testing mode                                | `false`    |
| `duration`    | Stress test duration (e.g. `30s`, `1m`)                   | `30s`      |
| `rate`        | Target requests per second for stress testing             | `10`       |
| `vus`         | Number of virtual users (alternative to `rate`)           | -          |
| `max-vus`     | Maximum concurrent requests in stress mode                | -          |
| `think-time`  | Think time between requests per VU                        | -          |
| `ramp-up`     | Ramp-up time to reach target rate/VUs                     | -          |
| `threshold`   | Pass/fail thresholds (e.g. `"p95<200ms,errors<0.1%"`)     | -          |
| `profile`     | Stress profile name from `hitspec.yaml`                   | -          |
| `version`     | hitspec version to install (e.g. `v0.9.4` or `latest`)    | `latest`   |

<Note>
  The Action defaults `output` to `junit` (handy for CI test reporting), whereas the
  `hitspec` CLI defaults to `console`.
</Note>

### Action Outputs

| Output      | Description                                                |
| ----------- | ---------------------------------------------------------- |
| `exit-code` | Exit code from hitspec (`0` = success, non-zero = failure) |

## Using the CLI Directly

If you prefer installing hitspec yourself (for example, to pin a specific version or use Homebrew caching), you can call the CLI directly:

```yaml .github/workflows/api-tests.yml theme={null}
name: API Tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install hitspec
        run: |
          # Choose a published version from the Releases page:
          # https://github.com/abdul-hamid-achik/hitspec/releases/latest
          VERSION=2.18.0
          curl -fsSL "https://github.com/abdul-hamid-achik/hitspec/releases/download/v${VERSION}/hitspec_${VERSION}_linux_amd64.tar.gz" | tar xz
          sudo mv hitspec /usr/local/bin/

      - name: Run API tests
        run: |
          hitspec run tests/ \
            --env staging \
            --output junit \
            --output-file test-results.xml \
            --bail

      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: test-results
          path: test-results.xml
```

## Exit Codes

hitspec uses specific exit codes that GitHub Actions interprets as pass or fail:

| Code | Meaning                                   | CI Result   |
| ---- | ----------------------------------------- | ----------- |
| `0`  | All tests passed                          | Step passes |
| `1`  | One or more tests failed                  | Step fails  |
| `2`  | Parse error (invalid `.http` file syntax) | Step fails  |
| `3`  | Configuration error                       | Step fails  |
| `4`  | Network/connection error                  | Step fails  |
| `64` | Invalid CLI usage                         | Step fails  |

Any non-zero exit code causes the GitHub Actions step to fail, which blocks the workflow (and any required status checks) from passing.

## Environment Variables and Secrets

Use GitHub secrets to pass sensitive values like API tokens and credentials. hitspec supports all major CLI flags as environment variables with the `HITSPEC_` prefix.

```yaml theme={null}
- uses: abdul-hamid-achik/hitspec@v1
  env:
    API_TOKEN: ${{ secrets.API_TOKEN }}
    HITSPEC_ENV: staging
    HITSPEC_TIMEOUT: 60s
    HITSPEC_BAIL: "true"
  with:
    files: tests/
    output: junit
    output-file: test-results.xml
```

### Using an `.env` File

If your tests rely on an environment file, generate it from secrets at runtime:

```yaml theme={null}
- name: Create environment file
  run: |
    echo "API_TOKEN=${{ secrets.API_TOKEN }}" >> .env.ci
    echo "DB_URL=${{ secrets.DB_URL }}" >> .env.ci

- uses: abdul-hamid-achik/hitspec@v1
  with:
    files: tests/
    env: staging
    env-file: .env.ci
```

### Supported Environment Variables

| Environment Variable  | CLI Flag        | Description           |
| --------------------- | --------------- | --------------------- |
| `HITSPEC_ENV`         | `--env`         | Environment to use    |
| `HITSPEC_ENV_FILE`    | `--env-file`    | Path to `.env` file   |
| `HITSPEC_CONFIG`      | `--config`      | Path to config file   |
| `HITSPEC_TIMEOUT`     | `--timeout`     | Request timeout       |
| `HITSPEC_TAGS`        | `--tags`        | Filter by tags        |
| `HITSPEC_OUTPUT`      | `--output`      | Output format         |
| `HITSPEC_OUTPUT_FILE` | `--output-file` | Output file path      |
| `HITSPEC_BAIL`        | `--bail`        | Stop on first failure |
| `HITSPEC_PARALLEL`    | `--parallel`    | Run in parallel       |
| `HITSPEC_CONCURRENCY` | `--concurrency` | Concurrent requests   |
| `HITSPEC_QUIET`       | `--quiet`       | Suppress output       |
| `HITSPEC_NO_COLOR`    | `--no-color`    | Disable colors        |
| `HITSPEC_PROXY`       | `--proxy`       | Proxy URL             |
| `HITSPEC_INSECURE`    | `--insecure`    | Skip SSL verification |

### Metrics and Notification Variables

| Environment Variable   | CLI Flag            | Description                                                                    |
| ---------------------- | ------------------- | ------------------------------------------------------------------------------ |
| `HITSPEC_METRICS`      | `--metrics`         | Metrics export format: `prometheus`, `datadog`, `json`                         |
| `HITSPEC_METRICS_PORT` | `--metrics-port`    | Prometheus metrics port (default `9090`)                                       |
| `HITSPEC_METRICS_FILE` | `--metrics-file`    | Output file for JSON metrics                                                   |
| `DD_API_KEY`           | `--datadog-api-key` | DataDog API key                                                                |
| `DD_SITE`              | `--datadog-site`    | DataDog site (default `datadoghq.com`)                                         |
| `DD_TAGS`              | `--datadog-tags`    | Comma-separated DataDog tags                                                   |
| `HITSPEC_NOTIFY`       | `--notify`          | Notification service: `slack`, `teams`                                         |
| `HITSPEC_NOTIFY_ON`    | `--notify-on`       | When to notify: `always`, `failure`, `success`, `recovery` (default `failure`) |
| `SLACK_WEBHOOK`        | `--slack-webhook`   | Slack webhook URL                                                              |
| `SLACK_CHANNEL`        | `--slack-channel`   | Slack channel override                                                         |
| `TEAMS_WEBHOOK`        | `--teams-webhook`   | Microsoft Teams webhook URL                                                    |

## Caching

Cache the hitspec binary to speed up subsequent runs:

```yaml theme={null}
- name: Cache hitspec binary
  uses: actions/cache@v5
  with:
    path: /usr/local/bin/hitspec
    key: hitspec-${{ runner.os }}-${{ hashFiles('.hitspec-version') }}

- name: Install hitspec
  run: |
    if ! command -v hitspec &> /dev/null; then
      # Choose a published version from the Releases page:
      # https://github.com/abdul-hamid-achik/hitspec/releases/latest
      VERSION=2.18.0
      curl -fsSL "https://github.com/abdul-hamid-achik/hitspec/releases/download/v${VERSION}/hitspec_${VERSION}_linux_amd64.tar.gz" | tar xz
      sudo mv hitspec /usr/local/bin/
    fi
```

If you install hitspec via Go, you can cache the Go module cache instead:

```yaml theme={null}
- uses: actions/setup-go@v6
  with:
    go-version: "1.25.x"
    cache: true

- name: Install hitspec
  run: go install github.com/abdul-hamid-achik/hitspec/apps/cli@latest
```

## Matrix Testing

Run the same tests across multiple environments or configurations using a GitHub Actions matrix:

```yaml .github/workflows/api-tests.yml theme={null}
name: API Tests (Matrix)

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        environment: [dev, staging, production]
    steps:
      - uses: actions/checkout@v6

      - uses: abdul-hamid-achik/hitspec@v1
        with:
          files: tests/
          env: ${{ matrix.environment }}
          output: junit
          output-file: test-results-${{ matrix.environment }}.xml

      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: test-results-${{ matrix.environment }}
          path: test-results-${{ matrix.environment }}.xml
```

### Matrix with Tags

You can also use a matrix to run different test suites:

```yaml theme={null}
strategy:
  fail-fast: false
  matrix:
    include:
      - suite: smoke
        tags: smoke
        timeout: 30s
      - suite: integration
        tags: integration
        timeout: 120s
      - suite: contract
        tags: contract
        timeout: 60s

steps:
  - uses: actions/checkout@v6

  - uses: abdul-hamid-achik/hitspec@v1
    env:
      HITSPEC_TIMEOUT: ${{ matrix.timeout }}
    with:
      files: tests/
      tags: ${{ matrix.tags }}
      output: junit
      output-file: test-results-${{ matrix.suite }}.xml
```

## Stress Testing in CI

Run load tests in your pipeline to catch performance regressions:

```yaml theme={null}
- uses: abdul-hamid-achik/hitspec@v1
  with:
    files: api.http
    stress: true
    duration: 2m
    rate: 100
    threshold: "p95<200ms,errors<0.5%"
```

The `threshold` input defines pass/fail criteria. If any threshold is exceeded, the step fails with exit code `1`.

## Reporting with JUnit

Most CI reporting tools understand JUnit XML. To publish results in GitHub pull requests, combine hitspec with a JUnit reporter action:

```yaml theme={null}
- uses: abdul-hamid-achik/hitspec@v1
  with:
    files: tests/
    output: junit
    output-file: test-results.xml

- name: Publish Test Results
  uses: EnricoMi/publish-unit-test-result-action@v2
  if: ${{ !cancelled() }}
  with:
    files: test-results.xml
    comment_mode: off
```

This adds a test summary directly to the pull request checks tab. Grant the
workflow or job token `checks: write` when publishing check runs.

## Full Example Workflow

A complete workflow that runs smoke tests on every PR, full tests on `main`, and uploads results:

```yaml .github/workflows/api-tests.yml theme={null}
name: API Tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  smoke:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: abdul-hamid-achik/hitspec@v1
        with:
          files: tests/
          tags: smoke
          output: junit
          output-file: smoke-results.xml
          bail: true

      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: smoke-results
          path: smoke-results.xml

  full:
    runs-on: ubuntu-latest
    needs: smoke
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v6

      - name: Create environment file
        run: |
          echo "API_TOKEN=${{ secrets.API_TOKEN }}" >> .env.ci

      - uses: abdul-hamid-achik/hitspec@v1
        with:
          files: tests/
          env: staging
          env-file: .env.ci
          parallel: true
          output: junit
          output-file: full-results.xml

      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: full-results
          path: full-results.xml
```
