Skip to content

Commit

Permalink
Stop creating default organization and refactor ui for org creation
Browse files Browse the repository at this point in the history
fixes

lint fix

remove unnecessary tests

fixes

fix case where we don't know at all what to do, but we do have orgs

added migration to delete everything related to personal orgs, and also delete unused orgs

remove everything related to personal org

fix migration

delete oopsi

added migrations testing

fix

better migration
  • Loading branch information
dotansimha committed Feb 26, 2023
1 parent 94360c5 commit 8432143
Show file tree
Hide file tree
Showing 35 changed files with 292 additions and 265 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/migrations-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
on:
workflow_call:

jobs:
test:
runs-on: ubuntu-22.04

services:
postgres:
image: postgres:13.10-alpine
ports:
- 5432:5432
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: registry
options: >-
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
POSTGRES_HOST: localhost
POSTGRES_PORT: 5432
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: registry

steps:
- name: checkout
uses: actions/checkout@v3

- name: setup environment
uses: ./.github/actions/setup
with:
codegen: false # no need to run codegen in this case, we can skip

- name: migrations tests
run: pnpm test
working-directory: packages/migrations
4 changes: 4 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ jobs:
db-types:
uses: ./.github/workflows/db-types-diff.yaml

# Run migrations tests
db-migrations:
uses: ./.github/workflows/migrations-test.yaml

