# Cicd > Github actions

# Running Artillery on GitHub Actions

Integrating Artillery with GitHub Actions allows you to track your service's performance while developing your applications in your existing GitHub repositories. The following guide will show you how to load-test your services using a GitHub Actions workflow and Artillery's [official Github Action](https://github.com/marketplace/actions/artillery-load-testing-action).

You’ll learn:

* How to set up a GitHub Actions workflow to run your Artillery tests
* How to schedule your Artillery tests to run at a specific time

You can find the complete source code used in this guide in the [Artillery CI/CD Examples GitHub repo](https://github.com/artilleryio/artillery-examples-cicd).

## Artillery test script example

In this guide, we'll use the following Artillery test script to run a load test on a simple API, creating 50 virtual users per second for 10 minutes and ensuring the aggregate maximum latency for the test is under 500 milliseconds:

```yaml
config:
  target: 'http://lab.artillery.io'
  phases:
    - duration: 600
      arrivalRate: 50
  ensure:
    maxErrorRate: 1
    max: 500

scenarios:
  - name: 'Get a list of movies'
    flow:
      - get:
          url: '/movies'
          expect:
            - statusCode: 200
```

[You can run an example of this test script and see it in action.](https://play.artillery.io/?s=cdeee395-6366-4963-b80c-ffa8544359d2\&hR=true)

## Setting up a GitHub Actions workflow

GitHub looks for configuration files placed inside your code repository in a directory called `.github/workflows`. The configuration files use YAML syntax to define the events that will trigger your workflow and the jobs and steps to execute.

For this guide, the Artillery load test for the Socket.IO service will run after pushing new code to the `main` branch of your GitHub repository. We'll also use the [official Artillery GitHub Action](https://github.com/artilleryio/action-cli) to execute the load test.

Create a GitHub Actions workflow configuration file placed in `.github/workflows/load-test.yml` with the following contents:

```yaml
name: Artillery Socket.IO Load Test

on:
  push:
    branches:
      - main

jobs:
  artillery:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Execute load tests
        uses: artilleryio/action-cli@v1
        with:
          command: run tests/performance/socket-io.yml
```

Commit this file to the `main` branch of your repository. Once you push the update to GitHub, GitHub Actions will execute the load test:

![Successful Artillery test run with GitHub Actions](/img/github-actions/artillery-github-actions-success.png)

## Scheduling Artillery load tests

You can also schedule GitHub Actions to run a workflow on a recurring schedule using the `on.schedule` configuration setting, which is helpful if you want to execute your Artillery load tests at a specific time. For instance, you may wish to load-test your production applications outside of peak hours.

The `on.schedule` setting accepts a string using the [POSIX cron syntax](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab#tag_20_25_07), with the times in UTC. The following configuration will automatically trigger the GitHub Actions workflow every day at midnight UTC:

```yaml
name: Artillery Socket.IO Load Test

on:
  push:
    branches:
      - main
  schedule:
    - cron: '0 0 * * *'

jobs:
  artillery:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Make reports directory
        run: mkdir reports

      - name: Execute load tests
        uses: artilleryio/action-cli@v1
        with:
          command: run tests/performance/socket-io.yml --output reports/report.json
```

## Distributed load testing on GitHub Actions

You can scale your load tests by using Artillery's support for AWS Lambda and AWS Fargate to execute your tests from different geographic regions within your AWS infrastructure.

To trigger distributed Artillery tests from GitHub Actions workflows, you'll need to set up AWS IAM permissions to allow the workflow to access AWS resources.

The following configuration will execute your Artillery test script in the `us-east-1` region using the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` values set as encrypted secrets:

```yaml
name: Artillery Socket.IO Load Test

on:
  push:
    branches:
      - main
  schedule:
    - cron: '0 0 * * *'

jobs:
  artillery:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Execute load tests on AWS (us-east-1 region)
        uses: artilleryio/action-cli@v1
        with:
          command: run-fargate --region us-east-1 --count 5 my-test.yml
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
```

However, using the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` values directly in your workflow configuration file is not recommended. Instead, let's explore how to use a better setup below.

### AWS Permissions

You must make sure that the role being used has the right AWS permissions setup in order to run Lambda/Fargate tests. Let's see how to configure that.

#### Set up an IAM Role and Policy

Usually when running commands that require access to AWS from a CI/CD system, there will be a role scoped to the correct permissions needed. We've provided guides for [AWS Fargate](../load-testing-at-scale/aws-fargate.mdx) and [AWS Lambda](../load-testing-at-scale/aws-lambda.mdx) on the permissions needed, and how to create the roles and policies.

Having a role and policy created is a pre-requisite, so make sure you do that or work with people in your organization who have the ability to do so.

#### Configuring the GitHub Action to use them

We recommend you use AWS's official [configure-aws-credentials GitHub Action](https://github.com/aws-actions/configure-aws-credentials) for this purpose. The exact configuration of the GitHub Action will depend on the method used for authentication. We'll provide you with the recommended mechanism below, but please check the documentation above for more details.

##### Using OIDC (recommended)

First, update your `permissions` in the action:

```yaml
permissions:
  contents: read # needed so that checkout of repository can happen
  id-token: write # additionally needed now for OIDC
```

Then, add this **before Artillery tests run**:

```yaml
- name: Configure AWS Credentials
  uses: aws-actions/configure-aws-credentials@v2
  env:
    SHOW_STACK_TRACE: true # in case there are issues, this can help with debugging
  with:
    aws-region: eu-west-1
    role-to-assume: ${{ secrets.ARTILLERY_ROLE_ARN }} # arn of the role created in AWS, should be kept in GitHub Secrets
    role-session-name: OIDCSession
```

*Note: this assumes that OIDC has been setup in the AWS account, as described in our guides. You can consult the [Github guide](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#configuring-the-role-and-trust-policy) on how to do it.*

> **Warning:** If you want to use something other than OIDC, you should check the documentation on how to do it. However, it is not recommended, as otherwise you have to store long-lived credentials in GitHub Secrets.
>
> For example, here is a guide for [using static IAM credentials](https://github.com/aws-actions/configure-aws-credentials#assumerole-with-static-iam-credentials-in-repository-secrets).

## Recipes

### Testing with Playwright

As our Fargate image officially supports Playwright, by running your tests in Fargate, you can easily run your Playwright Tests from GitHub Actions. There are no changes required for this to work.

### Reporting to Artillery Cloud Dashboard

The [Artillery Cloud dashboard](../cloud/get-started.mdx) is the best way to complement running tests on CI, as you'll be able to visualise runs over time easily, check historical results, etc.

There are no changes needed to the scenario and config to report to the Dashboard, so you'll only need to pass --record to the command and set the API key (obtained from the Dashboard) to report to cloud. For example:

```yaml
- name: Run Fargate Test
  uses: artilleryio/action-cli@v1
  timeout-minutes: 15 # best practice: adding timeout in case something goes wrong with the test, so that GitHub Action won’t run for the default 6h
  with:
    command: run-fargate ./scenario.yml --count 5 --output ./report.json --record # we add `--record` here to report to Artillery Cloud
  env:
    ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_KEY }} # cloud key set in gh action secrets
```

#### Using tags to correlate runs to commits

You can expand the tags to include the commit hash, so that you can easily correlate runs to commits. For example:

```yaml

---
with:
  command: ... --tags ci:true,owner:qa,type:baseline,repo:repo_name,commit:`git rev-parse --short HEAD`
```

The above will add a tag with the commit hash to the test run, as well as a tag with the repo name. Then, you can filter in the Artillery Dashboard using these tags, or any others you add.

### Saving CLI reports

If you want to save the CLI reports, you can use the official [Upload Artifact Github Action](https://github.com/marketplace/actions/upload-a-build-artifact):

```yaml
- name: Upload artifact
  uses: actions/upload-artifact@v3
  if: always()
  with:
    name: artillery-report
    path: ./report.json # reference the generated report in the file system
```

### Failure notifications to Slack

There are many actions in the Marketplace for this. For example, you can use [action-slack](https://github.com/marketplace/actions/action-slack), and simply add something like this to the workflow:

```yaml
- name: Notify about failures
  if: failure()
  uses: 8398a7/action-slack@v3.15.1
  with:
    status: ${{ job.status }}
    fields: repo,message,commit,author,eventName,job,took,pullRequest
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required in secrets
```
