Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ services:
- PYTHON_VERSION=${PYTHON_VERSION}
command: tail -f /dev/null
volumes: [./:/app]
# ports:
# - "5009:5009" # So we can debug the OpenAPI Generator process
ports:
- "5009:5009" # So we can debug the OpenAPI Generator process

ruby:
container_name: apic_ruby
Expand Down
5 changes: 4 additions & 1 deletion scripts/buildLanguages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ async function buildLanguage(language: Language, gens: Generator[], buildType: B
case 'kotlin':
// the playground specify search but it will still build everything
const isTestClass = buildType === 'guides' || buildType === 'snippets';
await run(`./gradle/gradlew -p ${cwd} ${isTestClass ? 'testClasses' : 'assemble'} ${language == 'kotlin' ? '-Pclient=Search' : ''}`, { language });
await run(
`./gradle/gradlew -p ${cwd} ${isTestClass ? 'testClasses' : 'assemble'} ${language == 'kotlin' ? '-Pclient=Search' : ''}`,
{ language },
);
break;
case 'php':
// await runComposerInstall();
Expand Down
54 changes: 30 additions & 24 deletions scripts/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Argument, program } from 'commander';
import { Argument, Option, program } from 'commander';
import semver from 'semver';

import { buildLanguages } from '../buildLanguages.ts';
Expand Down Expand Up @@ -29,10 +29,11 @@ const args = {
};

const flags = {
verbose: {
flag: '-v, --verbose',
description: 'make the generation verbose',
},
verbose: new Option('-v, --verbose', 'make the generation verbose'),
debugger: new Option(
'-d, --debugger',
'runs the generator in debug mode, it will wait for a Java debugger to be attached',
),
};