# GraphQL Breaking Changes Check
# This workflow validates that the GraphQL schema is not breaking, and fails in case of a breaking change.
# To allow a GraphQL breaking change in a PR, you may add the "non-breaking" label to the PR.
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ __generated__/
/packages/web/app/src/gql/**
/packages/web/app/src/graphql/index.ts
/packages/web/app/next.config.mjs
/packages/migrations/test/utils/testkit.ts

# test fixtures
integration-tests/fixtures/init-invalid-schema.graphql
Expand Down
3 changes: 1 addition & 2 deletions codegen.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const config = {
plugins: [
{
add: {
content: "import { StripeTypes } from '@hive/stripe-billing';",
content: "import type { StripeTypes } from '@hive/stripe-billing';",
},
},
'typescript',
Expand All @@ -26,7 +26,6 @@ const config = {
immutableTypes: true,
contextType: 'GraphQLModules.ModuleContext',
enumValues: {
OrganizationType: '../shared/entities#OrganizationType',
ProjectType: '../shared/entities#ProjectType',
TargetAccessScope: '../modules/auth/providers/target-access#TargetAccessScope',
ProjectAccessScope: '../modules/auth/providers/project-access#ProjectAccessScope',
Expand Down
1 change: 0 additions & 1 deletion integration-tests/testkit/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ export function getOrganization(organizationId: string, authToken: string) {
id
cleanId
name
type
getStarted {
creatingProject
publishingSchema
Expand Down
45 changes: 0 additions & 45 deletions integration-tests/testkit/seed.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
OrganizationAccessScope,
OrganizationType,
ProjectAccessScope,
ProjectType,
RegistryModel,
Expand Down Expand Up @@ -35,8 +34,6 @@ import {
updateRegistryModel,
updateSchemaVersionStatus,
} from './flow';
import { graphql } from './gql';
import { execute } from './graphql';
import { collect, CollectedOperation } from './usage';
import { generateUnique } from './utils';

Expand All @@ -51,48 +48,6 @@ export function initSeed() {
return {
ownerEmail,
ownerToken,
async createPersonalProject(projectType: ProjectType) {
const orgs = await execute({
document: graphql(`
query myOrganizations {
organizations {
total
nodes {
id
cleanId
name
type
}
}
}
`),
authToken: ownerToken,
}).then(r => r.expectNoGraphQLErrors());

const personalOrg = orgs.organizations.nodes.find(
o => o.type === OrganizationType.Personal,
);

if (!personalOrg) {
throw new Error('Personal organization should exist');
}

const projectResult = await createProject(
{
organization: personalOrg.cleanId,
type: projectType,
name: generateUnique(),
},
ownerToken,
).then(r => r.expectNoGraphQLErrors());

const targets = projectResult.createProject.ok!.createdTargets;
const target = targets[0];

return {
target,
};
},
async createOrg() {
const orgName = generateUnique();
const orgResult = await createOrganization({ name: orgName }, ownerToken).then(r =>
Expand Down
3 changes: 2 additions & 1 deletion packages/migrations/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"db:migrator": "node --experimental-specifier-resolution=node --loader ts-node/esm src/index.ts",
"migration:create": "pnpm db:migrator create",
"migration:rollback": "pnpm db:migrator down",
"migration:run": "pnpm db:migrator up"
"migration:run": "pnpm db:migrator up",
"test": "node --experimental-specifier-resolution=node --loader ts-node/esm ./test/*.test.ts"
},
"dependencies": {
"@slonik/migrator": "0.8.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Find and delete all organizations of type PERSONAL that have no projects
DELETE FROM public.organizations as o
WHERE
o.type = 'PERSONAL'
AND NOT EXISTS (
SELECT id from public.projects as p WHERE p.org_id = o.id LIMIT 1
);

-- Delete the "type" column from organizations
ALTER TABLE public.organizations DROP COLUMN type;

-- Delete the "organization_type" enum, as it's unused now
DROP TYPE organization_type;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
raise 'down migration not implemented'
11 changes: 11 additions & 0 deletions packages/migrations/src/connection-string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function createConnectionString(config: {
host: string;
port: number;
password: string;
user: string;
db: string;
ssl: boolean;
}) {
// prettier-ignore
return `postgres://${config.user}:${config.password}@${config.host}:${config.port}/${config.db}${config.ssl ? '?sslmode=require' : '?sslmode=disable'}`;
}
13 changes: 1 addition & 12 deletions packages/migrations/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,9 @@ import url from 'node:url';
import { createPool } from 'slonik';
import { SlonikMigrator } from '@slonik/migrator';
import { migrateClickHouse } from './clickhouse';
import { createConnectionString } from './connection-string';
import { env } from './environment';

export function createConnectionString(config: {
host: string;
port: number;
password: string;
user: string;
db: string;
ssl: boolean;
}) {
// prettier-ignore
return `postgres://${config.user}:${config.password}@${config.host}:${config.port}/${config.db}${config.ssl ? '?sslmode=require' : '?sslmode=disable'}`;
}

const [, , cmd] = process.argv;
const slonik = await createPool(createConnectionString(env.postgres));

Expand Down
69 changes: 69 additions & 0 deletions packages/migrations/test/drop-personal-org.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import assert from 'node:assert';
import { describe, test } from 'node:test';
import { sql } from 'slonik';
import { initMigrationTestingEnvironment } from './utils/testkit';

describe('migration: drop-personal-org', async () => {
await test('should remove all existing personal orgs that does not have projects', async () => {
const { db, runTo, complete, done, seed } = await initMigrationTestingEnvironment();

try {
// Run migrations all the way to the point before the one we are testing
await runTo('2023.02.21T14.32.24.supertokens-4.0.0.sql');

// Seed the DB with orgs
const user = await seed.user();
const emptyOrgs = await Promise.all([
db.one(
sql`INSERT INTO public.organizations (clean_id, name, user_id, type) VALUES ('personal-empty', 'personal-empty', ${user.id}, 'PERSONAL') RETURNING *;`,
),
db.one(
sql`INSERT INTO public.organizations (clean_id, name, user_id, type) VALUES ('regular-empty', 'regular-empty', ${user.id}, 'REGULAR') RETURNING *;`,
),
]);
const orgsWithProjects = await Promise.all([
await db.one(
sql`INSERT INTO public.organizations (clean_id, name, user_id, type) VALUES ('personal-project', 'personal-project', ${user.id}, 'PERSONAL') RETURNING *;`,
),
await db.one(
sql`INSERT INTO public.organizations (clean_id, name, user_id, type) VALUES ('regular-project', 'regular-project', ${user.id}, 'PERSONAL') RETURNING *;`,
),
]);

// Seed with projects
await db.one(
sql`INSERT INTO public.projects (clean_id, name, type, org_id) VALUES ('proj-1', 'proj-1', 'SINGLE', ${orgsWithProjects[0].id}) RETURNING *;`,
);
await db.one(
sql`INSERT INTO public.projects (clean_id, name, type, org_id) VALUES ('proj-2', 'proj-2', 'SINGLE', ${orgsWithProjects[1].id}) RETURNING *;`,
);

// Run the additional remaining migrations
await complete();

// Only this one should be deleted, the rest should still exists
assert.equal(
await db.maybeOne(sql`SELECT * FROM public.organizations WHERE id = ${emptyOrgs[0].id}`),
null,
);
assert.notEqual(
await db.maybeOne(sql`SELECT * FROM public.organizations WHERE id = ${emptyOrgs[1].id}`),
null,
);
assert.notEqual(
await db.maybeOne(
sql`SELECT * FROM public.organizations WHERE id = ${orgsWithProjects[0].id}`,
),
null,
);
assert.notEqual(
await db.maybeOne(
sql`SELECT * FROM public.organizations WHERE id = ${orgsWithProjects[1].id}`,
),
null,
);
} finally {
await done();
}
});
});
71 changes: 71 additions & 0 deletions packages/migrations/test/utils/testkit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* eslint-disable import/first */
/* eslint-disable import/no-extraneous-dependencies */
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { config } from 'dotenv';
import pgpFactory from 'pg-promise';
import { createPool, sql } from 'slonik';
import { SlonikMigrator } from '@slonik/migrator';
import type * as DbTypes from '../../../services/storage/src/db/types';
import { createConnectionString } from '../../src/connection-string';

