Skip to content

Commit

Permalink
feat(openapi): add --dryRun option (#612)
Browse files Browse the repository at this point in the history
* feat(openapi): add --dryRun option

* feat(openapi): add dryRun notification in createSpec()

* feat(openapi): add dryRun notification in updateSpec()

* test(openapi): add tests for dry run upload

* test(openapi): remove unused nock in create test

* test(openapi): add test for update dry run

* test(--help): update snapshot to include `dryRun` info

* feat(openapi): update dry run copy

* test(openapi): update dry run test snapshot

* test(openapi): update dry run test for updated copy

* feat(openapi): update ReadMe with new dryRun option for openapi.create and openapi.update

* feat(openapi): update readme to add dry run info
  • Loading branch information
darrenyong authored Sep 22, 2022
1 parent 2880fa3 commit 8cb48e8
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
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

0 comments on commit 8cb48e8

Please sign in to comment.