Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/eight-views-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'hive': minor
---

adjust change capture and resolvers to optionally provide a full list or the simplified list of
changes
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let schemaCheckCount = await db.oneFirst<number>(
Expand Down Expand Up @@ -166,6 +167,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

await storage.createSchemaCheck({
Expand All @@ -192,6 +194,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let schemaCheckCount = await db.oneFirst<number>(
Expand Down Expand Up @@ -275,6 +278,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

await storage.createSchemaCheck({
Expand All @@ -301,6 +305,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let schemaCheckCount = await db.oneFirst<number>(
Expand Down Expand Up @@ -394,6 +399,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

await storage.createSchemaCheck({
Expand All @@ -420,6 +426,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let schemaCheckCount = await db.oneFirst<number>(
Expand Down Expand Up @@ -571,6 +578,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

await storage.createSchemaCheck({
Expand All @@ -597,6 +605,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let schemaCheckCount = await db.oneFirst<number>(
Expand Down Expand Up @@ -745,6 +754,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let sdlStoreCount = await db.oneFirst<number>(sql`SELECT count(*) as total FROM sdl_store`);
Expand Down Expand Up @@ -856,6 +866,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let schemaCheckCount = await db.oneFirst<number>(
Expand Down Expand Up @@ -1016,6 +1027,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

await storage.createSchemaCheck({
Expand Down Expand Up @@ -1061,6 +1073,7 @@ describe('schema check purging', async () => {
schemaPolicyWarnings: null,
conditionalBreakingChangeMetadata: null,
serviceUrl: null,
schemaProposalId: null,
});

let schemaCheckCount = await db.oneFirst<number>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
type GraphQLSchema,
} from 'graphql';
import { Injectable, Scope } from 'graphql-modules';
import { Change, ChangeType, diff, DiffRule, TypeOfChangeType } from '@graphql-inspector/core';
import { Change, ChangeType, diff, Rule, TypeOfChangeType } from '@graphql-inspector/core';
import { traceFn } from '@hive/service-common';
import { HiveSchemaChangeModel } from '@hive/storage';
import { Logger } from '../../shared/providers/logger';
Expand All @@ -31,10 +31,10 @@ export class Inspector {
'hive.diff.changes.count': result.length,
}),
})
async diff(existing: GraphQLSchema, incoming: GraphQLSchema) {
async diff(existing: GraphQLSchema, incoming: GraphQLSchema, rules?: Rule[]) {
this.logger.debug('Comparing Schemas');

const changes = await diff(existing, incoming, [DiffRule.simplifyChanges]);
const changes = await diff(existing, incoming, rules);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change exposes the rules option up the callstack so it can be modifies.


return changes
.filter(dropTrimmedDescriptionChangedChange)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class CompositeModel {
existingSdl: contract.latestValidVersion?.compositeSchemaSdl ?? null,
incomingSdl: contractCompositionResult?.result?.fullSchemaSdl ?? null,
failDiffOnDangerousChange: args.failDiffOnDangerousChange,
filterNestedChanges: true,
}),
};
}),
Expand All @@ -103,6 +104,7 @@ export class CompositeModel {
conditionalBreakingChangeDiffConfig,
contracts,
failDiffOnDangerousChange,
filterNestedChanges,
}: {
input: {
sdl: string;
Expand Down Expand Up @@ -136,6 +138,7 @@ export class CompositeModel {
approvedChanges: Map<string, SchemaChangeType> | null;
}
> | null;
filterNestedChanges: boolean;
}): Promise<SchemaCheckResult> {
const incoming: PushedCompositeSchema = {
kind: 'composite',
Expand Down Expand Up @@ -228,6 +231,7 @@ export class CompositeModel {
compositionCheck.result?.fullSchemaSdl ?? compositionCheck.reason?.fullSchemaSdl ?? null,
conditionalBreakingChangeConfig: conditionalBreakingChangeDiffConfig,
failDiffOnDangerousChange,
filterNestedChanges,
}),
this.checks.policyCheck({
selector,
Expand Down Expand Up @@ -487,6 +491,7 @@ export class CompositeModel {
existingSdl: previousVersionSdl,
incomingSdl: compositionCheck.result?.fullSchemaSdl ?? null,
failDiffOnDangerousChange,
filterNestedChanges: true, // filter because publish is never associated to schema proposals in this way.
});

const contractChecks = await this.getContractChecks({
Expand Down Expand Up @@ -652,6 +657,7 @@ export class CompositeModel {
existingSdl: previousVersionSdl,
incomingSdl: compositionCheck.result?.fullSchemaSdl ?? null,
failDiffOnDangerousChange,
filterNestedChanges: true, // filter because deletes are never associated with schema proposals in this way.
});

const contractChecks = await this.getContractChecks({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class SingleModel {
approvedChanges,
conditionalBreakingChangeDiffConfig,
failDiffOnDangerousChange,
filterNestedChanges,
}: {
input: {
sdl: string;
Expand All @@ -68,6 +69,7 @@ export class SingleModel {
approvedChanges: Map<string, SchemaChangeType>;
conditionalBreakingChangeDiffConfig: null | ConditionalBreakingChangeDiffConfig;
failDiffOnDangerousChange: boolean;
filterNestedChanges: boolean;
}): Promise<SchemaCheckResult> {
const incoming: SingleSchema = {
kind: 'single',
Expand Down Expand Up @@ -130,6 +132,7 @@ export class SingleModel {
existingSdl: previousVersionSdl,
incomingSdl: compositionCheck.result?.fullSchemaSdl ?? null,
failDiffOnDangerousChange,
filterNestedChanges,
}),
this.checks.policyCheck({
selector,
Expand Down Expand Up @@ -267,6 +270,7 @@ export class SingleModel {
existingSdl: previousVersionSdl,
incomingSdl: compositionCheck.result?.fullSchemaSdl ?? null,
failDiffOnDangerousChange,
filterNestedChanges: true, // publish is never associated with schema proposals in this way. So always show the minimal changeset.
}),
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { URL } from 'node:url';
import { type GraphQLSchema } from 'graphql';
import { Injectable, Scope } from 'graphql-modules';
import hashObject from 'object-hash';
import { ChangeType, CriticalityLevel, TypeOfChangeType } from '@graphql-inspector/core';
import { ChangeType, CriticalityLevel, DiffRule, TypeOfChangeType } from '@graphql-inspector/core';
import type { CheckPolicyResponse } from '@hive/policy';
import type { CompositionFailureError, ContractsInputType } from '@hive/schema';
import { traceFn } from '@hive/service-common';
Expand Down Expand Up @@ -426,6 +426,11 @@ export class RegistryChecks {
/** Settings for fetching conditional breaking changes. */
conditionalBreakingChangeConfig: null | ConditionalBreakingChangeDiffConfig;
failDiffOnDangerousChange: null | boolean;
/**
* Set to true to reduce the number of changes to only what's relevant to the user.
* Use false for schema proposals in order to capture every single change record for the patch function.
*/
filterNestedChanges: boolean;
}) {
let existingSchema: GraphQLSchema | null = null;
let incomingSchema: GraphQLSchema | null = null;
Expand Down Expand Up @@ -463,7 +468,11 @@ export class RegistryChecks {
} satisfies CheckResult;
}

let inspectorChanges = await this.inspector.diff(existingSchema, incomingSchema);
let inspectorChanges = await this.inspector.diff(
existingSchema,
incomingSchema,
args.filterNestedChanges ? [DiffRule.simplifyChanges] : [],
);

// Filter out federation specific changes as they are not relevant for the schema diff and were in previous schema versions by accident.
if (args.filterOutFederationChanges === true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ export class SchemaCheckManager {
return null;
}

return [...(schemaCheck.breakingSchemaChanges ?? []), ...(schemaCheck.safeSchemaChanges ?? [])];
const changes = [
...(schemaCheck.breakingSchemaChanges ?? []),
...(schemaCheck.safeSchemaChanges ?? []),
];

return changes;
}

getBreakingSchemaChanges(schemaCheck: SchemaCheck) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,6 @@ export class SchemaPublisher {
}

if (github != null) {
// @todo should proposals do anything special here?
const result = await this.createGithubCheckRunStartForSchemaCheck({
organization,
project,
Expand Down Expand Up @@ -623,6 +622,7 @@ export class SchemaPublisher {
conditionalBreakingChangeDiffConfig:
conditionalBreakingChangeConfiguration?.conditionalBreakingChangeDiffConfig ?? null,
failDiffOnDangerousChange,
filterNestedChanges: !input.schemaProposalId,
});
break;
case ProjectType.FEDERATION:
Expand Down Expand Up @@ -668,6 +668,7 @@ export class SchemaPublisher {
conditionalBreakingChangeDiffConfig:
conditionalBreakingChangeConfiguration?.conditionalBreakingChangeDiffConfig ?? null,
failDiffOnDangerousChange,
filterNestedChanges: !input.schemaProposalId,
});
break;
default:
Expand Down Expand Up @@ -732,7 +733,7 @@ export class SchemaPublisher {
breakingSchemaChanges: contract.schemaChanges?.breaking ?? null,
safeSchemaChanges: contract.schemaChanges?.safe ?? null,
})) ?? null,
schemaProposalId: input.schemaProposalId,
schemaProposalId: input.schemaProposalId ?? null,
});
this.logger.info('created failed schema check. (schemaCheckId=%s)', schemaCheck.id);
} else if (checkResult.conclusion === SchemaCheckConclusion.Success) {
Expand Down Expand Up @@ -779,7 +780,7 @@ export class SchemaPublisher {
breakingSchemaChanges: contract.schemaChanges?.breaking ?? null,
safeSchemaChanges: contract.schemaChanges?.safe ?? null,
})) ?? null,
schemaProposalId: input.schemaProposalId,
schemaProposalId: input.schemaProposalId ?? null,
});
this.logger.info('created successful schema check. (schemaCheckId=%s)', schemaCheck.id);
} else if (checkResult.conclusion === SchemaCheckConclusion.Skip) {
Expand Down Expand Up @@ -858,7 +859,7 @@ export class SchemaPublisher {
})),
)
: null,
schemaProposalId: input.schemaProposalId,
schemaProposalId: input.schemaProposalId ?? null,
});
this.logger.info('created skipped schema check. (schemaCheckId=%s)', schemaCheck.id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,11 @@ export class SchemaVersionHelper {
}

if (schemaVersion.hasPersistedSchemaChanges) {
const changes = await this.storage.getSchemaChangesForVersion({
versionId: schemaVersion.id,
});
const changes: null | Array<SchemaChangeType> = await this.storage.getSchemaChangesForVersion(
{
versionId: schemaVersion.id,
},
);

const safeChanges: Array<SchemaChangeType> = [];
const breakingChanges: Array<SchemaChangeType> = [];
Expand Down Expand Up @@ -241,6 +243,7 @@ export class SchemaVersionHelper {
filterOutFederationChanges: project.type === ProjectType.FEDERATION,
conditionalBreakingChangeConfig: null,
failDiffOnDangerousChange,
filterNestedChanges: true,
});

if (diffCheck.status === 'skipped') {
Expand Down
13 changes: 7 additions & 6 deletions packages/services/storage/src/schema-change-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1012,25 +1012,25 @@ export const ObjectTypeInterfaceRemovedModel = implement<ObjectTypeInterfaceRemo
export const SchemaQueryTypeChangedModel = implement<SchemaQueryTypeChangedChange>().with({
type: SchemaQueryTypeChangedLiteral,
meta: z.object({
oldQueryTypeName: z.string(),
newQueryTypeName: z.string(),
oldQueryTypeName: z.string().nullable(),
newQueryTypeName: z.string().nullable(),
}),
});

export const SchemaMutationTypeChangedModel = implement<SchemaMutationTypeChangedChange>().with({
type: SchemaMutationTypeChangedLiteral,
meta: z.object({
oldMutationTypeName: z.string(),
newMutationTypeName: z.string(),
oldMutationTypeName: z.string().nullable(),
newMutationTypeName: z.string().nullable(),
}),
});

export const SchemaSubscriptionTypeChangedModel =
implement<SchemaSubscriptionTypeChangedChange>().with({
type: SchemaSubscriptionTypeChangedLiteral,
meta: z.object({
oldSubscriptionTypeName: z.string(),
newSubscriptionTypeName: z.string(),
oldSubscriptionTypeName: z.string().nullable(),
newSubscriptionTypeName: z.string().nullable(),
}),
});

Expand Down Expand Up @@ -1414,6 +1414,7 @@ const SchemaCheckSharedOutputFields = {
serviceUrl: z.string().nullable(),
targetId: z.string(),
schemaVersionId: z.string().nullable(),
schemaProposalId: z.string().nullable(),
meta: z
.object({
author: z.string(),
Expand Down
Loading
Loading