mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Fix the default retention period of personal plans in PG (#949)
This commit is contained in:
parent
7c84107e9f
commit
21a135b9d4
14 changed files with 117 additions and 11 deletions
|
|
@ -20,3 +20,4 @@ RATE_LIMIT_ENDPOINT=http://rate-limit:3009
|
|||
CLICKHOUSE_ASYNC_INSERT_BUSY_TIMEOUT_MS=500
|
||||
CLICKHOUSE_ASYNC_INSERT_MAX_DATA_SIZE=1000
|
||||
EXTERNAL_COMPOSITION_SECRET=secretsecret
|
||||
LIMIT_CACHE_UPDATE_INTERVAL_MS=2000
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ services:
|
|||
environment:
|
||||
NODE_ENV: production
|
||||
LOG_LEVEL: debug
|
||||
LIMIT_CACHE_UPDATE_INTERVAL_MS: 2000
|
||||
LIMIT_CACHE_UPDATE_INTERVAL_MS: '${LIMIT_CACHE_UPDATE_INTERVAL_MS}'
|
||||
POSTGRES_HOST: db
|
||||
POSTGRES_PORT: 5432
|
||||
POSTGRES_DB: '${POSTGRES_DB}'
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default {
|
|||
}),
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1',
|
||||
},
|
||||
testTimeout: 200000,
|
||||
testTimeout: 30_000,
|
||||
setupFilesAfterEnv: ['dotenv/config'],
|
||||
collectCoverage: false,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
"zod": "3.20.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hive/rate-limit": "workspace:*",
|
||||
"@hive/server": "workspace:*",
|
||||
"@types/dockerode": "3.3.14",
|
||||
"@types/ioredis": "4.28.10",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { gql } from '@app/gql';
|
||||
import {
|
||||
OrganizationAccessScope,
|
||||
OrganizationType,
|
||||
ProjectAccessScope,
|
||||
ProjectType,
|
||||
TargetAccessScope,
|
||||
|
|
@ -31,6 +33,7 @@ import {
|
|||
updateMemberAccess,
|
||||
updateSchemaVersionStatus,
|
||||
} from './flow';
|
||||
import { execute } from './graphql';
|
||||
import { collect, CollectedOperation } from './usage';
|
||||
import { generateUnique } from './utils';
|
||||
|
||||
|
|
@ -45,6 +48,48 @@ export function initSeed() {
|
|||
return {
|
||||
ownerEmail,
|
||||
ownerToken,
|
||||
async createPersonalProject(projectType: ProjectType) {
|
||||
const orgs = await execute({
|
||||
document: gql(/* 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 =>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { ProjectType, TargetAccessScope } from '@app/gql/graphql';
|
||||
import {
|
||||
DeleteObjectsCommand,
|
||||
GetObjectCommand,
|
||||
|
|
@ -5,7 +6,6 @@ import {
|
|||
S3Client,
|
||||
} from '@aws-sdk/client-s3';
|
||||
import { fetch } from '@whatwg-node/fetch';
|
||||
import { ProjectType, TargetAccessScope } from '../../testkit/gql/graphql';
|
||||
import { initSeed } from '../../testkit/seed';
|
||||
import { getServiceHost } from '../../testkit/utils';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
import { OrganizationAccessScope, ProjectAccessScope, TargetAccessScope } from '@app/gql/graphql';
|
||||
import {
|
||||
answerOrganizationTransferRequest,
|
||||
getOrganizationTransferRequest,
|
||||
requestOrganizationTransfer,
|
||||
} from '../../../testkit/flow';
|
||||
import {
|
||||
OrganizationAccessScope,
|
||||
ProjectAccessScope,
|
||||
TargetAccessScope,
|
||||
} from '../../../testkit/gql/graphql';
|
||||
import { initSeed } from '../../../testkit/seed';
|
||||
|
||||
test.concurrent(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,17 @@
|
|||
import { gql } from '@app/gql';
|
||||
import { ProjectType } from '@app/gql/graphql';
|
||||
import type { RateLimitApi } from '@hive/rate-limit';
|
||||
import { createTRPCProxyClient, httpLink } from '@trpc/client';
|
||||
import { createFetch } from '@whatwg-node/fetch';
|
||||
import { ensureEnv } from '../../testkit/env';
|
||||
import { waitFor } from '../../testkit/flow';
|
||||
import { execute } from '../../testkit/graphql';
|
||||
import { initSeed } from '../../testkit/seed';
|
||||
import { getServiceHost } from '../../testkit/utils';
|
||||
|
||||
const { fetch } = createFetch({
|
||||
useNodeFetch: true,
|
||||
});
|
||||
|
||||
test.concurrent('should auto-create an organization for freshly signed-up user', async () => {
|
||||
const { ownerToken } = await initSeed().createOwner();
|
||||
|
|
@ -22,6 +33,49 @@ test.concurrent('should auto-create an organization for freshly signed-up user',
|
|||
expect(result.organizations.total).toBe(1);
|
||||
});
|
||||
|
||||
test.concurrent(
|
||||
'freshly signed-up user should have a Hobby plan with 7 days of retention',
|
||||
async () => {
|
||||
const { ownerToken, createPersonalProject } = await initSeed().createOwner();
|
||||
const result = await execute({
|
||||
document: gql(/* GraphQL */ `
|
||||
query organizations {
|
||||
organizations {
|
||||
total
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
authToken: ownerToken,
|
||||
}).then(r => r.expectNoGraphQLErrors());
|
||||
|
||||
expect(result.organizations.total).toBe(1);
|
||||
|
||||
const { target } = await createPersonalProject(ProjectType.Single);
|
||||
|
||||
await waitFor(ensureEnv('LIMIT_CACHE_UPDATE_INTERVAL_MS', 'number') + 1_000); // wait for rate-limit to update
|
||||
|
||||
const rateLimit = createTRPCProxyClient<RateLimitApi>({
|
||||
links: [
|
||||
httpLink({
|
||||
url: `http://${await getServiceHost('rate-limit', 3009)}/trpc`,
|
||||
fetch,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
// Expect the default retention for a Hobby plan to be 7 days
|
||||
await expect(
|
||||
rateLimit.getRetention.query({
|
||||
targetId: target.id,
|
||||
}),
|
||||
).resolves.toEqual(7);
|
||||
},
|
||||
);
|
||||
|
||||
test.concurrent(
|
||||
'should auto-create an organization for freshly signed-up user with no race-conditions',
|
||||
async () => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-disable no-process-env */
|
||||
import { createHash } from 'node:crypto';
|
||||
import { ProjectType } from '@app/gql/graphql';
|
||||
import { schemaCheck, schemaPublish } from '../../testkit/cli';
|
||||
import { ProjectType } from '../../testkit/gql/graphql';
|
||||
import { initSeed } from '../../testkit/seed';
|
||||
|
||||
test.concurrent('can publish and check a schema with target:registry:read access', async () => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
"esModuleInterop": true,
|
||||
"paths": {
|
||||
"@hive/server": ["../packages/services/server/src/api.ts"],
|
||||
"@hive/storage": ["../packages/services/storage/src/index.ts"]
|
||||
"@hive/storage": ["../packages/services/storage/src/index.ts"],
|
||||
"@hive/rate-limit": ["../packages/services/rate-limit/src/api.ts"]
|
||||
}
|
||||
},
|
||||
"include": ["testkit", "tests"]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export type RateLimitInput = z.infer<typeof VALIDATION>;
|
|||
|
||||
const VALIDATION = z
|
||||
.object({
|
||||
id: z.string().nonempty(),
|
||||
id: z.string().min(1),
|
||||
entityType: z.enum(['organization', 'target']),
|
||||
type: z.enum(['operations-reporting']),
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
-- Update Hobby with 3d to 7d - personal orgs were created with the default value of 3d
|
||||
UPDATE public.organizations SET limit_retention_days = 7 WHERE plan_name = 'HOBBY' AND limit_retention_days = 3;
|
||||
|
||||
-- Update limit_retention_days default value to 7
|
||||
ALTER table public.organizations ALTER COLUMN limit_retention_days SET DEFAULT 7;
|
||||
|
|
@ -0,0 +1 @@
|
|||
-- no need
|
||||
|
|
@ -157,6 +157,7 @@ importers:
|
|||
'@esm2cjs/execa': 6.1.1-cjs.1
|
||||
'@graphql-hive/core': 0.2.3
|
||||
'@graphql-typed-document-node/core': 3.1.1
|
||||
'@hive/rate-limit': workspace:*
|
||||
'@hive/server': workspace:*
|
||||
'@trpc/client': 10.7.0
|
||||
'@trpc/server': 10.7.0
|
||||
|
|
@ -196,6 +197,7 @@ importers:
|
|||
slonik: 30.1.2_wg2hxbo7txnklmvja4aeqnygfi
|
||||
zod: 3.20.2
|
||||
devDependencies:
|
||||
'@hive/rate-limit': link:../packages/services/rate-limit
|
||||
'@hive/server': link:../packages/services/server
|
||||
'@types/dockerode': 3.3.14
|
||||
'@types/ioredis': 4.28.10
|
||||
|
|
|
|||
Loading…
Reference in a new issue