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

# Monitoring as Code Tutorial

> Define your full DevHelm monitoring stack in YAML and deploy it with a single command

By the end of this guide, you'll have a complete `devhelm.yml` defining monitors, alert channels, and tags — deployed via the CLI.

<Accordion title="Prerequisites">
  * DevHelm CLI installed (`npm install -g devhelm`)
  * An API token set as `DEVHELM_API_TOKEN`
  * A text editor
</Accordion>

## File format

A `devhelm.yml` file has a `version` field and one or more resource sections:

```yaml theme={null}
version: "1"

tags:
  - name: production
    color: "#10b981"

monitors:
  - name: API Health
    type: HTTP
    config:
      url: https://api.example.com/health
      method: GET
    frequencySeconds: 60
    regions:
      - us-east
      - eu-west
    tags:
      - production

alertChannels:
  - name: Engineering Slack
    config:
      channelType: slack
      webhookUrl: ${SLACK_WEBHOOK_URL}
```

### Secret references

Use `${VAR_NAME}` syntax to reference environment variables or DevHelm secrets. Secrets are resolved at deploy time — never store credentials in the YAML file.

```yaml theme={null}
alertChannels:
  - name: PagerDuty On-Call
    config:
      channelType: pagerduty
      routingKey: ${PAGERDUTY_ROUTING_KEY}
```

Set secrets via the CLI or environment variables:

```bash theme={null}
devhelm secrets create --key SLACK_WEBHOOK_URL --value https://hooks.slack.com/...
devhelm secrets create --key PAGERDUTY_ROUTING_KEY --value your-routing-key
```

## CLI workflow

### Validate

Check config syntax offline (no API calls):

```bash theme={null}
devhelm validate devhelm.yml
```

Validation runs against the DevHelm JSON Schema. Editors with JSON Schema support (VS Code, JetBrains) provide autocomplete and inline validation.

### Plan

Preview what would change without applying:

```bash theme={null}
devhelm plan -f devhelm.yml
```

Plan output shows resources to create, update, and delete. Use `-o json` for machine-readable output:

```bash theme={null}
devhelm plan -f devhelm.yml -o json
```

### Deploy

Apply changes:

```bash theme={null}
devhelm deploy -f devhelm.yml
```

Deploy shows the plan and asks for confirmation. Use `--yes` to skip confirmation (for CI):

```bash theme={null}
devhelm deploy -f devhelm.yml --yes
```

Use `--dry-run` to simulate without applying:

```bash theme={null}
devhelm deploy -f devhelm.yml --dry-run
```

With `--detailed-exitcode`, dry-run returns exit code 10 when changes are pending (useful for CI gating):

```bash theme={null}
devhelm deploy -f devhelm.yml --dry-run --detailed-exitcode
```

## CI/CD integration

### GitHub Actions

```yaml theme={null}
name: Deploy Monitoring Config
on:
  push:
    branches: [main]
    paths: ['devhelm.yml']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: devhelmhq/setup-devhelm@v1
        with:
          api-token: ${{ secrets.DEVHELM_API_TOKEN }}

      - name: Validate
        run: devhelm validate devhelm.yml

      - name: Deploy
        run: devhelm deploy -f devhelm.yml --yes
```

### PR preview

Add a plan step to pull requests to preview changes before merging:

```yaml theme={null}
name: Monitor Config Preview
on:
  pull_request:
    paths: ['devhelm.yml']

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: devhelmhq/setup-devhelm@v1
        with:
          api-token: ${{ secrets.DEVHELM_API_TOKEN }}

      - name: Plan
        run: devhelm plan -f devhelm.yml
```

## Deploy locking

DevHelm uses deploy locks to prevent concurrent deploys from conflicting. Only one deploy can run at a time per organization.

If a deploy is interrupted, you can release the lock:

```bash theme={null}
devhelm deploy force-unlock --yes
```

## Drift detection

If someone modifies a resource through the Dashboard while you're managing it via Monitoring as Code, `devhelm plan` shows the drift. The next `devhelm deploy` overwrites the Dashboard changes with the YAML definition — YAML is the source of truth.

## Next steps

<CardGroup cols={2}>
  <Card title="YAML file format" icon="file-code" href="/mac/yaml/file-format">
    Full schema reference for devhelm.yml.
  </Card>

  <Card title="CI/CD pipeline guide" icon="rotate" href="/guides/ci-cd-pipeline">
    Set up automated deploys from GitHub Actions.
  </Card>

  <Card title="Terraform provider" icon="server" href="/mac/terraform/overview">
    Alternative: manage monitors with Terraform.
  </Card>

  <Card title="Deploy workflow" icon="rocket" href="/mac/yaml/workflow">
    Deep dive into validate → plan → deploy.
  </Card>
</CardGroup>
