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(openapi): add --dryRun option #612

Merged
merged 13 commits into from
Sep 22, 2022
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ If you want to bypass the prompt to create or update an API definition, you can
rdme openapi [path-to-file.json] --version={project-version} --create
```

This command also has a dry run mode, which can be useful for initial setup and debugging. You can perform a dry run by supplying the `--dryRun` flag.

#### Editing (Re-Syncing) an Existing API Definition

This will edit (re-sync) an existing API definition (identified by `--id`) within your ReadMe project. **This is the recommended approach for usage in CI environments.**
Expand Down Expand Up @@ -150,6 +152,8 @@ You can add `--update` to the command so if there's only one API definition for
rdme openapi [path-to-file.json] --version={project-version} --update
```

This command also has a dry run mode, which can be useful for initial setup and debugging. You can perform a dry run by supplying the `--dryRun` flag.

#### Omitting the File Path

If you run `rdme` within a directory that contains your OpenAPI or Swagger definition, you can omit the file path. `rdme` will then look for JSON or YAML files (including in sub-directories) that contain a top-level [`openapi`](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#fixed-fields) or [`swagger`](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#fixed-fields) property.
Expand Down
6 changes: 6 additions & 0 deletions __tests__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Options
--create Bypasses the create/update prompt and creates a new API definition.
--update Automatically update an existing API definition in ReadMe if it's the
only one associated with the current version.
--dryRun Runs the command without creating/updating any API Definitions in
ReadMe. Useful for debugging.
-h, --help Display this usage guide

Related commands
Expand Down Expand Up @@ -57,6 +59,8 @@ Options
--create Bypasses the create/update prompt and creates a new API definition.
--update Automatically update an existing API definition in ReadMe if it's the
only one associated with the current version.
--dryRun Runs the command without creating/updating any API Definitions in
ReadMe. Useful for debugging.
-h, --help Display this usage guide

Related commands
Expand Down Expand Up @@ -90,6 +94,8 @@ Options
--create Bypasses the create/update prompt and creates a new API definition.
--update Automatically update an existing API definition in ReadMe if it's the
only one associated with the current version.
--dryRun Runs the command without creating/updating any API Definitions in
ReadMe. Useful for debugging.
-h, --help Display this usage guide

Related commands
Expand Down
69 changes: 69 additions & 0 deletions __tests__/cmds/openapi/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,41 @@ describe('rdme openapi', () => {
return mock.done();
});

it('should return spec create info for dry run', async () => {
const registryUUID = getRandomRegistryId();

const mock = getAPIMock()
.get(`/api/v1/version/${version}`)
.basicAuth({ user: key })
.reply(200, { version })
.post('/api/v1/api-registry', body => body.match('form-data; name="spec"'))
.reply(201, { registryUUID, spec: { openapi: '3.0.0' } });

const mockWithHeader = getAPIMockWithVersionHeader(version)
.get('/api/v1/api-specification')
.basicAuth({ user: key })
.reply(200, []);

await expect(
openapi.run({
key,
version,
dryRun: true,
workingDirectory: './__tests__/__fixtures__/relative-ref-oas',
})
).resolves.toMatch(
'🎭 dry run! The API Definition located at petstore.json will be created for this project version: 1.0.0'
);

const output = getCommandOutput();
expect(output).toMatch(
chalk.yellow('🎭 dry run option detected! No API definitions will be created or updated in ReadMe.')
);

mockWithHeader.done();
return mock.done();
});

describe('CI spec selection', () => {
beforeEach(() => {
process.env.TEST_CI = 'true';
Expand Down Expand Up @@ -488,6 +523,40 @@ describe('rdme openapi', () => {
return mock.done();
});

it('should return spec update info for dry run', async () => {
prompts.inject(['update', 'spec2']);
const registryUUID = getRandomRegistryId();

const mock = getAPIMock()
.get(`/api/v1/version/${version}`)
.basicAuth({ user: key })
.reply(200, { version })
.post('/api/v1/api-registry', body => body.match('form-data; name="spec"'))
.reply(201, { registryUUID, spec: { openapi: '3.0.0' } });

const mockWithHeader = getAPIMockWithVersionHeader(version)
.get('/api/v1/api-specification')
.basicAuth({ user: key })
.reply(200, [
{ _id: 'spec1', title: 'spec1_title' },
{ _id: 'spec2', title: 'spec2_title' },
]);

const spec = './__tests__/__fixtures__/ref-oas/petstore.json';

await expect(
openapi.run({
key,
version,
spec,
dryRun: true,
})
).resolves.toMatch(`dry run! The API Definition located at ${spec} will update this API Definition ID: spec2`);

mockWithHeader.done();
return mock.done();
});

describe('--update', () => {
it("should update a spec file without prompts if providing `update` and it's the one spec available", async () => {
const registryUUID = getRandomRegistryId();
Expand Down
20 changes: 19 additions & 1 deletion src/cmds/openapi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type Options = {
useSpecVersion?: boolean;
workingDirectory?: string;
update?: boolean;
dryRun?: boolean;
};

export default class OpenAPICommand extends Command {
Expand Down Expand Up @@ -81,13 +82,18 @@ export default class OpenAPICommand extends Command {
description:
"Automatically update an existing API definition in ReadMe if it's the only one associated with the current version.",
},
{
name: 'dryRun',
type: Boolean,
description: 'Runs the command without creating/updating any API Definitions in ReadMe. Useful for debugging.',
},
];
}

async run(opts: CommandOptions<Options>) {
super.run(opts);

const { key, id, spec, create, raw, useSpecVersion, version, workingDirectory, update } = opts;
const { dryRun, key, id, spec, create, raw, useSpecVersion, version, workingDirectory, update } = opts;

let selectedVersion = version;
let isUpdate: boolean;
Expand All @@ -98,6 +104,10 @@ export default class OpenAPICommand extends Command {
*/
const ignoredGHAParameters: Options = { version: undefined, update: undefined };

if (dryRun) {
Command.warn('🎭 dry run option detected! No API definitions will be created or updated in ReadMe.');
}

if (create && update) {
throw new Error(
'The `--create` and `--update` options cannot be used simultaneously. Please use one or the other!'
Expand Down Expand Up @@ -224,6 +234,10 @@ export default class OpenAPICommand extends Command {
};

function createSpec() {
if (dryRun) {
return `🎭 dry run! The API Definition located at ${specPath} will be created for this project version: ${selectedVersion}`;
}

options.method = 'post';
spinner.start('Creating your API docs in ReadMe...');
return fetch(`${config.get('host')}/api/v1/api-specification`, options).then(res => {
Expand All @@ -237,6 +251,10 @@ export default class OpenAPICommand extends Command {
}

function updateSpec(specId: string) {
if (dryRun) {
return `🎭 dry run! The API Definition located at ${specPath} will update this API Definition ID: ${specId}`;
}

isUpdate = true;
options.method = 'put';
spinner.start('Updating your API docs in ReadMe...');
Expand Down