Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 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
25 changes: 25 additions & 0 deletions .github/workflows/router-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ jobs:
- name: Install tools
run: make setup-build-tools

- uses: ./.github/actions/node

- name: Install dependencies
run: |
pnpm --filter ./cli --filter ./connect --filter ./shared --filter ./composition --filter ./protographic install --frozen-lockfile
pnpm buf generate --template buf.ts.gen.yaml
pnpm --filter ./cli --filter ./connect --filter ./shared --filter ./composition --filter ./protographic run build

- name: Install Bun For Plugin Building
uses: oven-sh/setup-bun@v2
with:
Expand Down Expand Up @@ -132,6 +140,14 @@ jobs:
- name: Install tools
run: make setup-build-tools

- uses: ./.github/actions/node

- name: Install dependencies
run: |
pnpm --filter ./cli --filter ./connect --filter ./shared --filter ./composition --filter ./protographic install --frozen-lockfile
pnpm buf generate --template buf.ts.gen.yaml
pnpm --filter ./cli --filter ./connect --filter ./shared --filter ./composition --filter ./protographic run build

- name: Install Bun For Plugin Building
uses: oven-sh/setup-bun@v2
with:
Expand Down Expand Up @@ -307,9 +323,18 @@ jobs:
with:
cache-dependency-path: |
router-tests/go.sum

- name: Install tools
run: make setup-build-tools

- uses: ./.github/actions/node

- name: Install dependencies
run: |
pnpm --filter ./cli --filter ./connect --filter ./shared --filter ./composition --filter ./protographic install --frozen-lockfile
pnpm buf generate --template buf.ts.gen.yaml
pnpm --filter ./cli --filter ./connect --filter ./shared --filter ./composition --filter ./protographic run build

- name: Install Bun For Plugin Building
uses: oven-sh/setup-bun@v2
with:
Expand Down
7 changes: 6 additions & 1 deletion cli/src/commands/router/commands/plugin/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,24 @@ export default (opts: BaseCommandOptions) => {
[],
);
command.option('--all-platforms', 'Build for all supported platforms', false);

// Tools installation specific
command.option('--skip-tools-installation', 'Skip tool installation', false);
command.option(
'--force-tools-installation',
'Force tools installation regardless of version check or confirmation',
false,
);
command.option('-y, --yes', 'Automatically answer yes to all prompts', false);

command.option('--go-module-path <path>', 'Go module path to use for the plugin');

