---
title: GitHub Actions
id: github-actions
slug: /integrations/github-actions
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

[GitHub Actions](https://github.com/features/actions) is a popular CI/CD 
product from GitHub. With GitHub Actions, users can easily define workflows
that are triggered in various lifecycle events related to a Git repository.
For example, many teams configure GitHub actions to run all unit tests in
a repository on each change that is committed to a repository. 

One of the powerful features of GitHub Actions is its extensibility: it is
very easy to package a piece of functionality as a module (called an "action")
that can later be re-used by many projects. 

Atlas provides a number of GitHub Actions that can be used to automate
database schema management tasks.

| Action                                                | Use Case                                            |
|-------------------------------------------------------|-----------------------------------------------------|
| [ariga/setup-atlas](https://github.com/ariga/setup-atlas) | Install Atlas from a GitHub Actions workflow    |
| [ariga/atlas-action/migrate/lint](https://github.com/ariga/atlas-action/tree/master/migrate/lint/action.yml)        | CI for schema changes                               |
| [ariga/atlas-action/migrate/push](https://github.com/ariga/atlas-action/tree/master/migrate/push/action.yml)   | Push your migration directory to Atlas Cloud (atlasgo.cloud) |
| [ariga/atlas-action/migrate/apply](https://github.com/ariga/atlas-action/tree/master/migrate/apply/action.yml) | Deploy versioned migrations from GitHub Actions    |

## `ariga/setup-atlas`

The [ariga/setup-atlas](https://github.com/ariga/setup-atlas) action can be used to install Atlas from a GitHub Actions workflow.

### Usage

```yaml title=".github/workflows/atlas.yaml"
name: Deploy schema changes
run-name: I'm using Atlas 🚀
on: [push]
jobs:
  use-atlas:
    runs-on: ubuntu-latest
    steps:
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - run: atlas version
      # - run: atlas schema apply ...
```

### Inputs

* `cloud-token` - (Optional) The Atlas Cloud token to use for authentication. To create
  a cloud token see the [docs](https://atlasgo.io/cloud/bots).
* `version` - (Optional) The version of the Atlas CLI to install.  Defaults to the latest
  version.

## `ariga/atlas-action/migrate/push`

Push the current version of your migration directory to Atlas Cloud.

### Usage

<Tabs
defaultValue="mysql"
values={[
    {label: 'MySQL', value: 'mysql'},
    {label: 'MariaDB', value: 'maria'},
    {label: 'PostgreSQL', value: 'postgres'},
    {label: 'SQLite', value: 'sqlite'},
]}>
<TabItem value="mysql">

```yaml
name: Push Migrations
on:
  # Run whenever code is changed in the master branch,
  # change this to your main branch.
  push:
    branches:
      - master
jobs:
  push:
    services:
      # Spin up a mysql:8 container to be used as the dev-database.
      mysql:
        image: mysql:8
        env:
          MYSQL_DATABASE: dev
          MYSQL_ROOT_PASSWORD: pass
        ports:
          - 3306:3306
        options: >-
          --health-cmd "mysqladmin ping -ppass"
          --health-interval 10s
          --health-start-period 10s
          --health-timeout 5s
          --health-retries 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/push@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project'
          dev-url: 'mysql://root:pass@localhost:3306/dev'
```

</TabItem>
<TabItem value="maria">

```yaml
name: Push Migrations
on:
  # Run whenever code is changed in the master branch,
  # change this to your main branch.
  push:
    branches:
      - master
jobs:
  push:
    services:
      # Spin up a mariadb:11 container to be used as the dev-database.
      maria11:
        image: mariadb:11
        env:
          MYSQL_DATABASE: dev
          MYSQL_ROOT_PASSWORD: pass
        ports:
          - 3306:3306
        options: >-
          --health-cmd "mysqladmin ping -ppass"
          --health-interval 10s
          --health-start-period 10s
          --health-timeout 5s
          --health-retries 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/push@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project'
          dev-url: 'maria://root:pass@localhost:3306/dev'
```

</TabItem>
<TabItem value="postgres">

```yaml
name: Push Migrations
on:
  # Run whenever code is changed in the master branch,
  # change this to your root branch.
  push:
    branches:
      - master
jobs:
  push:
    services:
      # Spin up a postgres:15 container to be used as the dev-database.
      postgres15:
        image: postgres:15
        env:
          POSTGRES_DB: test
          POSTGRES_PASSWORD: pass
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/push@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project'
          dev-url: postgres://postgres:pass@localhost:5432/test?sslmode=disable
```

</TabItem>
<TabItem value="sqlite">

```yaml
name: Push Migrations
on:
  # Run whenever code is changed in the master branch,
  # change this to your root branch.
  push:
    branches:
      - master
jobs:
  push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/push@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project'
          dev-url: sqlite://file?mode=memory&_fk=1
```
</TabItem>
</Tabs>

### Inputs

All inputs are optional as they may be specified in the Atlas configuration file.

* `dir` - The URL of the migration directory to push.  For example: `file://migrations`.
Read more about [Atlas URLs](https://atlasgo.io/concepts/url).
* `dir-name` - The name (slug) of the project in Atlas Cloud.
* `dev-url` - The URL of the dev-database to use for analysis.  For example: `mysql://root:pass@localhost:3306/dev`.
Read more about [dev-databases](https://atlasgo.io/concepts/dev-database).
* `tag` - The tag to apply to the pushed migration directory.  By default the current git commit hash is used.
* `config` - The path to the Atlas configuration file. By default, Atlas will look for a file
named `atlas.hcl` in the current directory. For example, `file://config/atlas.hcl`.
Learn more about [Atlas configuration files](https://atlasgo.io/atlas-schema/projects).
* `env` - The environment to use from the Atlas configuration file.  For example, `dev`.

### Outputs

* `url` - The URL of the migration directory in Atlas Cloud, containing an ERD visualization of the schema.

## `ariga/atlas-action/migrate/lint` (CI)

Teams using GitHub that wish to ensure all changes to their database schema are safe
can use the [`atlas-action/migrate/lint`](https://github.com/ariga/atlas-action/blob/master/migrate/lint/action.yml) GitHub Action.

This action is used for [linting migration directories](/versioned/lint)
using the `atlas migrate lint` command. This command  validates and analyzes the contents
of migration directories and generates insights and diagnostics on the selected changes:

* Ensure the migration history can be replayed from any point at time.
* Protect from unexpected history changes when concurrent migrations are written to the migration directory by
  multiple team members. Read more about the consistency checks in the section below.
* Detect whether destructive or irreversible changes have been made or whether they are dependent on tables'  
  contents and can cause a migration failure.

### Usage

Add `.github/workflows/atlas-ci.yaml` to your repo with the following contents:

<Tabs
defaultValue="mysql"
values={[
    {label: 'MySQL', value: 'mysql'},
    {label: 'MariaDB', value: 'maria'},
    {label: 'PostgreSQL', value: 'postgres'},
    {label: 'SQLite', value: 'sqlite'},
]}>
<TabItem value="mysql">

```yaml
name: Atlas CI
on:
  # Run whenever code is changed in the master branch,
  # change this to your root branch.
  push:
    branches:
      - master
  # Run on PRs where something changed under the `migrations/` directory.
  pull_request:
    paths:
      - 'migrations/*'
jobs:
  lint:
    services:
      # Spin up a mysql:8 container to be used as the dev-database for analysis.
      mysql:
        image: mysql:8
        env:
          MYSQL_DATABASE: dev
          MYSQL_ROOT_PASSWORD: pass
        ports:
          - "3306:3306"
        options: >-
          --health-cmd "mysqladmin ping -ppass"
          --health-interval 10s
          --health-start-period 10s
          --health-timeout 5s
          --health-retries 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/lint@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project' # The name of the project in Atlas Cloud
          dev-url: "mysql://root:pass@localhost:3306/dev"
```

</TabItem>
<TabItem value="maria">

```yaml
name: Atlas CI
on:
  # Run whenever code is changed in the master branch,
  # change this to your root branch.
  push:
    branches:
      - master
  # Run on PRs where something changed under the `migrations/` directory.
  pull_request:
    paths:
      - 'migrations/*'
jobs:
  lint:
    services:
      # Spin up a maria:11 container to be used as the dev-database for analysis.
      mariadb:
        image: mariadb:11
        env:
          MYSQL_DATABASE: dev
          MYSQL_ROOT_PASSWORD: pass
        ports:
          - 3306:3306
        options: >-
          --health-cmd "healthcheck.sh --su-mysql --connect --innodb_initialized"
          --health-interval 10s
          --health-start-period 10s
          --health-timeout 5s
          --health-retries 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/lint@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project' # The name of the project in Atlas Cloud
          dev-url: "maria://root:pass@localhost:3306/dev"
```

</TabItem>
<TabItem value="postgres">

```yaml
name: Atlas CI
on:
  # Run whenever code is changed in the master branch,
  # change this to your root branch.
  push:
    branches:
      - master
  # Run on PRs where something changed under the `path/to/migration/dir/` directory.
  pull_request:
    paths:
      - 'migrations/*'
jobs:
  lint:
    services:
      # Spin up a postgres:15 container to be used as the dev-database for analysis.
      postgres:
        image: postgres:15
        env:
          POSTGRES_DB: dev
          POSTGRES_PASSWORD: pass
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-start-period 10s
          --health-timeout 5s
          --health-retries 5
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/lint@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project' # The name of the project in Atlas Cloud
          dev-url: postgres://postgres:pass@localhost:5432/dev?sslmode=disable
```

</TabItem>
<TabItem value="sqlite">

```yaml
name: Atlas CI
on:
  # Run whenever code is changed in the master branch,
  # change this to your root branch.
  push:
    branches:
      - master
  # Run on PRs where something changed under the `path/to/migration/dir/` directory.
  pull_request:
    paths:
      - 'migrations/*'
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
        with:
          cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
      - uses: ariga/atlas-action/migrate/lint@v1
        with:
          dir: 'file://migrations'
          dir-name: 'my-project' # The name of the project in Atlas Cloud
          dev-url: sqlite://file?mode=memory&_fk=1
```
</TabItem>
</Tabs>

### Inputs

All inputs are optional as they may be specified in the Atlas configuration file.

* `dir` - The URL of the migration directory to lint.  For example: `file://migrations`.
  Read more about [Atlas URLs](https://atlasgo.io/concepts/url).
* `dir-name` - The name (slug) of the project in Atlas Cloud.
* `dev-url` - The URL of the dev-database to use for analysis.  For example: `mysql://root:pass@localhost:3306/dev`.
  Read more about [dev-databases](https://atlasgo.io/concepts/dev-database).
* `config` - The path to the Atlas configuration file.  By default, Atlas will look for a file
  named `atlas.hcl` in the current directory. For example, `file://config/atlas.hcl`.
  Learn more about [Atlas configuration files](https://atlasgo.io/atlas-schema/projects).
* `env` - The environment to use from the Atlas configuration file.  For example, `dev`.

### Outputs

* `url` - The URL of the CI report in Atlas Cloud, containing an ERD visualization
   and analysis of the schema migrations.

## `ariga/atlas-action/migrate/apply`

You can use [ariga/atlas-action/migrate-apply](https://github.com/ariga/atlas-action/blob/master/migrate/apply/action.yml) to deploy migrations to your database directly from
GitHub Actions.

:::info

Atlas needs network access to your database to deploy migrations,
so make sure your database is either publicly accessible or that you have otherwise enabled
network access to it from your GitHub Actions runners.

:::

This action supports two workflows:

- *Local* - the migration directory is checked in to the repository.
- *Cloud* - the migration directory is [connected to Atlas Cloud](https://atlasgo.io/cloud/directories).
Runs are reported to your Atlas Cloud account.

### Usage

Notice that the following examples rely on a `DATABASE_URL` secret being set in your repository.

To learn how to set secrets, read [GitHub's documentation](https://docs.github.com/en/actions/reference/encrypted-secrets).

The `DATABASE_URL` secret should be set to the URL of your database, for examples please see [Atlas URL formats](/concepts/url).

#### Local

```yaml
name: Deploy Database Migrations
on:
  push:
    branches:
      - master
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
      - name: Deploy Atlas Migrations
        uses: ariga/atlas-action/migrate/apply@v1
        with:
          url: ${{ secrets.DATABASE_URL }}
          dir: path/to/migrations
```

#### Deploy from Cloud

```yaml
name: Deploy Database Migrations
on:
  push:
    branches:
      - master
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ariga/setup-atlas@v0
      - name: Deploy Atlas Migrations
        uses: ariga/atlas-action/migrate/apply@v1
        with:
          url: ${{ secrets.DATABASE_URL }}
          dir: atlas://my-project # name (slug) of your project in Atlas Cloud. Add `?tag=<tag>` to deploy a specific tag.
```

### Inputs

All inputs are optional as they may be specified in the Atlas configuration file.

* `url` - The URL of the target database.  For example: `mysql://root:pass@localhost:3306/dev`.
* `dir` - The URL of the migration directory to apply.  For example: `atlas://dir-name` for cloud
   based directories or `file://migrations` for local ones.
* `config` - The URL of the Atlas configuration file.  By default, Atlas will look for a file
  named `atlas.hcl` in the current directory. For example, `file://config/atlas.hcl`.
  Learn more about [Atlas configuration files](https://atlasgo.io/atlas-schema/projects).
* `env` - The environment to use from the Atlas configuration file.  For example, `dev`.

### Outputs

* `current` - The current version of the database. (before applying migrations)
* `target` - The target version of the database.
* `pending_count` - The number of migrations that will be applied.
* `applied_count` - The number of migrations that were applied.
