snapshot of https://github.com/ent/ent.git (master, 2026-09-15; blobs > 131072B omitted)
This commit is contained in:
293
doc/md/ci.mdx
Normal file
293
doc/md/ci.mdx
Normal file
@@ -0,0 +1,293 @@
|
||||
---
|
||||
id: ci
|
||||
title: Continuous Integration
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
To ensure the quality of their software, teams often apply _Continuous
|
||||
Integration_ workflows, commonly known as CI. With CI, teams continuously run a suite
|
||||
of automated verifications against every change to the code-base. During CI,
|
||||
teams may run many kinds of verifications:
|
||||
* Compilation or build of the most recent version to make sure it
|
||||
isn't broken.
|
||||
* Linting to enforce any accepted code-style standards.
|
||||
* Unit tests that verify individual components work as expected
|
||||
and that changes to the codebase do not cause regressions in
|
||||
other areas.
|
||||
* Security scans to make sure no known vulnerabilities are introduced
|
||||
to the codebase.
|
||||
* And much more!
|
||||
|
||||
From our discussions with the Ent community, we have learned
|
||||
that many teams using Ent already use CI and would like to enforce some
|
||||
Ent-specific verifications into their workflows.
|
||||
|
||||
To support the community with this effort we have started this guide which
|
||||
documents common best practices to verify in CI and introduces
|
||||
[ent/contrib/ci](https://github.com/ent/contrib/tree/master/ci) a GitHub Action
|
||||
we maintain that codifies them.
|
||||
|
||||
## Verify all generated files are checked in
|
||||
|
||||
Ent heavily relies on code generation. In our experience, generated code
|
||||
should always be checked into source control. This is done for two reasons:
|
||||
* If generated code is checked into source control, it can be read
|
||||
along with the main application code. Having generated code present when
|
||||
the code is reviewed or when a repository is browsed is essential to get
|
||||
a complete picture of how things work.
|
||||
* Differences in development environments between team members can easily be
|
||||
spotted and remedied. This further reduces the chance of "it works on my
|
||||
machine" type issues since everyone is running the same code.
|
||||
|
||||
If you're using GitHub for source control, it's easy to verify that all generated
|
||||
files are checked in with the `ent/contrib/ci` GitHub Action.
|
||||
Otherwise, we supply a simple bash script that you can integrate in your existing
|
||||
CI flow.
|
||||
|
||||
<Tabs
|
||||
defaultValue="gh"
|
||||
values={[
|
||||
{label: 'GitHub Action', value: 'gh'},
|
||||
{label: 'Bash', value: 'bash'},
|
||||
]}>
|
||||
<TabItem value="gh">
|
||||
Simply add a file named `.github/workflows/ent-ci.yaml` in your repository:
|
||||
|
||||
```yaml
|
||||
name: EntCI
|
||||
on:
|
||||
push:
|
||||
# Run whenever code is changed in the master.
|
||||
branches:
|
||||
- master
|
||||
# Run on PRs where something changed under the `ent/` directory.
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ent/*'
|
||||
jobs:
|
||||
ent:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.0.1
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
- uses: ent/contrib/ci@master
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="bash">
|
||||
|
||||
```bash
|
||||
go generate ./...
|
||||
status=$(git status --porcelain)
|
||||
if [ -n "$status" ]; then
|
||||
echo "you need to run 'go generate ./...' and commit the changes"
|
||||
echo "$status"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Lint migration files
|
||||
|
||||
Changes to your project's Ent schema almost always result in a modification
|
||||
of your database. If you are using [Versioned Migrations](/docs/versioned-migrations)
|
||||
to manage changes to your database schema, you can run [migration linting](https://atlasgo.io/versioned/lint)
|
||||
as part of your continuous integration flow. This is done for multiple reasons:
|
||||
|
||||
* Linting replays your migration directory on a [database container](https://atlasgo.io/concepts/dev-database) to
|
||||
make sure all SQL statements are valid and in the correct order.
|
||||
* [Migration directory integrity](/docs/versioned-migrations#atlas-migration-directory-integrity-file)
|
||||
is enforced - ensuring that history wasn't accidentally changed and that migrations that are
|
||||
planned in parallel are unified to a clean linear history.
|
||||
* Destructive changes are detected notifying you of any potential data loss that may be
|
||||
caused by your migrations way before they reach your production database.
|
||||
* Linting detects data-dependant changes that _may_ fail upon deployment and require
|
||||
more careful review from your side.
|
||||
|
||||
If you're using GitHub, you can use the [Official Atlas Action](https://github.com/ariga/atlas-action)
|
||||
to run migration linting during CI.
|
||||
|
||||
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 `ent/migrate/migrations/` directory.
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ent/migrate/migrations/*'
|
||||
jobs:
|
||||
lint:
|
||||
services:
|
||||
# Spin up a mysql:8.0.29 container to be used as the dev-database for analysis.
|
||||
mysql:
|
||||
image: mysql:8.0.29
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: pass
|
||||
MYSQL_DATABASE: test
|
||||
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://ent/migrate/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 `ent/migrate/migrations/` directory.
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ent/migrate/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://ent/migrate/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 `ent/migrate/migrations/` directory.
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ent/migrate/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://ent/migrate/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 `ent/migrate/migrations/` directory.
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ent/migrate/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://ent/migrate/migrations'
|
||||
dir-name: 'my-project' # The name of the project in Atlas Cloud
|
||||
dev-url: sqlite://file?mode=memory&_fk=1
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Notice that running `atlas migrate lint` requires a clean [dev-database](https://atlasgo.io/concepts/dev-database)
|
||||
which is provided by the `services` block in the example code above.
|
||||
Reference in New Issue
Block a user