Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow to upsert a subgraph on publish #196

Merged
merged 44 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
a9868b4
feat: Allow to upsert a subgraph on publish
StarpTech Oct 20, 2023
ca68a88
chore: improve
StarpTech Oct 20, 2023
386b801
Merge branch 'main' into dustin/eng-4352-wgc-createorpublish
StarpTech Oct 20, 2023
3d78f43
chore: improve
StarpTech Oct 20, 2023
5b8f5fd
chore: improve
StarpTech Oct 20, 2023
14704a1
chore: improve
StarpTech Oct 20, 2023
5a9a075
chore: improve
StarpTech Oct 21, 2023
991b9fd
chore: improve
StarpTech Oct 21, 2023
4eeb007
chore: improve
StarpTech Oct 21, 2023
4d95b57
chore: improve
StarpTech Oct 21, 2023
49b8539
chore: improve
StarpTech Oct 21, 2023
3fce3fb
chore: improve
StarpTech Oct 21, 2023
e01aba2
chore: improve
StarpTech Oct 21, 2023
33931e4
chore: improve
StarpTech Oct 21, 2023
fc5d798
chore: improve
StarpTech Oct 21, 2023
3c53449
chore: improve
StarpTech Oct 21, 2023
fd81da8
chore: improve
StarpTech Oct 21, 2023
2b90ae9
chore: improve
StarpTech Oct 21, 2023
30ced31
chore: improve
StarpTech Oct 22, 2023
bce48d4
chore: improve
StarpTech Oct 22, 2023
e3fbc11
fix: migrate from apollo
JivusAyrus Oct 22, 2023
e6e7ecc
fix: handle text overflow
JivusAyrus Oct 22, 2023
c77b9f4
chore: refactor tests, add new publish tests
StarpTech Oct 22, 2023
9fbcfe5
chore: improve
StarpTech Oct 22, 2023
e20a9fb
chore: improve
StarpTech Oct 22, 2023
5d90708
chore: improve
StarpTech Oct 22, 2023
54c679b
chore: improve
StarpTech Oct 22, 2023
a6f78e9
fix: fetch latest valid schema version while fetching the sdl
JivusAyrus Oct 22, 2023
718e346
chore: improve
StarpTech Oct 22, 2023
8e41ecf
chore: improve
StarpTech Oct 22, 2023
b531971
chore: improve
StarpTech Oct 22, 2023
34fd013
chore: improve
StarpTech Oct 22, 2023
283bfb6
chore: improve
StarpTech Oct 22, 2023
1eb9170
chore: improve
StarpTech Oct 22, 2023
91e0cd7
chore: improve
StarpTech Oct 22, 2023
6961d15
chore: improve
StarpTech Oct 22, 2023
bd0f51f
chore: improve
StarpTech Oct 22, 2023
078b4a7
chore: improve
StarpTech Oct 22, 2023
800db28
chore: improve
StarpTech Oct 22, 2023
97af483
chore: improve
StarpTech Oct 22, 2023
bb63e29
chore: improve
StarpTech Oct 22, 2023
ed10dea
chore: improve
StarpTech Oct 22, 2023
ee60bfb
chore: improve
StarpTech Oct 22, 2023
3b5c6ab
chore: improve
StarpTech Oct 22, 2023
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
12 changes: 12 additions & 0 deletions .run/router.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="router" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="cosmo" />
<working_directory value="$PROJECT_DIR$/router" />
<go_parameters value="-race" />
<kind value="FILE" />
<package value="github.com/wundergraph/cosmo/router" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/router/cmd/router/main.go" />
<method v="2" />
</configuration>
</component>
4 changes: 2 additions & 2 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@
"@types/js-yaml": "^4.0.5",
"@types/node": "^20.3.1",
"del-cli": "^5.0.0",
"eslint": "^8.44.0",
"eslint": "^8.52.0",
"eslint-config-unjs": "^0.2.1",
"prettier": "^2.8.8",
"tsx": "^3.12.7",
"tsx": "^3.14.0",
"typescript": "^5.2.2",
"vitest": "^0.34.1"
},
Expand Down
2 changes: 1 addition & 1 deletion cli/src/commands/federated-graph/commands/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Command } from 'commander';
import pc from 'picocolors';
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
import inquirer from 'inquirer';
import { BaseCommandOptions } from '../../../core/types/types.js';
import { baseHeaders } from '../../../core/config.js';
import { BaseCommandOptions } from '../../../core/types/types.js';

