# GitLab

In this example, you will configure a GitLab project which contains the test application that you would like to run.

Note that you will need a ReSim project. You can [create a project](../../projects/) with the ReSim CLI.

Referring to [GitLab's documentation about CI variables](https://docs.gitlab.com/ee/ci/variables/) as required, navigate to your project's CI/CD Settings and scroll to and expand the Variables section.

Add the following variables:

- `AWS_ACCESS_KEY_ID` - set the value of this to the access key generated [above](../#creating-an-iam-user-with-aws-ecr-permissions)
- `AWS_SECRET_ACCESS_KEY` - set the value of this to the secret access key generated [above](../#creating-an-iam-user-with-aws-ecr-permissions)
- `SLACK_WEBHOOK` - if you want to run nightly tests with summaries, add a Slack webhook URL (see the [Slack documentation](https://api.slack.com/messaging/webhooks))

Also add one of these sets of variables. Your ReSim contact will provide you with either a client ID and secret, or a username and password:

- `RESIM_CLIENT_ID` and `RESIM_CLIENT_SECRET`, or
- `RESIM_USERNAME` and `RESIM_PASSWORD`

If you plan to use a merge request workflow, these variables should **not** be `protected` (so that branches can use them to push images and run tests in ReSim), or the branches you raise MRs for should be covered by a branch protection rule.

If you would like CI pipelines to be able to comment on merge requests, you also need to set a variable containing a [GitLab authentication token](https://docs.gitlab.com/ee/security/token_overview.html), either a personal access token or a project token, with at least the `api` scope.

Add a [`.gitlab-ci.yml`](https://docs.gitlab.com/ee/ci/quick_start/#create-a-gitlab-ciyml-file) file to the root of the repository.

Below is an example of building and pushing a Docker image to an ECR repository. If you use this example, make sure to replace the following placeholder values:

- `<AWS account number>` - replace with your AWS account number
- `<AWS region>` - replace with the AWS region in which you have deployed your ECR repository, e.g. `us-east-1`
- `<repository name>` - replace with the name of the ECR repository, e.g. the name of the application
- `<your project name>` - replace with the name of your ReSim project
- `<your project id>` - replace with the id of your ReSim project
- `<your build commands>` - the commands you run to build a Docker image containing your application
- `<your image name>` - the name of the Docker image created by your build
- `<your experience ids>` - the experience(s) you want to test against (see [Adding Experiences](../../adding-experiences/)), comma-separated

Text

```
stages:
  - build
  - comment # Optional - configures this workflow to post a results link if it's triggered by an MR
  - notify  # Optional - configures this workflow to send the results of a completed nightly batch to a slack webhook

variables:
  PROJECT_ID: <your project id>

push-image:
  stage: build

  # Start a Docker daemon we can use to build images
  services:
   - name: docker:dind
     alias: dockerdaemon

  # Run this job if this is an MR, a tag, or the default branch
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

  variables:
    DOCKER_HOST: tcp://dockerdaemon:2375/
    DOCKER_DRIVER: overlay2
    DOCKER_TLS_CERTDIR: ""
    SYSTEM_NAME: <your system name>

  script:
    # First, you need to build a Docker image containing your application.  Put your build commands below.
    <your build commands>
    # For example
    # - docker build . -t <your image name>:latest
    # Store our new image's URI as a variable to use later. Make sure you update these placeholder values
    - IMAGE_URI=<AWS account number>.dkr.ecr.<AWS region>.amazonaws.com/<repository name>:$CI_COMMIT_SHORT_SHA
    # We are using $CI_COMMIT_SHORT_SHA as image tag - this variable is set automatically by GitLab to the first 8 characters of the commit that triggered the run
    # Using this tag lets us map built images to code (and the inverse) easily
    - docker tag <your image name>:latest $IMAGE_URI
    # Log in to ECR so we can push the image. Make sure you update these placeholder values
    - aws ecr get-login-password --region <AWS region> | docker login --username AWS --password-stdin <AWS account number>.dkr.ecr.<AWS region>.amazonaws.com
    - docker push $IMAGE_URI
    # Install the latest version of the ReSim CLI
    - curl -L https://github.com/resim-ai/api-client/releases/latest/download/resim-linux-amd64 -o resim
    - chmod +x resim
    # Register our new image with ReSim as a build
    - BUILD_ID_OUTPUT=$(./resim builds create --system $SYSTEM_NAME --description "A quadcopter simulation" --version "$CI_COMMIT_SHORT_SHA" --project $PROJECT_ID --branch "$CI_COMMIT_REF_NAME" --image "$IMAGE_URI" --auto-create-branch --github)
    # Run a batch with the new build
    - BATCH_ID_OUTPUT=$(./resim batches create --project $PROJECT_ID --build-id ${BUILD_ID_OUTPUT#build_id=} --experiences "<your experience IDs or names>" --github)
    - echo $BATCH_ID_OUTPUT >> build.env

  # This passes data to the next job
  artifacts:
    reports:
      dotenv: build.env

# To comment a results link for the batch above on an MR, this command uses a GitLab token from the variable $MY_GITLAB_TOKEN. You may need to change the name of this variable here or in your project's settings.
comment-on-mr:
  stage: comment
  # Configure this job to run only on MRs
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'

  script:
    # this syntax (a folded block scalar) stops YAML complaining about the colons in this string
    - >
      curl --location --request POST "https://gitlab.com/api/v4/projects/$CI_MERGE_REQUEST_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes" \
      --header "PRIVATE-TOKEN: $MY_GITLAB_TOKEN" --header "Content-Type: application/json" \
      --data-raw "{ \"body\": \"View results on [app.resim.ai](https://app.resim.ai/projects/$PROJECT_ID/batches/$batch_id)\" }"

slack-notify:
  stage: notify
  # Run only on a schedule - for nightly tests
  rules:
    - if: $CI_PIPELINE_SOURCE == 'schedule'
  script:
    # Install the latest version of the ReSim CLI
    - curl -L https://github.com/resim-ai/api-client/releases/latest/download/resim-linux-amd64 -o resim
    - chmod +x resim
    # Wait for the job to complete and capture the exit code
    # the default wait time is one hour. If you think your batch will reliably take longer, you may need to edit this
    - ./resim batch wait --project "$PROJECT_ID" --batch-id "$BATCH_ID" || exit_status=$?
    # Build the slack payload and post it using curl
    - > 
      ./resim batch get --project "$PROJECT_ID" --batch-id "$BATCH_ID" --slack | \
      curl -X POST -H "content-type: application/json" --data @- $SLACK_WEBHOOK
    # Exit with error code
    - exit "${exit_status:-0}"
  # optional - you may want to permit job failure for batch errors
  allow_failure:
    exit_codes:
      - 2 # batch failure
      - 5 # batch cancelled
```
