Skip to content

Commit

Permalink
providers/sequelize: sequelize+tf example project
Browse files Browse the repository at this point in the history
  • Loading branch information
rotemtam committed Dec 1, 2023
1 parent 7b5af94 commit 7b0d587
Show file tree
Hide file tree
Showing 15 changed files with 5,800 additions and 4 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/providers-sequelize-terraform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Sequelize + Terraform
on:
push:
branches:
- master
paths:
- .github/workflows/providers-sequelize-terraform.yaml
- 'providers/sequelize-terraform/migrations/*'
pull_request:
paths:
- 'providers/sequelize-terraform/migrations/*'
- .github/workflows/providers-sequelize-terraform.yaml
# Permissions to write comments on the pull request.
permissions:
contents: read
pull-requests: write
jobs:
atlas:
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@v4
with:
fetch-depth: 0
- uses: ariga/setup-atlas@v0
with:
cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
- uses: ariga/atlas-action/migrate/lint@v1
with:
dir: 'file://providers/sequelize/migrations'
dir-name: 'sequelize'
dev-url: 'mysql://root:pass@mysql:3306/dev'
env:
GITHUB_TOKEN: ${{ github.token }}
- uses: ariga/atlas-action/migrate/push@v1
if: github.ref == 'refs/heads/master'
with:
dir: 'file://atlashcl/gcp-secrets/migrations'
dir-name: 'sequelize'
dev-url: 'mysql://root:pass@mysql:3306/dev'

83 changes: 83 additions & 0 deletions providers/sequelize-terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# sequelize-terraform

e2e sequelize schema management

### Desired state

The desired state for this application is defined as a [Sequelize](https://sequelize.org/) schema definition which
resides in the [`model`](./model) directory.

The desired state is loaded into the `atlas.hcl` file using an `external_schema` data source:

```hcl
data "external_schema" "sequelize" {
program = [
"npx",
"@ariga/atlas-provider-sequelize",
"load",
"--path", "./model",
"--dialect", "mysql", // mariadb | postgres | sqlite | mssql
]
}
```

#### Planning new migrations

1. Make a change to the desired state in the [`model`](./model) directory.
2. Run `atlas migrate diff --env sequelize` to see the migration plan.

### Continuous integration

CI is set up using a [GitHub Actions Workflow](./.github/workflows/providers-sequelize-terraform.yml).
Whenever you make a change to your migration directory, the workflow will use the `atlas-action/migrate/lint`
action to check that the migrations are valid and safe.

#### Verifying changes locally

You can run the same checks locally using the following command:

```bash
atlas migrate lint --env sequelize --latest 1
```

The `--latest 1` flag tells Atlas to check the latest migration only. To learn more about
the `atlas migrate lint` command, see the [Atlas CLI reference](https://atlasgo.io/cli-reference#atlas-migrate-lint).

### Continuous Delivery

The [GitHub Actions Workflow](./.github/workflows/providers-sequelize-terraform.yml) in this repository
will push the migration directory to Atlas Cloud and tag it with the current Git commit SHA whenever
a change is merged to the `master` branch.

### Deployment using Terraform

The [Terraform configuration](./terraform) in this repository relies on two secrets pre-configured in you
AWS account:

Save your [Atlas Cloud token](https://atlasgo.io/cloud/bots) as `atlas-cloud-token` in AWS Secrets Manager:

```
aws secretsmanager create-secret \
--name atlas-cloud-token \
--secret-string "aci_your_token_here"
```

Save the database URL as `db-url` in AWS Secrets Manager:

```
aws secretsmanager create-secret \
--name db-url \
--secret-string "mysql://user:pass@host:port/db"
```

Next, initialize Terraform:

```bash
terraform init
```

Finally, deploy the infrastructure:

```bash
terraform apply -var tag="<latest master commit sha>"
```
22 changes: 22 additions & 0 deletions providers/sequelize-terraform/atlas.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
data "external_schema" "sequelize" {
program = [
"npx",
"@ariga/atlas-provider-sequelize",
"load",
"--path", "./model",
"--dialect", "mysql", // mariadb | postgres | sqlite | mssql
]
}

env "sequelize" {
src = data.external_schema.sequelize.url
dev = "docker://mysql/8/dev"
migration {
dir = "file://migrations"
}
format {
migrate {
diff = "{{ sql . \" \" }}"
}
}
}
20 changes: 20 additions & 0 deletions providers/sequelize-terraform/migrations/20231130133839.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- Create "Users" table
CREATE TABLE `Users` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`createdAt` datetime NOT NULL,
`updatedAt` datetime NOT NULL,
PRIMARY KEY (`id`)
) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- Create "Tasks" table
CREATE TABLE `Tasks` (
`id` int NOT NULL AUTO_INCREMENT,
`complete` bool NULL DEFAULT 0,
`createdAt` datetime NOT NULL,
`updatedAt` datetime NOT NULL,
`userID` int NOT NULL,
PRIMARY KEY (`id`),
INDEX `userID` (`userID`),
CONSTRAINT `Tasks_ibfk_1` FOREIGN KEY (`userID`) REFERENCES `Users` (`id`) ON UPDATE CASCADE ON DELETE NO ACTION
) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
2 changes: 2 additions & 0 deletions providers/sequelize-terraform/migrations/20231130144552.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- Modify "Users" table
ALTER TABLE `Users` ADD COLUMN `hobby` varchar(255) NOT NULL;
3 changes: 3 additions & 0 deletions providers/sequelize-terraform/migrations/atlas.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
h1:pwDJzAI2IQmaCd7lUwhKRPj/nYuN8O+eGE7BbFBkcus=
20231130133839.sql h1:MmMtplD4lbMmtYQzORgEcktY7yiMORWIbMao9BrvSP8=
20231130144552.sql h1:ZCugFXvthlNK3gDP3X2qe7TSsiQRfnn3DNyEm+abDBA=
21 changes: 21 additions & 0 deletions providers/sequelize-terraform/model/task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';
module.exports = (sequelize, DataTypes) => {
const Task = sequelize.define('Task', {
complete: {
type: DataTypes.BOOLEAN,
defaultValue: false,
}
});

Task.associate = (models) => {
Task.belongsTo(models.User, {
foreignKey: {
name: 'userID',
allowNull: false
},
as: 'tasks'
});
};

return Task;
};
32 changes: 32 additions & 0 deletions providers/sequelize-terraform/model/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';
module.exports = function(sequelize, DataTypes) {
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
isEmail: true
},
},
hobby: {
type: DataTypes.STRING,
allowNull: false
},
});

User.associate = (models) => {
User.hasMany(models.Task, {
foreignKey: {
name: 'userID',
allowNull: false
},
as: 'tasks'
});
};

return User;
};
Loading

0 comments on commit 7b0d587

Please sign in to comment.