program.name('cli');
Expand All @@ -49,16 +50,17 @@ program
.description('Generate a specified client')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.action(async (langArg: LangArg, clientArg: string[], { verbose }) => {
.addOption(flags.verbose)
.addOption(flags.debugger)
.action(async (langArg: LangArg, clientArg: string[], { verbose, debugger: withDebugger }) => {
const { language, client, clientList } = transformSelection({
langArg,
clientArg,
});

setVerbose(Boolean(verbose));

await generate(generatorList({ language, client, clientList }));
await generate(generatorList({ language, client, clientList }), Boolean(withDebugger));
});

const buildCommand = program.command('build').description('Build the clients or specs');
Expand All @@ -68,7 +70,7 @@ buildCommand
.description('Build a specified client')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.action(async (langArg: LangArg, clientArg: string[], { verbose }) => {
const { language, client, clientList } = transformSelection({
langArg,
Expand All @@ -85,7 +87,7 @@ buildCommand
.description('Build a specified playground')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.action(async (langArg: LangArg, clientArg: string[], { verbose }) => {
const { language, client, clientList } = transformSelection({
langArg,
Expand All @@ -102,7 +104,7 @@ buildCommand
.description('Build a specified snippets')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.action(async (langArg: LangArg, clientArg: string[], { verbose }) => {
const { language, client, clientList } = transformSelection({
langArg,
Expand All @@ -119,7 +121,7 @@ buildCommand
.description('Build a specified guides')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.action(async (langArg: LangArg, clientArg: string[], { verbose }) => {
const { language, client, clientList } = transformSelection({
langArg,
Expand All @@ -135,7 +137,7 @@ buildCommand
.command('specs')
.description('Build a specified spec')
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.option('-s, --skip-cache', 'skip cache checking to force building specs')
.option('-j, --json', 'outputs the spec in JSON instead of yml')
.option('-d, --docs', 'generates the doc specs with the code snippets')
Expand Down Expand Up @@ -172,25 +174,26 @@ ctsCommand
.description('Generate the CTS tests')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.addOption(flags.debugger)
.option('--lv, --language-version <version>', 'the version of the language to use')
.action(async (langArg: LangArg, clientArg: string[], { verbose, languageVersion }) => {
.action(async (langArg: LangArg, clientArg: string[], { verbose, debugger: withDebugger, languageVersion }) => {
const { language, client, clientList } = transformSelection({
langArg,
clientArg,
});

setVerbose(Boolean(verbose));

await ctsGenerateMany(generatorList({ language, client, clientList }), languageVersion);
await ctsGenerateMany(generatorList({ language, client, clientList }), withDebugger, languageVersion);
});

ctsCommand
.command('run')
.description('Run the tests for the CTS')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.option('-e, --no-e2e', 'skip the e2e tests, that requires internet connection')
.option('-c, --no-client', 'skip the client tests')
.option('-r, --no-requests', 'skip the requests tests')
Expand Down Expand Up @@ -250,7 +253,7 @@ program
.description('Format the specified folder for a specific language')
.addArgument(args.requiredLanguage)
.argument('folder', 'The folder to format')
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.action(async (language: string, folder: string, { verbose }) => {
setVerbose(Boolean(verbose));

Expand All @@ -262,25 +265,27 @@ program
.description('Generate the snippets')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.action(async (langArg: LangArg, clientArg: string[], { verbose }) => {
.addOption(flags.verbose)
.addOption(flags.debugger)
.action(async (langArg: LangArg, clientArg: string[], { verbose, debugger: withDebugger }) => {
const { language, client, clientList } = transformSelection({
langArg,
clientArg,
});

setVerbose(Boolean(verbose));

await docsGenerateMany(generatorList({ language, client, clientList }), 'snippets');
await docsGenerateMany(generatorList({ language, client, clientList }), 'snippets', Boolean(withDebugger));
});

program
.command('guides')
.description('Generate the guides')
.addArgument(args.language)
.addArgument(args.clients)
.option(flags.verbose.flag, flags.verbose.description)
.action(async (langArg: LangArg, clientArg: string[], { verbose }) => {
.addOption(flags.verbose)
.addOption(flags.debugger)
.action(async (langArg: LangArg, clientArg: string[], { verbose, debugger: withDebugger }) => {
const { language, client, clientList } = transformSelection({
langArg,
clientArg,
Expand All @@ -293,13 +298,14 @@ program
existsSync(toAbsolutePath(`templates/${gen.language}/guides/${gen.client}`)),
),
'guides',
Boolean(withDebugger),
);
});

program
.command('release')
.description('Releases the client')
.option(flags.verbose.flag, flags.verbose.description)
.addOption(flags.verbose)
.option<semver.ReleaseType>(
'--rt --release-type <type>',
'triggers a release for the given language list with the given releaseType',
Expand Down
42 changes: 35 additions & 7 deletions scripts/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fsp from 'fs/promises';
import path from 'path';

import { Octokit } from '@octokit/rest';
import chalk from 'chalk';
import type { ExecaError } from 'execa';
import { execa, execaCommand } from 'execa';
import { remove } from 'fs-extra';
Expand Down Expand Up @@ -270,13 +271,40 @@ export function isVerbose(): boolean {
return verbose;
}

export async function callGenerator(gen: Generator): Promise<void> {
await run(
// Use the following line if you want to be able to attach a debugger to the generators
// `JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=\*:5009" yarn openapi-generator-cli --custom-generator=generators/build/libs/algolia-java-openapi-generator-1.0.0.jar generate --generator-key ${gen.key}`,
`yarn openapi-generator-cli --custom-generator=generators/build/libs/algolia-java-openapi-generator-1.0.0.jar generate --generator-key ${gen.key}`,
{ language: 'java' },
);
export async function callGenerator(gen: Generator, withDebugger: boolean): Promise<void> {
const cmd = `yarn openapi-generator-cli --custom-generator=generators/build/libs/algolia-java-openapi-generator-1.0.0.jar generate --generator-key ${gen.key}`;
if (!withDebugger) {
await run(cmd, { language: 'java' });
return;
}

console.log(chalk.yellow('Running the generator in debug mode, waiting for debugger to be attached on port 5009'));

/*
example .vscode/launch.json config to attach the debugger
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "APIC Generator",
"request": "attach",
"hostName": "localhost",
"port": "5009"
}
]
}
*/

const verbose = isVerbose();
setVerbose(false); // verbose messes up the order of execution

// kill previous debuggers
await run('(killall -9 java && sleep 1) || true', { language: 'java' });
setVerbose(verbose);
await run(`JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5009" ${cmd}`, {
language: 'java',
});
}

export function isWSL(): boolean {
Expand Down
8 changes: 6 additions & 2 deletions scripts/cts/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import { getTestOutputFolder } from '../config.ts';
import { formatter } from '../formatter.ts';
import type { Generator } from '../types.ts';

export async function ctsGenerateMany(generators: Generator[], languageVersion = ''): Promise<void> {
export async function ctsGenerateMany(
generators: Generator[],
withDebugger: boolean,
languageVersion = '',
): Promise<void> {
await setupAndGen(
generators,
'tests',
async (gen) => {
if (getTestOutputFolder(gen.language)) {
await callGenerator(gen);
await callGenerator(gen, withDebugger);
}
},
{
Expand Down
2 changes: 2 additions & 0 deletions scripts/docker/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ SHELL ["/bin/bash", "--login", "-c"]
# Global dependencies
RUN apt-get update \
&& apt-get install -y --no-install-recommends git curl zip unzip libexpat1-dev libicu76 \
# for killall and ps
&& apt-get install -y procps \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

Expand Down
8 changes: 6 additions & 2 deletions scripts/docs/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { getTestOutputFolder } from '../config.ts';
import { formatter } from '../formatter.ts';
import type { Generator } from '../types.ts';

export async function docsGenerateMany(generators: Generator[], scope: 'guides' | 'snippets'): Promise<void> {
export async function docsGenerateMany(
generators: Generator[],
scope: 'guides' | 'snippets',
withDebugger: boolean,
): Promise<void> {
await setupAndGen(generators, scope, async (gen) => {
if (getTestOutputFolder(gen.language)) {
await callGenerator(gen);
await callGenerator(gen, withDebugger);
}
});

Expand Down
4 changes: 2 additions & 2 deletions scripts/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ async function preGen(gen: Generator): Promise<void> {
await removeExistingCodegen(gen);
}

export async function generate(generators: Generator[]): Promise<void> {
export async function generate(generators: Generator[], withDebugger: boolean): Promise<void> {
await setupAndGen(generators, 'client', async (gen) => {
await preGen(gen);
await callGenerator(gen);
await callGenerator(gen, withDebugger);
});

for (const lang of new Set(generators.map((gen) => gen.language))) {
Expand Down
33 changes: 30 additions & 3 deletions website/docs/CLI/cts-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ apic cts generate <language | all> <client... | all>

### Available options

| Option | Command | Description |
| ------- | :------------ | :------------------------------------------------------------ |
| verbose | -v, --verbose | Make the process verbose, display logs from third party tools |
| Option | Command | Description |
|----------|:---------------|:----------------------------------------------------------------------------------|
| verbose | -v, --verbose | Make the process verbose, display logs from third party tools |
| debugger | -d, --debugger | runs the generator in debug mode, it will wait for a Java debugger to be attached |

## Generate

Expand All @@ -50,6 +51,32 @@ apic cts generate java search
apic cts generate php insights recommend search
```

### Attach a debugger to the generator

Using VS code extension [Debugger For Java](https://code.visualstudio.com/docs/java/java-debugging), you can attach breakpoint to the generator.
Example config for VS Code in `.vscode/launch.json`:

```json
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "APIC Generator",
"request": "attach",
"hostName": "localhost",
"port": "5009"
}
]
}
```

```bash
apic cts generate java search -d
```

Then you can connect you favorite Java debugger, either IntelliJ, VS Code, or jdb.

## Run

### Run CTS for all supported languages
Expand Down