mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor: fix alteration issues and add tests
This commit is contained in:
parent
39bc1a82f1
commit
03a8e84e2f
7 changed files with 200 additions and 10 deletions
2
.github/workflows/integration-test.yml
vendored
2
.github/workflows/integration-test.yml
vendored
|
@ -78,7 +78,7 @@ jobs:
|
||||||
- name: Extract
|
- name: Extract
|
||||||
working-directory: tests
|
working-directory: tests
|
||||||
run: |
|
run: |
|
||||||
npm run cli init -- -p ../logto --db postgres://postgres:postgres@localhost:5432/postgres --no-oc --du ../logto.tar.gz
|
npm run cli init -- -p ../logto --db postgres://postgres:postgres@localhost:5432/postgres --du ../logto.tar.gz
|
||||||
|
|
||||||
- name: Check and add mock connectors
|
- name: Check and add mock connectors
|
||||||
working-directory: tests
|
working-directory: tests
|
||||||
|
|
60
.github/workflows/main.yml
vendored
60
.github/workflows/main.yml
vendored
|
@ -85,19 +85,73 @@ jobs:
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
|
||||||
main-alteration-sequence:
|
main-alteration:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
# ** Checkout fresh and alteration ref **
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
|
path: ./fresh
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: v1.0.0-beta.11
|
||||||
|
path: ./alteration
|
||||||
|
# ** End **
|
||||||
|
|
||||||
|
- name: Copy lockfile # Make setup workflow happy
|
||||||
|
run: cp ./fresh/pnpm-lock.yaml ./
|
||||||
|
|
||||||
- name: Setup Node and pnpm
|
- name: Setup Node and pnpm
|
||||||
uses: silverhand-io/actions-node-pnpm-run-steps@v2
|
uses: silverhand-io/actions-node-pnpm-run-steps@v2
|
||||||
|
with:
|
||||||
|
run-install: false
|
||||||
|
|
||||||
- name: Build
|
# ** Prepack packages **
|
||||||
run: pnpm prepack
|
- name: Prepack fresh
|
||||||
|
working-directory: ./fresh
|
||||||
|
run: pnpm i && pnpm prepack
|
||||||
|
|
||||||
|
- name: Prepack alteration
|
||||||
|
working-directory: ./alteration
|
||||||
|
run: pnpm i && pnpm prepack
|
||||||
|
# ** End **
|
||||||
|
|
||||||
- name: Check alteration sequence
|
- name: Check alteration sequence
|
||||||
|
working-directory: ./fresh
|
||||||
run: node .scripts/check-alterations-sequence.js
|
run: node .scripts/check-alterations-sequence.js
|
||||||
|
|
||||||
|
- name: Setup Postgres
|
||||||
|
uses: ikalnytskyi/action-setup-postgres@v4
|
||||||
|
|
||||||
|
# ** Setup up-to-date databases and compare (test `up`) **
|
||||||
|
- name: Setup fresh database
|
||||||
|
working-directory: ./fresh
|
||||||
|
run: pnpm cli db seed
|
||||||
|
env:
|
||||||
|
DB_URL: postgres://postgres:postgres@localhost:5432/fresh
|
||||||
|
|
||||||
|
- name: Setup alteration database
|
||||||
|
working-directory: ./alteration
|
||||||
|
run: |
|
||||||
|
cd packages/cli
|
||||||
|
pnpm start db seed
|
||||||
|
env:
|
||||||
|
DB_URL: postgres://postgres:postgres@localhost:5432/alteration
|
||||||
|
|
||||||
|
- name: Run alteration scripts
|
||||||
|
working-directory: ./fresh
|
||||||
|
run: pnpm cli db alt deploy next
|
||||||
|
env:
|
||||||
|
DB_URL: postgres://postgres:postgres@localhost:5432/alteration
|
||||||
|
|
||||||
|
- name: Compare manifests
|
||||||
|
working-directory: ./fresh
|
||||||
|
run: node .scripts/compare-database.js fresh alteration
|
||||||
|
# ** End **
|
||||||
|
|
||||||
|
# ** Setup old databases and compare (test `down`) **
|
||||||
|
# TBD
|
||||||
|
# ** End **
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* This script runs a task to check alteration files seqence:
|
* This script runs a task to check alteration files sequence:
|
||||||
* new files should come last
|
* Newest files should come last.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { execSync } from "child_process";
|
import { execSync } from "child_process";
|
||||||
|
|
84
.scripts/compare-database.js
Normal file
84
.scripts/compare-database.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import pg from 'pg';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
|
||||||
|
const omit = (object, ...keys) => Object.fromEntries(Object.entries(object).filter(([key]) => !keys.includes(key)));
|
||||||
|
const omitArray = (arrayOfObjects, ...keys) => arrayOfObjects.map((value) => omit(value, ...keys));
|
||||||
|
|
||||||
|
const schema = 'public';
|
||||||
|
|
||||||
|
const queryDatabaseManifest = async (database) => {
|
||||||
|
const pool = new pg.Pool({ database, user: 'postgres', password: 'postgres' });
|
||||||
|
|
||||||
|
const { rows: tables } = await pool.query(/* sql */`
|
||||||
|
select *
|
||||||
|
from information_schema.tables
|
||||||
|
where table_schema = '${schema}'
|
||||||
|
order by table_name asc;
|
||||||
|
`);
|
||||||
|
|
||||||
|
const { rows: columns } = await pool.query(/* sql */`
|
||||||
|
select *
|
||||||
|
from information_schema.columns
|
||||||
|
where table_schema = '${schema}'
|
||||||
|
order by table_name, column_name asc;
|
||||||
|
`);
|
||||||
|
|
||||||
|
const { rows: enums } = await pool.query(/* sql */`
|
||||||
|
select pg_type.typname, pg_enum.enumlabel
|
||||||
|
from pg_type
|
||||||
|
join pg_enum
|
||||||
|
on pg_enum.enumtypid = pg_type.oid
|
||||||
|
order by pg_type.typname, pg_enum.enumlabel asc;
|
||||||
|
`);
|
||||||
|
|
||||||
|
const { rows: constraints } = await pool.query(/* sql */`
|
||||||
|
select conrelid::regclass AS table, con.*, pg_get_constraintdef(con.oid)
|
||||||
|
from pg_catalog.pg_constraint con
|
||||||
|
inner join pg_catalog.pg_class rel
|
||||||
|
on rel.oid = con.conrelid
|
||||||
|
inner join pg_catalog.pg_namespace nsp
|
||||||
|
on nsp.oid = connamespace
|
||||||
|
where nsp.nspname = 'public'
|
||||||
|
order by conname asc;
|
||||||
|
`);
|
||||||
|
|
||||||
|
const { rows: indexes } = await pool.query(/* sql */`
|
||||||
|
select *
|
||||||
|
from pg_indexes
|
||||||
|
where schemaname='${schema}'
|
||||||
|
order by tablename, indexname asc;
|
||||||
|
`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
tables: omitArray(tables, 'table_catalog'),
|
||||||
|
columns: omitArray(columns, 'table_catalog', 'udt_catalog', 'ordinal_position', 'dtd_identifier'),
|
||||||
|
enums,
|
||||||
|
constraints: omitArray(
|
||||||
|
constraints,
|
||||||
|
'oid',
|
||||||
|
'connamespace',
|
||||||
|
'conrelid',
|
||||||
|
'contypid',
|
||||||
|
'conindid',
|
||||||
|
'conparentid',
|
||||||
|
'confrelid',
|
||||||
|
'conkey',
|
||||||
|
'confkey',
|
||||||
|
'conpfeqop',
|
||||||
|
'conppeqop',
|
||||||
|
'conffeqop',
|
||||||
|
'confdelsetcols',
|
||||||
|
'conexclop',
|
||||||
|
),
|
||||||
|
indexes,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const [,, database1, database2] = process.argv;
|
||||||
|
|
||||||
|
console.log('Compare database manifest between', database1, 'and', database2)
|
||||||
|
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
await queryDatabaseManifest(database1),
|
||||||
|
await queryDatabaseManifest(database2),
|
||||||
|
);
|
|
@ -24,7 +24,9 @@
|
||||||
"@commitlint/cli": "^17.0.0",
|
"@commitlint/cli": "^17.0.0",
|
||||||
"@commitlint/config-conventional": "^17.0.0",
|
"@commitlint/config-conventional": "^17.0.0",
|
||||||
"@commitlint/types": "^17.0.0",
|
"@commitlint/types": "^17.0.0",
|
||||||
|
"@types/pg": "^8.6.6",
|
||||||
"husky": "^8.0.0",
|
"husky": "^8.0.0",
|
||||||
|
"pg": "^8.8.0",
|
||||||
"typescript": "^4.9.4"
|
"typescript": "^4.9.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { sql } from 'slonik';
|
||||||
|
|
||||||
|
import type { AlterationScript } from '../lib/types/alteration.js';
|
||||||
|
|
||||||
|
const alteration: AlterationScript = {
|
||||||
|
up: async (pool) => {
|
||||||
|
await pool.query(sql`
|
||||||
|
alter table roles_scopes
|
||||||
|
drop constraint roles_scopes_role_id_fkey;
|
||||||
|
`);
|
||||||
|
await pool.query(sql`
|
||||||
|
alter table users_roles
|
||||||
|
drop constraint users_roles_role_id_fkey;
|
||||||
|
`);
|
||||||
|
await pool.query(sql`drop index roles_pkey;`);
|
||||||
|
await pool.query(sql`
|
||||||
|
alter table roles
|
||||||
|
add primary key (id);
|
||||||
|
`);
|
||||||
|
|
||||||
|
await pool.query(sql`
|
||||||
|
alter table roles_scopes
|
||||||
|
drop constraint roles_permissison_pkey,
|
||||||
|
add primary key (role_id, scope_id);
|
||||||
|
`);
|
||||||
|
|
||||||
|
await pool.query(sql`
|
||||||
|
alter table users_roles
|
||||||
|
add foreign key (role_id) references roles (id) on update cascade on delete cascade;
|
||||||
|
`);
|
||||||
|
await pool.query(sql`
|
||||||
|
alter table roles_scopes
|
||||||
|
add foreign key (role_id) references roles (id) on update cascade on delete cascade;
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
down: async (pool) => {
|
||||||
|
throw new Error('Not implemented');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default alteration;
|
|
@ -9,7 +9,9 @@ importers:
|
||||||
'@commitlint/config-conventional': ^17.0.0
|
'@commitlint/config-conventional': ^17.0.0
|
||||||
'@commitlint/types': ^17.0.0
|
'@commitlint/types': ^17.0.0
|
||||||
'@logto/cli': ^1.0.0-beta.10
|
'@logto/cli': ^1.0.0-beta.10
|
||||||
|
'@types/pg': ^8.6.6
|
||||||
husky: ^8.0.0
|
husky: ^8.0.0
|
||||||
|
pg: ^8.8.0
|
||||||
typescript: ^4.9.4
|
typescript: ^4.9.4
|
||||||
dependencies:
|
dependencies:
|
||||||
'@logto/cli': link:packages/cli
|
'@logto/cli': link:packages/cli
|
||||||
|
@ -18,7 +20,9 @@ importers:
|
||||||
'@commitlint/cli': 17.0.0
|
'@commitlint/cli': 17.0.0
|
||||||
'@commitlint/config-conventional': 17.0.0
|
'@commitlint/config-conventional': 17.0.0
|
||||||
'@commitlint/types': 17.0.0
|
'@commitlint/types': 17.0.0
|
||||||
|
'@types/pg': 8.6.6
|
||||||
husky: 8.0.1
|
husky: 8.0.1
|
||||||
|
pg: 8.8.0
|
||||||
typescript: 4.9.4
|
typescript: 4.9.4
|
||||||
|
|
||||||
packages/cli:
|
packages/cli:
|
||||||
|
@ -4084,6 +4088,14 @@ packages:
|
||||||
pg-types: 2.2.0
|
pg-types: 2.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/pg/8.6.6:
|
||||||
|
resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==}
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 18.11.18
|
||||||
|
pg-protocol: 1.5.0
|
||||||
|
pg-types: 2.2.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/pluralize/0.0.29:
|
/@types/pluralize/0.0.29:
|
||||||
resolution: {integrity: sha512-BYOID+l2Aco2nBik+iYS4SZX0Lf20KPILP5RGmM1IgzdwNdTs0eebiFriOPcej1sX9mLnSoiNte5zcFxssgpGA==}
|
resolution: {integrity: sha512-BYOID+l2Aco2nBik+iYS4SZX0Lf20KPILP5RGmM1IgzdwNdTs0eebiFriOPcej1sX9mLnSoiNte5zcFxssgpGA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -11558,7 +11570,6 @@ packages:
|
||||||
pg: '>=8.0'
|
pg: '>=8.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
pg: 8.8.0
|
pg: 8.8.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/pg-protocol/1.5.0:
|
/pg-protocol/1.5.0:
|
||||||
resolution: {integrity: sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==}
|
resolution: {integrity: sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==}
|
||||||
|
@ -11630,7 +11641,6 @@ packages:
|
||||||
pg-protocol: 1.5.0
|
pg-protocol: 1.5.0
|
||||||
pg-types: 2.2.0
|
pg-types: 2.2.0
|
||||||
pgpass: 1.0.4
|
pgpass: 1.0.4
|
||||||
dev: false
|
|
||||||
|
|
||||||
/pgpass/1.0.4:
|
/pgpass/1.0.4:
|
||||||
resolution: {integrity: sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==}
|
resolution: {integrity: sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==}
|
||||||
|
|
Loading…
Reference in a new issue