mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Fix publishing of a service right after deleting it (#1326)
This commit is contained in:
parent
de21913717
commit
99f7c66a44
10 changed files with 136 additions and 6 deletions
5
.changeset/tasty-lemons-vanish.md
Normal file
5
.changeset/tasty-lemons-vanish.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@graphql-hive/cli': patch
|
||||
---
|
||||
|
||||
Do not show "Skipping" when publishing schema to the modern model
|
||||
|
|
@ -114,3 +114,111 @@ describe.each`
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe.each`
|
||||
projectType
|
||||
${ProjectType.Stitching}
|
||||
${ProjectType.Federation}
|
||||
`('$projectType', ({ projectType }) => {
|
||||
test.concurrent(
|
||||
'should publish A, publish B, delete B, publish A and have A and B at the end',
|
||||
async () => {
|
||||
const { createOrg } = await initSeed().createOwner();
|
||||
const { createProject } = await createOrg();
|
||||
const { createToken } = await createProject(projectType);
|
||||
const { publishSchema, deleteSchema, fetchVersions, fetchLatestValidSchema } =
|
||||
await createToken({
|
||||
targetScopes: [TargetAccessScope.RegistryRead, TargetAccessScope.RegistryWrite],
|
||||
projectScopes: [],
|
||||
organizationScopes: [],
|
||||
});
|
||||
|
||||
const serviceA = /* GraphQL */ `
|
||||
type Query {
|
||||
topProduct: Product
|
||||
}
|
||||
|
||||
type Product {
|
||||
id: ID!
|
||||
name: String
|
||||
}
|
||||
`;
|
||||
|
||||
const serviceB = /* GraphQL */ `
|
||||
type Query {
|
||||
topReview: Review
|
||||
}
|
||||
|
||||
type Review {
|
||||
id: ID!
|
||||
title: String
|
||||
}
|
||||
`;
|
||||
|
||||
await publishSchema({
|
||||
author: 'Kamil',
|
||||
commit: 'push1',
|
||||
sdl: serviceA,
|
||||
service: 'service-a',
|
||||
url: 'http://localhost:4001',
|
||||
}).then(r => r.expectNoGraphQLErrors());
|
||||
|
||||
await expect(fetchVersions(2)).resolves.toHaveLength(1);
|
||||
|
||||
await publishSchema({
|
||||
author: 'Kamil',
|
||||
commit: 'push2',
|
||||
sdl: serviceB,
|
||||
service: 'service-b',
|
||||
url: 'http://localhost:4002',
|
||||
}).then(r => r.expectNoGraphQLErrors());
|
||||
|
||||
// We should have 2 versions (push, push)
|
||||
await expect(fetchVersions(3)).resolves.toHaveLength(2);
|
||||
|
||||
await expect(deleteSchema('service-b').then(r => r.expectNoGraphQLErrors())).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
schemaDelete: {
|
||||
__typename: 'SchemaDeleteSuccess',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const versions = await fetchVersions(4);
|
||||
|
||||
// We should have 3 versions (push, push, delete)
|
||||
expect(versions).toHaveLength(3);
|
||||
// Most recent version should be a delete action
|
||||
expect(versions[0].log).toEqual({
|
||||
__typename: 'DeletedSchemaLog',
|
||||
deletedService: 'service-b',
|
||||
});
|
||||
|
||||
await publishSchema({
|
||||
author: 'Kamil',
|
||||
commit: 'push3',
|
||||
sdl: serviceB,
|
||||
service: 'service-b',
|
||||
url: 'http://localhost:4002',
|
||||
}).then(r => r.expectNoGraphQLErrors());
|
||||
|
||||
// We should have 4 versions (push, push, delete, push)
|
||||
await expect(fetchVersions(5)).resolves.toHaveLength(4);
|
||||
|
||||
const latestValid = await fetchLatestValidSchema();
|
||||
expect(latestValid.latestValidVersion).toBeDefined();
|
||||
expect(latestValid.latestValidVersion?.log.__typename).toEqual('PushedSchemaLog');
|
||||
expect(latestValid.latestValidVersion?.schemas.nodes).toHaveLength(2);
|
||||
expect(latestValid.latestValidVersion?.schemas.nodes).toContainEqual(
|
||||
expect.objectContaining({
|
||||
commit: 'push1',
|
||||
}),
|
||||
);
|
||||
expect(latestValid.latestValidVersion?.schemas.nodes).toContainEqual(
|
||||
expect.objectContaining({
|
||||
commit: 'push3',
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
9
packages/libraries/cli/examples/stitching.users.graphql
Normal file
9
packages/libraries/cli/examples/stitching.users.graphql
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
type User {
|
||||
id: ID!
|
||||
username: String!
|
||||
email: String!
|
||||
}
|
||||
|
||||
type Query {
|
||||
users(ids: [ID!]!): [User]! @merge(keyField: "id") @canonical
|
||||
}
|
||||
|
|
@ -38,8 +38,8 @@
|
|||
"prepack": "rimraf lib && tsc -b && oclif manifest && oclif readme",
|
||||
"schema:check:federation": "pnpm start schema:check examples/federation.graphql --service reviews",
|
||||
"schema:check:single": "pnpm start schema:check examples/single.graphql",
|
||||
"schema:check:stitching": "pnpm start schema:check examples/stitching.graphql --service posts",
|
||||
"schema:publish:federation": "pnpm start schema:publish --service reviews examples/federation.reviews.graphql",
|
||||
"schema:check:stitching": "pnpm start schema:check --service posts examples/stitching.posts.graphql",
|
||||
"schema:publish:federation": "pnpm start schema:publish --service reviews --url reviews.com/graphql examples/federation.reviews.graphql",
|
||||
"start": "./bin/dev",
|
||||
"version": "oclif readme && git add README.md"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -194,10 +194,12 @@ export default class SchemaPublish extends Command {
|
|||
this.success('Published initial schema.');
|
||||
} else if (result.schemaPublish.successMessage) {
|
||||
this.success(result.schemaPublish.successMessage);
|
||||
} else if (!changes?.total) {
|
||||
} else if (changes && changes.total === 0) {
|
||||
this.success('No changes. Skipping.');
|
||||
} else {
|
||||
renderChanges.call(this, changes);
|
||||
if (changes) {
|
||||
renderChanges.call(this, changes);
|
||||
}
|
||||
this.success('Schema published');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ export class RegistryChecks {
|
|||
constructor(private helper: SchemaHelper, private inspector: Inspector, private logger: Logger) {}
|
||||
|
||||
async checksum({ schemas, latestVersion }: { schemas: Schemas; latestVersion: LatestVersion }) {
|
||||
this.logger.debug(
|
||||
'Checksum check (before=%s, after=%s)',
|
||||
latestVersion?.schemas.length ?? 0,
|
||||
schemas.length,
|
||||
);
|
||||
const isInitial = latestVersion === null;
|
||||
|
||||
if (isInitial) {
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ export class SchemaPublisher {
|
|||
await unlock();
|
||||
}
|
||||
},
|
||||
ttl: 60,
|
||||
ttl: 15,
|
||||
span,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
LOG_LEVEL=debug
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=postgres
|
||||
POSTGRES_HOST=localhost
|
||||
|
|
|
|||
|
|
@ -1732,7 +1732,7 @@ export async function createStorage(connection: string, maximumPoolSize: number)
|
|||
FROM public.schema_versions as sv
|
||||
LEFT JOIN public.targets as t ON (t.id = sv.target_id)
|
||||
LEFT JOIN public.schema_log as sl ON (sl.id = sv.action_id)
|
||||
WHERE t.id = ${target} AND t.project_id = ${project} AND sl.action = 'PUSH'
|
||||
WHERE t.id = ${target} AND t.project_id = ${project}
|
||||
ORDER BY sv.created_at DESC
|
||||
LIMIT 1
|
||||
`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue