Bash Uploader

Introduction

The OtterWise Bash Uploader is a lightweight script that can be used in any CI environment to process and upload code coverage data to OtterWise. It's designed to be flexible, privacy-focused, and easy to integrate with your existing workflows.

This script handles several important tasks:

  • Detecting your CI environment automatically (GitHub Actions, CircleCI, ChipperCI, etc.)
  • Finding coverage reports in standard locations
  • Gathering git information without requiring additional API access
  • Removing code from coverage reports to maintain privacy
  • Generating and sending patch information to track coverage changes
  • Supporting multiple coverage formats and testing frameworks

Basic Usage

The simplest way to use the bash uploader is to download and run it directly in your CI pipeline:

bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh)

This command will download and execute the latest version of the bash uploader. The script will look for coverage reports in common locations and attempt to automatically detect your CI environment.

Repository Token Setup

The OtterWise bash uploader requires a repository token for authentication. This token is unique to each repository and can be found in your repository settings page within OtterWise.

Finding Your Repository Token

  1. Navigate to your repository in OtterWise
  2. Click on "Settings" or "Setup Instructions"
  3. Copy the OTTERWISE_TOKEN value displayed

Setting the Token in CI Environments

The uploader looks for the OTTERWISE_TOKEN environment variable. Here's how to set it up in different CI providers:

GitHub Actions

  1. Navigate to your repository on GitHub
  2. Go to Settings → Secrets and variables → Actions
  3. Click New repository secret
  4. Name: OTTERWISE_TOKEN
  5. Value: Paste your token from OtterWise
  6. Click Add secret

Then reference it in your workflow:

- name: Upload to OtterWise
  env:
    OTTERWISE_TOKEN: ${{ secrets.OTTERWISE_TOKEN }}
  run: bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh)

CircleCI

Add the token as an environment variable in your CircleCI project settings:

  1. Go to your project settings in CircleCI
  2. Navigate to Environment Variables
  3. Click Add Variable
  4. Name: OTTERWISE_TOKEN
  5. Value: Paste your token from OtterWise

GitLab CI

Add the token as a CI/CD variable:

  1. Navigate to Settings → CI/CD → Variables
  2. Click Add variable
  3. Key: OTTERWISE_TOKEN
  4. Value: Paste your token from OtterWise
  5. Check Mask variable to hide it in logs

Travis CI

Add the token as an encrypted environment variable:

  1. Go to your repository settings in Travis CI
  2. Navigate to Environment Variables
  3. Name: OTTERWISE_TOKEN
  4. Value: Paste your token from OtterWise
  5. Ensure Display value in build log is OFF

Jenkins

Use Jenkins credentials or environment variables:

environment {
    OTTERWISE_TOKEN = credentials('otterwise-token')
}

Local Development with nektos/act

For developers using nektos/act to test GitHub Actions locally, you can pass the secret directly:

act --secret OTTERWISE_TOKEN=your_token_here

Or create a .secrets file in your repository root:

OTTERWISE_TOKEN=your_token_here

Then run act without the --secret flag:

act

Security Note

Never commit your .secrets file to version control. Add it to your .gitignore file.

Alternative: Pass Token as Command Argument

If you prefer not to use environment variables, you can pass the token directly to the uploader:

bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh) --repo-token your_token_here

Advanced: Organization Tokens

For advanced configurations, OtterWise also supports organization-wide tokens via the OTTERWISE_ORG_TOKEN environment variable or --org-token argument. Contact support for more information about this feature.

Privacy and Security

The OtterWise bash uploader is designed with privacy in mind:

  • No source code transmission: The uploader strips all actual source code from coverage reports before sending them
  • Local git operations: All git diff information is processed locally; only anonymized patch information is sent (showing only + and - symbols, not actual code)
  • Optional verbosity control: Use the --quiet flag to prevent sensitive information from appearing in CI logs
  • No API dependencies: The script uses only git commands and doesn't require access to GitHub or other provider APIs

Privacy Guarantee

The OtterWise uploader takes a privacy-first approach by stripping all source code from the coverage reports before transmission. This means your actual code never leaves your CI environment - only metadata about coverage is sent.

CI Environment Detection

The bash uploader automatically detects and configures itself for various CI providers:

  • GitHub Actions: Automatically detects repository, branch, and PR information
  • CircleCI: Extracts workflow and job details
  • ChipperCI: Optimized for Laravel's preferred CI service
  • Travis CI: Supports legacy Travis builds
  • AppVeyor: Extracts build and job information
  • Jenkins: Detects common Jenkins environment variables

Coming soon: Support for GitLab CI, TeamCity, Heroku CI, Azure Pipelines, and Bitbucket CI.

Configuration Options

The OtterWise uploader has numerous options to customize its behavior:

Basic Options