export { DbTypes };

const __dirname = dirname(fileURLToPath(import.meta.url));

config({
path: resolve(__dirname, '../../.env'),
});

import { env } from '../../src/environment';

export async function initMigrationTestingEnvironment() {
const pgp = pgpFactory();
const db = pgp(
createConnectionString({
...env.postgres,
db: 'postgres',
}),
);

const dbName = 'migration_test_' + Date.now();
await db.query(`CREATE DATABASE ${dbName};`);

const slonik = await createPool(
createConnectionString({
...env.postgres,
db: dbName,
}),
);

const actionsDirectory = resolve(__dirname + '/../../src/actions/');
console.log('actionsDirectory', actionsDirectory);

const migrator = new SlonikMigrator({
migrationsPath: actionsDirectory,
slonik,
migrationTableName: 'migration',
logger: console,
});

return {
db: slonik,
async runTo(name: string) {
await migrator.up({ to: name });
},
seed: {
async user() {
return await slonik.one<DbTypes.users>(
sql`INSERT INTO public.users (email, display_name, full_name, supertoken_user_id) VALUES ('test@mail.com', 'test1' , 'test1', '1') RETURNING *;`,
);
},
},
async complete() {
await migrator.up();
},
async done(deleteDb = true) {
deleteDb ?? (await db.query(`DROP DATABASE ${dbName};`));
await db.$pool.end().catch();
},
};
}
2 changes: 1 addition & 1 deletion packages/services/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export type {
} from './shared/entities';
export { minifySchema } from './shared/schema';
export { HiveError } from './shared/errors';
export { OrganizationType, ProjectType } from './__generated__/types';
export { ProjectType } from './__generated__/types';
export type { AuthProvider } from './__generated__/types';
export { HttpClient } from './modules/shared/providers/http-client';
export { OperationsManager } from './modules/operations/providers/operations-manager';
Expand Down
Loading

0 comments on commit 8432143

Please sign in to comment.