command.action(async (directory, options) => {
const startTime = performance.now();
const pluginDir = resolve(directory);
const spinner = Spinner();
const pluginName = path.basename(pluginDir);
const autoConfirmPrompts: boolean = options.yes;

const language = getLanguage(pluginDir);
if (!language) {
Expand All @@ -61,7 +66,7 @@ export default (opts: BaseCommandOptions) => {
try {
// Check and install tools if needed
if (!options.skipToolsInstallation) {
await checkAndInstallTools(options.forceToolsInstallation, language);
await checkAndInstallTools(options.forceToolsInstallation, language, autoConfirmPrompts);
}

// Start the main build process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ export default (opts: BaseCommandOptions) => {
false,
);
command.option('--go-module-path <path>', 'Go module path to use for the plugin');
command.option('-y, --yes', 'Automatically answer yes to all prompts', false);

command.action(async (directory, options) => {
const startTime = performance.now();
const pluginDir = resolve(directory);
const spinner = Spinner();
const pluginName = path.basename(pluginDir);
const autoConfirmPrompts: boolean = options.yes;

const language = getLanguage(pluginDir);
if (!language) {
Expand All @@ -48,7 +50,7 @@ export default (opts: BaseCommandOptions) => {
try {
// Check and install tools if needed
if (!options.skipToolsInstallation) {
await checkAndInstallTools(options.forceToolsInstallation, language);
await checkAndInstallTools(options.forceToolsInstallation, language, autoConfirmPrompts);
}

// Start the generation process
Expand Down
4 changes: 3 additions & 1 deletion cli/src/commands/router/commands/plugin/commands/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ export default (opts: BaseCommandOptions) => {
'Force tools installation regardless of version check or confirmation',
false,
);
command.option('-y, --yes', 'Automatically answer yes to all prompts', false);

command.action(async (directory, options) => {
const startTime = performance.now();
const pluginDir = resolve(directory);
const spinner = Spinner({ text: 'Running tests...' });
const pluginName = path.basename(pluginDir);
const autoConfirmPrompts: boolean = options.yes;

const language = getLanguage(pluginDir);
if (!language) {
Expand All @@ -42,7 +44,7 @@ export default (opts: BaseCommandOptions) => {
try {
// Check and install tools if needed
if (!options.skipToolsInstallation) {
await checkAndInstallTools(options.forceToolsInstallation, language);
await checkAndInstallTools(options.forceToolsInstallation, language, autoConfirmPrompts);
}

spinner.start();
Expand Down
51 changes: 32 additions & 19 deletions cli/src/commands/router/commands/plugin/toolchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,22 +354,22 @@ export function validateAndGetGoModulePath(language: string, goModulePath: strin
/**
* Check if tools need installation and ask the user if needed
*/
export async function checkAndInstallTools(force = false, language: string): Promise<boolean> {
export async function checkAndInstallTools(
force = false,
language: string,
autoConfirmPrompts: boolean,
): Promise<boolean> {
const [needsReinstall, shouldCleanup] = await shouldReinstallTools(force, language);

if (!needsReinstall) {
return true;
}

// Ask user for confirmation to install tools
const installMessage = existsSync(TOOLS_DIR)
? 'Version changes detected. Install required toolchain?'
: 'Install required toolchain?';

const toolVersionsForLanguage = LanguageSpecificTools[language];

// Create a more informative message with simple formatting
const toolsInfo = Object.entries(toolVersionsForLanguage)
.filter(([tool]) => shouldCleanup || !Object.keys(COMMON_TOOL_VERSIONS).includes(tool))
.map(([tool, { range: version }]) => ` ${pc.cyan('•')} ${pc.bold(tool)}: ${version}`)
.join('\n');

Expand All @@ -379,22 +379,35 @@ export async function checkAndInstallTools(force = false, language: string): Pro
pc.white('The following tools are needed to build the router plugin:') +
'\n\n' +
toolsInfo +
'\n\n' +
pc.white('You can install them automatically or manually install them yourself') +
'\n' +
pc.white('by following the documentation at https://cosmo-docs.wundergraph.com') +
'\n',
'\n\n',
);

const response = await prompts({
type: 'confirm',
name: 'installTools',
message: installMessage,
});
// In case of auto-confirm, skip the prompt
if (autoConfirmPrompts) {
console.log(pc.white('These tools will now be automatically installed') + '\n');
} else {
console.log(
pc.white('You can install them automatically or manually install them yourself') +
'\n' +
pc.white('by following the documentation at https://cosmo-docs.wundergraph.com') +
'\n',
);

// Ask user for confirmation to install tools
const installMessage = existsSync(TOOLS_DIR)
? 'Version changes detected. Install required toolchain?'
: 'Install required toolchain?';

const response = await prompts({
type: 'confirm',
name: 'installTools',
message: installMessage,
});

if (!response.installTools) {
console.log(pc.yellow('Tools installation skipped. Build may fail.'));
return false;
if (!response.installTools) {
console.log(pc.yellow('Tools installation skipped. Build may fail.'));
return false;
}
}

try {
Expand Down
16 changes: 7 additions & 9 deletions demo/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
SHELL := bash
wgc_router = pnpx tsx --env-file ../cli/.env ../cli/src/index.ts router
wgc_router = pnpm dlx tsx --env-file ../cli/.env ../cli/src/index.ts router
wgc_router_ci = pnpm dlx tsx ../cli/src/index.ts router

generate:
go generate ./...
Expand All @@ -20,14 +21,11 @@ plugin-generate:
$(wgc_router) plugin build ./pkg/subgraphs/projects --generate-only --go-module-path github.com/wundergraph/cosmo/demo/pkg/subgraphs/projects
$(wgc_router) plugin build ./pkg/subgraphs/courses --generate-only

plugin-build-bun-binary:
cd pkg/subgraphs/courses/ && \
bun install && bun build src/plugin.ts --compile --outfile bin/$(shell go env GOOS)_$(shell go env GOARCH) && \
mkdir -p bin/grpc-health-check && \
cp -r node_modules/grpc-health-check/proto bin/grpc-health-check
plugin-build-ci-bun-binary:
$(wgc_router_ci) plugin build ./pkg/subgraphs/courses --yes

plugin-build-go-binary:
cd pkg/subgraphs/projects/ && go build -o ./bin/$(shell go env GOOS)_$(shell go env GOARCH) ./src
plugin-build-ci-go-binary:
$(wgc_router_ci) plugin build ./pkg/subgraphs/projects --yes

plugin-compose:
$(wgc_router) compose -i ./graph-with-plugin.yaml -o ./configWithPlugins.json
Expand All @@ -39,7 +37,7 @@ plugin-build-integration: plugin-build plugin-compose
cp -a pkg/subgraphs/courses ../router/plugins/
mv configWithPlugins.json ../router-tests/testenv/testdata/configWithPlugins.json

plugin-build-ci: plugin-build-go-binary plugin-build-bun-binary
plugin-build-ci: plugin-build-ci-go-binary plugin-build-ci-bun-binary
rm -rf ../router/plugins/*
mkdir -p ../router/plugins/projects/bin
mkdir -p ../router/plugins/courses/bin
Expand Down
16 changes: 0 additions & 16 deletions demo/pkg/subgraphs/courses/generated/mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,6 @@
}
],
"entityMappings": [
{
"typeName": "Course",
"kind": "entity",
"key": "id",
"rpc": "LookupCourseById",
"request": "LookupCourseByIdRequest",
"response": "LookupCourseByIdResponse"
},
{
"typeName": "Lesson",
"kind": "entity",
"key": "id",
"rpc": "LookupLessonById",
"request": "LookupLessonByIdRequest",
"response": "LookupLessonByIdResponse"
},
{
"typeName": "Employee",
"kind": "entity",
Expand Down
82 changes: 5 additions & 77 deletions demo/pkg/subgraphs/courses/generated/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ import "google/protobuf/wrappers.proto";

// Service definition for CoursesService
service CoursesService {
// Lookup Course entity by id
rpc LookupCourseById(LookupCourseByIdRequest) returns (LookupCourseByIdResponse) {}
// Lookup Employee entity by id
rpc LookupEmployeeById(LookupEmployeeByIdRequest) returns (LookupEmployeeByIdResponse) {}
// Lookup Lesson entity by id
rpc LookupLessonById(LookupLessonByIdRequest) returns (LookupLessonByIdResponse) {}
rpc MutationAddCourse(MutationAddCourseRequest) returns (MutationAddCourseResponse) {}
rpc MutationAddLesson(MutationAddLessonRequest) returns (MutationAddLessonResponse) {}
rpc QueryCourse(QueryCourseRequest) returns (QueryCourseResponse) {}
Expand All @@ -20,74 +16,6 @@ service CoursesService {
rpc QueryThrowErrorCourses(QueryThrowErrorCoursesRequest) returns (QueryThrowErrorCoursesResponse) {}
}

// Key message for Course entity lookup
message LookupCourseByIdRequestKey {
// Key field for Course entity lookup.
string id = 1;
}

// Request message for Course entity lookup.
message LookupCourseByIdRequest {
/*
* List of keys to look up Course entities.
* Order matters - each key maps to one entity in LookupCourseByIdResponse.
*/
repeated LookupCourseByIdRequestKey keys = 1;
}

// Response message for Course entity lookup.
message LookupCourseByIdResponse {
/*
* List of Course entities in the same order as the keys in LookupCourseByIdRequest.
* Always return the same number of entities as keys. Use null for entities that cannot be found.
*
* Example:
* LookupUserByIdRequest:
* keys:
* - id: 1
* - id: 2
* LookupUserByIdResponse:
* result:
* - id: 1 # User with id 1 found
* - null # User with id 2 not found
*/
repeated Course result = 1;
}

// Key message for Lesson entity lookup
message LookupLessonByIdRequestKey {
// Key field for Lesson entity lookup.
string id = 1;
}

// Request message for Lesson entity lookup.
message LookupLessonByIdRequest {
/*
* List of keys to look up Lesson entities.
* Order matters - each key maps to one entity in LookupLessonByIdResponse.
*/
repeated LookupLessonByIdRequestKey keys = 1;
}

// Response message for Lesson entity lookup.
message LookupLessonByIdResponse {
/*
* List of Lesson entities in the same order as the keys in LookupLessonByIdRequest.
* Always return the same number of entities as keys. Use null for entities that cannot be found.
*
* Example:
* LookupUserByIdRequest:
* keys:
* - id: 1
* - id: 2
* LookupUserByIdResponse:
* result:
* - id: 1 # User with id 1 found
* - null # User with id 2 not found
*/
repeated Lesson result = 1;
}

// Key message for Employee entity lookup
message LookupEmployeeByIdRequestKey {
// Key field for Employee entity lookup.
Expand Down Expand Up @@ -179,6 +107,11 @@ message MutationAddLessonResponse {
Lesson add_lesson = 1;
}

message Employee {
int32 id = 1;
repeated Course taught_courses = 2;
}

message Course {
string id = 1;
string title = 2;
Expand All @@ -194,9 +127,4 @@ message Lesson {
google.protobuf.StringValue description = 4;
int32 order = 5;
Course course = 6;
}

message Employee {
int32 id = 1;
repeated Course taught_courses = 2;
}
Loading
Loading