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

# Deploy contracts, events and structs with GitHub Actions

> Use the Stellarium CLI and GitHub Actions to check .req files on every pull request and deploy contracts, event types and structs on merge.

The `stellarium deploy` command publishes [contracts](https://docs.stellarium.sh/concepts/contracts.md), [event types](https://docs.stellarium.sh/concepts/events.md) and [structs](https://docs.stellarium.sh/concepts/structs.md) from `.req` files to a node. In this tutorial you keep those files in a GitHub repository, check them on every pull request, and deploy them when a change reaches `main`.

## Prerequisites

* A running Stellarium node. To deploy event types or structs, the node must be enrolled in an organization.
* A GitHub repository for your `.req` files.

**1. Add your declarations**

Put your declarations in one directory, such as `stellarium/`, with one declaration per file:

```kotlin stellarium/Address.req theme={null}
struct com.example.Address@1(street: string, zip: int32)
```

```kotlin stellarium/OrderPlaced.req theme={null}
event com.example.OrderPlaced@1(orderId: string, shipTo: com.example.Address@1)
```

```kotlin stellarium/ShippingLabel.req theme={null}
contract com.example.ShippingLabel@1(to: com.example.Address@1): string {
    return "Ship to ${to.street}"
}
```

**2. Create an API client**

Create an [API client](https://docs.stellarium.sh/concepts/api-clients.md) for your node on the [Stellarium Platform](https://platform.stellarium.sh). To deploy event types or structs, create it in the organization the node is enrolled in. Save its client ID and secret.

**3. Add its details to GitHub**

In your repository, open **Settings > Secrets and variables > Actions** and add:

| Name | Kind | Value |
| - | - | - |
| `STELLARIUM_NODE_URL` | Variable | Node origin, without `/v1` |
| `STELLARIUM_OPERATOR_URL` | Variable | Operator base URL, including `/v1` |
| `STELLARIUM_CLIENT_ID` | Secret | API client ID |
| `STELLARIUM_CLIENT_SECRET` | Secret | API client secret |

**4. Add the workflow**

```yaml .github/workflows/stellarium.yml theme={null}
name: Stellarium

on:
  push:
    branches: [main]
    paths: ['stellarium/**', '.github/workflows/stellarium.yml']
  pull_request:
    paths: ['stellarium/**', '.github/workflows/stellarium.yml']

permissions:
  contents: read

env:
  STELLARIUM_NODE_URL: ${{ vars.STELLARIUM_NODE_URL }}

jobs:
  check:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install -g stellarium-cli
      - run: stellarium --output agent deploy --dry-run stellarium/

  deploy:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    concurrency:
      group: stellarium-deploy
      cancel-in-progress: false
    env:
      STELLARIUM_OPERATOR_URL: ${{ vars.STELLARIUM_OPERATOR_URL }}
      STELLARIUM_CLIENT_ID: ${{ secrets.STELLARIUM_CLIENT_ID }}
      STELLARIUM_CLIENT_SECRET: ${{ secrets.STELLARIUM_CLIENT_SECRET }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install -g stellarium-cli
      - run: stellarium --output agent deploy stellarium/
```

The `check` job needs no secrets, so it also works on pull requests from forks. `concurrency` runs one deploy at a time. `--output agent` prints plain text to the job log instead of the JSON used when output is piped.

**5. Ship a change**

Versions are immutable, so edit a declaration and give it a new version:

```kotlin stellarium/ShippingLabel.req theme={null}
contract com.example.ShippingLabel@2(to: com.example.Address@1): string {
    return "Deliver to ${to.street}"
}
```

Open a pull request and merge it. The `deploy` job publishes the new version and reports the others as `unchanged`:

```text theme={null}
unchanged struct com.example.Address@1 stellarium/Address.req
unchanged event com.example.OrderPlaced@1 stellarium/OrderPlaced.req
deployed contract com.example.ShippingLabel@2 stellarium/ShippingLabel.req
summary: 1 deployed, 2 unchanged
```

## How deploys behave

* **Order.** Structs deploy first, with a struct before any struct that names it, then event types, then contracts.
* **Deploying again is safe.** Versions the node already has with the same content are left alone and cost nothing, so you can re-run a job.
* **A changed file needs a new version.** If a file changed but its version didn't, nothing is deployed and the command exits with code `4`.
* **A failure stops the deploy.** Files before it stay deployed. Fix the file and run the job again.
* **Requests are skipped.** A `request` script found in a directory isn't deployed.
* **Fees.** A node can charge other organizations a [deploy fee](https://docs.stellarium.sh/concepts/contracts.md#deploying-a-contract) for contracts. It's paid from your API client's run.

> [!NOTE]
>
> `--dry-run` reads each file's declaration and compares it with the node's public routes. The node checks the rest of the script when you deploy, so a syntax error in a contract body fails the `deploy` job, not the `check` job.

## Troubleshooting

| Exit code | Meaning | What to do |
| - | - | - |
| `2` | Usage or configuration error | Check the path you passed and the four variables and secrets |
| `3` | Authentication failed, or the deploy was refused | Check the client's secret and that it was issued for this node. Event types and structs need a client of the node's organization |
| `4` | The script is invalid, or conflicts with a deployed version | Fix the file named in the error, or give it a new version |
| `5` | Network error, timeout, rate limit or server error | Run the job again |
| `6` | The operator refused the deploy fee | Top up your organization's balance or raise its monthly cap |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.