# Test and deploy Rell code with the Chromia CLI · Build your dapp with CI · Learn Chromia

> This guide shows you how to write and run CI pipelines that use the Chromia CLI to test and deploy Rell code on the Chromia blockchain platform. The example…

Source: https://chromia.com/learn/continuous-integration/introduction/

Build your dapp with CILesson 1 of 1

1. [01Test and deploy Rell code with the Chromia CLI](https://chromia.com/learn/continuous-integration/introduction/)

[Learn](https://chromia.com/learn/)[Build your dapp with CI](https://chromia.com/learn/continuous-integration/)

01 / 01Guide

# Test and deploy Rell code with the Chromia CLI

This guide shows you how to write and run CI pipelines that use the Chromia CLI to test and deploy Rell code on the Chromia blockchain platform. The example pipeline file is split into stages for building, testing, and deploying, and each step is described below.

**Defining base image**

Start by choosing the base image your pipelines run on. The example uses the `latest` tag, but pinning a specific version is safer because it prevents unexpected changes between runs.

yaml

```nolines
image: registry.gitlab.com/chromaway/core-tools/chromia-cli/chr:latest
```

yaml

```nolines
image: registry.gitlab.com/chromaway/core-tools/chromia-cli/chr:latest
```

**Building the project**

The build stage generates the blockchain configuration for every blockchain configured in your project and stores the results as artifacts.

This file also declares the `build`, `test`, and `deploy` stages, which the jobs defined later are assigned to.

yaml

```
stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
    - chr build
  artifacts:
    when: on_success
    paths:
      - build/*.xml
```

yaml

```
pipelines:
  default:
    - step:
        name: Build
        script:
          - chr build
        artifacts:
          - build/**
```

caution

If your project has dependencies, run `chr install` in your script first, before any other command such as build, test, or start.

**Running tests**

Unit tests need a Postgres service container. Use the Alpine variant of the image, because its collation settings match what is expected.

The database properties are set as global variables so the integration test job can reuse them.

yaml

```
variables:
  POSTGRES_DB: postchain
  POSTGRES_USER: postchain
  POSTGRES_PASSWORD: postchain
  CHR_DB_URL: jdbc:postgresql://postgres/postchain

test:
  stage: test
  services:
    - postgres:15-alpine
  script: chr test --test-report
  artifacts:
    when: always
    reports:
      junit: build/reports/*.xml
```

Postgres is declared in the definitions section and then attached to the pipeline as a service container.

yaml

```
definitions:
  services:
    postgres:
      image: "postgres:15-alpine"
      variables:
        POSTGRES_DB: postchain
        POSTGRES_USER: postchain
        POSTGRES_PASSWORD: postchain

pipelines:
  default:
    - step:
        name: Test
        services:
          - postgres
        script:
          - export CHR_DB_URL=jdbc:postgresql://localhost:5432/postchain
          - chr test --test-report --test-report-dir build/test-reports
        artifacts:
          - build/test-reports/*.xml
```

The integration test job first launches a test node in the background, then waits until messaging port 9870 is exposed before continuing. If you write your integration tests in TypeScript, Kotlin, or another language rather than shell, consider a framework such as [Testcontainers](https://testcontainers.com) to run the test node as a sidecar. For a TypeScript setup, see [the integration testing guide](https://chromia.com/learn/rell-integration-test/introduction/).

yaml

```
integration-test:
  stage: test
  services:
    - postgres:15-alpine
  before_script:
    - chr node start &
    - while ! nc -z localhost 9870; do sleep 1; done; sleep 1
  script:
    - chr tx --await set_name Alice
    - $([ "$(chr query hello_world)" = "\"Hello Alice!\"" ])
  artifacts:
    when: on_failure
    paths:
      - logs/*.log
```

yaml

```
pipelines:
  default:
    - step:
        name: Integration Test
        services:
          - postgres
        script:
          - chr node start &
          - while ! nc -z localhost 9870; do sleep 1; done; sleep 1
          - chr tx --await set_name Alice
          - $([ "$(chr query hello_world)" = "\"Hello Alice!\"" ])
        artifacts:
          - logs/**
```

Written for this site from Chromia’s public course. Code samples are the course’s own.

[← Course**Build your dapp with CI**](https://chromia.com/learn/continuous-integration/)[Course done →**Start building**](https://chromia.com/developers/#start)