Option Description
--file Specify a custom path to your coverage file if not in the default location
--repo-token Your OtterWise repository token (if not set as environment variable)
--org-token Your OtterWise organization token (optional, for advanced configurations)
--endpoint Custom API endpoint (defaults to https://otterwise.app/ingress/upload)
--base-dir Base directory of your project (defaults to current working directory)
--quiet Reduce verbose output for cleaner CI logs
--fail-on-errors Make the CI pipeline fail if coverage upload fails

Advanced Options

Option Description
--mutation-file Path to mutation testing results file (from Infection PHP)
--type-coverage-file Path to type coverage results (from tools like Pest PHP TypeCoverage plugin)
--flag Add a flag to group your coverage reports (useful for monorepos or different test suites)

Example Usage Scenarios

Basic Usage with Default Settings

# Using environment variable for authentication
export OTTERWISE_TOKEN=your-repo-token
bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh)

Specifying a Custom Coverage File Location

bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh) \
  --repo-token your-repo-token \
  --file ./path/to/custom/coverage.xml

Using with Multiple Coverage Types

bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh) \
  --repo-token your-repo-token \
  --file ./coverage/clover.xml \
  --type-coverage-file ./pest-type-coverage.json \
  --mutation-file ./infection.json

Using Flags for Monorepos or Multiple Test Suites

# Run for backend tests
bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh) \
  --repo-token your-repo-token \
  --file ./backend/coverage/clover.xml \
  --flag backend

# Run separately for frontend tests
bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh) \
  --repo-token your-repo-token \
  --file ./frontend/coverage/lcov.info \
  --flag frontend

Automatic Coverage File Detection

If you don't specify a coverage file location, the uploader will automatically look for coverage reports in standard locations:

  1. build/logs/clover.xml (PHPUnit and Pest default)
  2. otterwise-coverage.xml (Custom file specifically for OtterWise)
  3. build/logs/cobertura.xml (Python and Java coverage tools)
  4. coverage/lcov.info (JavaScript/TypeScript coverage tools)

Additionally, the script will automatically look for type coverage in standard locations when applicable.

Troubleshooting

If you encounter issues with the bash uploader, try these troubleshooting steps:

Common Issues and Solutions

Issue Solution
Coverage file not found
  • Verify your test framework is generating the coverage file
  • Use --file to specify the exact path
  • Check file permissions in your CI environment
ERROR: No repo_token or org_token provided

Symptoms: Error messages like "No repo_token or org_token provided"

  • Check token is set: Verify your OTTERWISE_TOKEN environment variable is set correctly in your CI provider's secret/variable settings
  • Verify secret name: Ensure the secret is named exactly OTTERWISE_TOKEN (case-sensitive)
  • Check token value: Confirm you copied the complete token from OtterWise repository settings without extra spaces
  • Test locally: For nektos/act users, run: act --secret OTTERWISE_TOKEN=your_token
  • Try direct parameter: Pass the token directly with --repo-token your_token to rule out environment variable issues
  • Regenerate token: If the token was recently rotated or regenerated, update it in your CI provider
Authentication errors / Invalid token

Symptoms: "Invalid token", "Unauthorized", or HTTP 401/403 errors

  • Verify token validity: Check that the token hasn't been revoked or regenerated in OtterWise
  • Check repository match: Ensure the token belongs to the correct repository
  • Whitespace issues: Remove any leading/trailing spaces from the token value
  • Quote issues: If passing via command line, ensure proper quoting: --repo-token "your_token"
  • Environment variable not exported: Make sure the variable is available in the shell running the uploader
Git diff issues
  • Ensure your CI checkout has enough git history (fetch-depth: 2)
  • Check that git is installed and accessible in your CI environment
  • Verify the commit has a parent commit for diff calculation
CI detection issues
  • Remove --quiet to see detailed environment detection logs
  • If your CI isn't detected, raise an issue on our GitHub repository

Debugging

To get more detailed information about what the uploader is doing, remove the --quiet flag or add verbose logging:

# Run without --quiet to see full debug output
bash <(curl -s https://raw.githubusercontent.com/getOtterWise/bash-uploader/main/uploader.sh) --repo-token your-repo-token

Supported Coverage Formats

The bash uploader works with the following coverage report formats:

  • Clover XML (PHPUnit, Pest, and other PHP testing frameworks)
  • LCOV (JavaScript, TypeScript, and front-end frameworks)
  • Cobertura XML (Python, Java, and other languages)

For more details about supported formats and what data is extracted from each, see the Supported Formats page.

Advanced Metadata Collection

Beyond basic code coverage, the OtterWise bash uploader can collect and report additional metrics:

  • Type Coverage: From Pest PHP's type coverage plugin
  • Mutation Testing: From tools like Infection PHP

These additional metrics help create a more comprehensive view of your code quality beyond simple line coverage.

CI-Specific Integration Guides

While the bash uploader works with any CI system, we have detailed integration guides for popular CI providers:

For further assistance, contact OtterWise support or check our example repository which contains fully working CI configuration examples.