export default (opts: BaseCommandOptions) => {
const deleteFederatedGraph = new Command('delete');
Expand Down
2 changes: 1 addition & 1 deletion cli/src/commands/federated-graph/commands/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default (opts: BaseCommandOptions) => {
for (const graph of resp.graphs) {
graphsTable.push([
graph.name,
graph.labelMatchers.join(','),
graph.labelMatchers.map((l) => `(${l})`).join(','),
graph.routingURL,
graph.isComposable ? logSymbols.success : logSymbols.error,
graph.lastUpdatedAt,
Expand Down
9 changes: 2 additions & 7 deletions cli/src/commands/subgraph/commands/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,12 @@ export default (opts: BaseCommandOptions) => {
'--subscription-protocol <protocol>',
'The protocol to use when subscribing to the subgraph. The supported protocols are ws, sse, and sse-post.',
);

schemaPush.action(async (name, options) => {
const resp = await opts.client.platform.createFederatedSubgraph(
{
name,
labels: options.label.map((label: string) => {
const { key, value } = splitLabel(label);
return {
key,
value,
};
}),
labels: options.label.map((label: string) => splitLabel(label)),
routingUrl: options.routingUrl,
headers: options.header,
// If the argument is provided but the URL is not, clear it
Expand Down
24 changes: 22 additions & 2 deletions cli/src/commands/subgraph/commands/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Command } from 'commander';
import pc from 'picocolors';
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
import inquirer from 'inquirer';
import Table from 'cli-table3';
import { BaseCommandOptions } from '../../../core/types/types.js';
import { baseHeaders } from '../../../core/config.js';

Expand Down Expand Up @@ -32,9 +33,28 @@ export default (opts: BaseCommandOptions) => {
);

if (resp.response?.code === EnumStatusCode.OK) {
console.log(pc.dim(pc.green(`A subgraph called '${name}' was deleted.`)));
console.log(pc.dim(pc.green(`Subgraph '${name}' was deleted.`)));
} else if (resp.response?.code === EnumStatusCode.ERR_SUBGRAPH_COMPOSITION_FAILED) {
const compositionErrorsTable = new Table({
head: [pc.bold(pc.white('FEDERATED_GRAPH_NAME')), pc.bold(pc.white('ERROR_MESSAGE'))],
colWidths: [30, 120],
wordWrap: true,
});

console.log(
pc.red(
`We found composition errors, while composing the federated graph.\nThe router will continue to work with the latest valid schema.\n${pc.bold(
'Please check the errors below:',
)}`,
),
);
for (const compositionError of resp.compositionErrors) {
compositionErrorsTable.push([compositionError.federatedGraphName, compositionError.message]);
}
// Don't exit here with 1 because the change was still applied
console.log(compositionErrorsTable.toString());
} else {
console.log(`Failed to delete subgraph ${pc.bold(name)}.`);
console.log(pc.red(`Failed to delete subgraph ${pc.bold(name)}.`));
if (resp.response?.details) {
console.log(pc.red(pc.bold(resp.response?.details)));
}
Expand Down
47 changes: 41 additions & 6 deletions cli/src/commands/subgraph/commands/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,43 @@ import { Command } from 'commander';
import { resolve } from 'pathe';
import pc from 'picocolors';
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
import { parseGraphQLSubscriptionProtocol, splitLabel } from '@wundergraph/cosmo-shared';
import { BaseCommandOptions } from '../../../core/types/types.js';
import { baseHeaders } from '../../../core/config.js';

export default (opts: BaseCommandOptions) => {
const schemaPush = new Command('publish');
schemaPush.description('Publishes a subgraph on the control plane.');
schemaPush.description(
"Publishes a subgraph on the control plane. If the subgraph doesn't exists, it will be created.\nIf the publication leads to composition errors, the errors will be visible in the Studio.\nThe router will continue to work with the latest valid schema.\nConsider using the 'wgc subgraph check' command to check for composition errors before publishing.",
);
schemaPush.argument(
'<name>',
'The name of the subgraph to push the schema to. It is usually in the format of <org>.<service.name> and is used to uniquely identify your subgraph.',
);
schemaPush.requiredOption('--schema <path-to-schema>', 'The schema file to upload to the subgraph.');
schemaPush.option(
'-r, --routing-url <url>',
'The routing url of your subgraph. This is the url that the subgraph will be accessible at (Only required to create the subgraph).',
);
schemaPush.option(
'--label [labels...]',
'The labels to apply to the subgraph. The labels are passed in the format <key>=<value> <key>=<value>. Required to create the subgraph.',
[],
);
schemaPush.option(
'--header [headers...]',
'The headers to apply when the subgraph is introspected. This is used for authentication and authorization.',
[],
);
schemaPush.option(
'--subscription-url [url]',
'The url used for subscriptions. If empty, it defaults to same url used for routing.',
);
schemaPush.option(
'--subscription-protocol <protocol>',
'The protocol to use when subscribing to the subgraph. The supported protocols are ws, sse, and sse-post.',
);

schemaPush.action(async (name, options) => {
const schemaFile = resolve(process.cwd(), options.schema);
if (!existsSync(schemaFile)) {
Expand All @@ -30,7 +56,16 @@ export default (opts: BaseCommandOptions) => {
const resp = await opts.client.platform.publishFederatedSubgraph(
{
name,
// Publish schema only
schema: await readFile(schemaFile),
// Optional when subgraph does not exist yet
routingUrl: options.routingUrl,
headers: options.header,
subscriptionUrl: options.subscriptionUrl,
subscriptionProtocol: options.subscriptionProtocol
? parseGraphQLSubscriptionProtocol(options.subscriptionProtocol)
: undefined,
labels: options.label.map((label: string) => splitLabel(label)),
},
{
headers: baseHeaders,
Expand All @@ -40,17 +75,17 @@ export default (opts: BaseCommandOptions) => {
if (resp.response?.code === EnumStatusCode.OK) {
console.log(pc.dim(pc.green(`Subgraph '${name}' was updated successfully.`)));
} else if (resp.response?.code === EnumStatusCode.ERR_SUBGRAPH_COMPOSITION_FAILED) {
console.log(pc.dim(pc.green(`Subgraph '${name}' was updated successfully.`)));

const compositionErrorsTable = new Table({
head: [pc.bold(pc.white('FEDERATED_GRAPH_NAME')), pc.bold(pc.white('ERROR_MESSAGE'))],
colWidths: [30, 120],
wordWrap: true,
});

console.log(
pc.yellow(
'But we found composition errors, while composing the federated graph.\nThe graph will not be updated until the errors are fixed. Please check the errors below:',
pc.red(
`We found composition errors, while composing the federated graph.\nThe router will continue to work with the latest valid schema.\n${pc.bold(
'Please check the errors below:',
)}`,
),
);
for (const compositionError of resp.compositionErrors) {
Expand All @@ -59,7 +94,7 @@ export default (opts: BaseCommandOptions) => {
// Don't exit here with 1 because the change was still applied
console.log(compositionErrorsTable.toString());
} else {
console.log(`Failed to update subgraph '${pc.bold(name)}'.`);
console.log(pc.red(`Failed to update subgraph ${pc.bold(name)}.`));
if (resp.response?.details) {
console.log(pc.red(pc.bold(resp.response?.details)));
}
Expand Down
8 changes: 5 additions & 3 deletions cli/src/commands/subgraph/commands/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ export default (opts: BaseCommandOptions) => {
});

console.log(
pc.yellow(
'But we found composition errors, while composing the federated graph.\nThe graph will not be updated until the errors are fixed. Please check the errors below:',
pc.red(
`We found composition errors, while composing the federated graph.\nThe router will continue to work with the latest valid schema.\n${pc.bold(
'Please check the errors below:',
)}`,
),
);
for (const compositionError of resp.compositionErrors) {
Expand All @@ -77,7 +79,7 @@ export default (opts: BaseCommandOptions) => {
// Don't exit here with 1 because the change was still applied
console.log(compositionErrorsTable.toString());
} else {
console.log(`Failed to update subgraph ${pc.bold(name)}.`);
console.log(pc.red(`Failed to update subgraph ${pc.bold(name)}.`));
if (resp.response?.details) {
console.log(pc.red(pc.bold(resp.response?.details)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ export const getFederatedGraphByName = createQueryService({
}).getFederatedGraphByName;

/**
* GetFederatedGraphSDLByName returns the SDL of the federated graph by name.
* GetFederatedGraphSDLByName returns the latest valid SDL of the federated graph by name.
*
* @generated from rpc wg.cosmo.platform.v1.PlatformService.GetFederatedGraphSDLByName
*/
Expand Down
2 changes: 1 addition & 1 deletion connect/src/wg/cosmo/platform/v1/platform_connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export const PlatformService = {
kind: MethodKind.Unary,
},
/**
* GetFederatedGraphSDLByName returns the SDL of the federated graph by name.
* GetFederatedGraphSDLByName returns the latest valid SDL of the federated graph by name.
*
* @generated from rpc wg.cosmo.platform.v1.PlatformService.GetFederatedGraphSDLByName
*/
Expand Down
46 changes: 46 additions & 0 deletions connect/src/wg/cosmo/platform/v1/platform_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,41 @@ export class PublishFederatedSubgraphRequest extends Message<PublishFederatedSub
*/
schema = new Uint8Array(0);

/**
* routing_url is the URL of the service which will be used to route the requests to the subgraph.
*
* @generated from field: optional string routing_url = 3;
*/
routingUrl?: string;

/**
* labels are the labels of the services which will form the federated graph. If the proposed is not valid, the service will be rejected.
*
* @generated from field: repeated wg.cosmo.platform.v1.Label labels = 4;
*/
labels: Label[] = [];

/**
* headers are the headers which will be used to route the requests to the subgraph.
*
* @generated from field: repeated string headers = 5;
*/
headers: string[] = [];

/**
* subscription protocol to use when subscribing to this subgraph
*
* @generated from field: optional wg.cosmo.common.GraphQLSubscriptionProtocol subscription_protocol = 6;
*/
subscriptionProtocol?: GraphQLSubscriptionProtocol;

/**
* url used for subscriptions
*
* @generated from field: optional string subscription_url = 7;
*/
subscriptionUrl?: string;

constructor(data?: PartialMessage<PublishFederatedSubgraphRequest>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -389,6 +424,11 @@ export class PublishFederatedSubgraphRequest extends Message<PublishFederatedSub
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "schema", kind: "scalar", T: 12 /* ScalarType.BYTES */ },
{ no: 3, name: "routing_url", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 4, name: "labels", kind: "message", T: Label, repeated: true },
{ no: 5, name: "headers", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true },
{ no: 6, name: "subscription_protocol", kind: "enum", T: proto3.getEnumType(GraphQLSubscriptionProtocol), opt: true },
{ no: 7, name: "subscription_url", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): PublishFederatedSubgraphRequest {
Expand Down Expand Up @@ -1107,6 +1147,11 @@ export class DeleteFederatedSubgraphResponse extends Message<DeleteFederatedSubg
*/
response?: Response;

/**
* @generated from field: repeated wg.cosmo.platform.v1.CompositionError compositionErrors = 2;
*/
compositionErrors: CompositionError[] = [];

constructor(data?: PartialMessage<DeleteFederatedSubgraphResponse>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -1116,6 +1161,7 @@ export class DeleteFederatedSubgraphResponse extends Message<DeleteFederatedSubg
static readonly typeName = "wg.cosmo.platform.v1.DeleteFederatedSubgraphResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "response", kind: "message", T: Response },
{ no: 2, name: "compositionErrors", kind: "message", T: CompositionError, repeated: true },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): DeleteFederatedSubgraphResponse {
Expand Down
Loading