Skip to content

Commit

Permalink
feat: debugging support (#446)
Browse files Browse the repository at this point in the history
* feat: debug setup

This installs a couple packages and sets up a logger for usage in normal and GHA environments

* chore: fix imports

* feat: use annotations for warnings

* temp: attempt to surface warning

* revert: skip warn function for now

* chore: clean up logger

* fix: incorrect import pattern

* feat: add debugging statements for top-level + docs

* fix: make fetch debug less noisy

* fix: specify method in fetch debug

* chore: more docs debug statements

* chore: add command/opts debug statements to every command file

* fix: undefined errors

can't wait to use optional chaining lol

* chore: cleanup

* feat: add logging for handleRes

* feat: add logging for `open` command

* feat: `oas` command debug

* feat: docs:edit debug

* feat: version update/delete debug

* feat: validate command debug

* feat: lots of debugging for openapi command

* refactor: prefix GHA logs, cleanup

* feat: surface errors in GHA action annotations

* chore: temporarily create failing example, see if it works

* refactor: is this any cleaner?

* revert: restore normal workflow states

* Update bin/rdme

Co-authored-by: Jon Ursenbach <[email protected]>

* chore: PR feedback

Use ci-info package here instead!

Feedback: #446 (comment)
Co-Authored-By: Jon Ursenbach <[email protected]>

* Revert "chore: PR feedback"

This reverts commit 1d2fad0.

Co-authored-by: Jon Ursenbach <[email protected]>
Co-authored-by: Jon Ursenbach <[email protected]>
  • Loading branch information
3 people authored Feb 24, 2022
1 parent bf20f2d commit bdb3c6c
Show file tree
Hide file tree
Showing 21 changed files with 200 additions and 14 deletions.
12 changes: 12 additions & 0 deletions bin/rdme
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#! /usr/bin/env node
const chalk = require('chalk');
const core = require('@actions/core');

const updateNotifier = require('update-notifier');
const pkg = require('../package.json');

const isGHA = require('../src/lib/isGitHub');

updateNotifier({ pkg }).notify();

require('../src')(process.argv.slice(2))
Expand All @@ -21,6 +24,15 @@ require('../src')(process.argv.slice(2))
message = err.message;
}

/**
* If we're in a GitHub Actions environment, log errors with that formatting instead.
* @link: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message
* @link: https://github.com/actions/toolkit/tree/main/packages/core#annotations
*/
if (isGHA) {
return core.setFailed(message);
}

// eslint-disable-next-line no-console
console.error(chalk.red(`\n${message}\n`));
return process.exit(1);
Expand Down
55 changes: 49 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@
"url": "https://github.com/readmeio/rdme/issues"
},
"dependencies": {
"@actions/core": "^1.6.0",
"chalk": "^4.1.2",
"cli-table": "^0.3.1",
"command-line-args": "^5.2.0",
"command-line-usage": "^6.0.2",
"config": "^3.1.0",
"configstore": "^5.0.0",
"debug": "^4.3.3",
"editor": "^1.0.0",
"enquirer": "^2.3.0",
"form-data": "^4.0.0",
Expand Down
13 changes: 13 additions & 0 deletions src/cmds/docs/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const APIError = require('../../lib/apiError');
const { getProjectVersion } = require('../../lib/versionSelect');
const fetch = require('../../lib/fetch');
const { cleanHeaders, handleRes } = require('../../lib/fetch');
const { debug } = require('../../lib/logger');

const writeFile = promisify(fs.writeFile);
const readFile = promisify(fs.readFile);
Expand Down Expand Up @@ -42,6 +43,9 @@ module.exports = class EditDocsCommand {
async run(opts) {
const { slug, key, version } = opts;

debug(`command: ${this.command}`);
debug(`opts: ${JSON.stringify(opts)}`);

if (!key) {
return Promise.reject(new Error('No project API key provided. Please use `--key`.'));
}
Expand All @@ -54,6 +58,8 @@ module.exports = class EditDocsCommand {
return Promise.reject(e);
});

debug(`selectedVersion: ${selectedVersion}`);

const filename = `${slug}.md`;

const existingDoc = await fetch(`${config.get('host')}/api/v1/docs/${slug}`, {
Expand All @@ -66,11 +72,16 @@ module.exports = class EditDocsCommand {

await writeFile(filename, existingDoc.body);

debug(`wrote to local file: ${filename}, opening editor`);

return new Promise((resolve, reject) => {
(opts.mockEditor || editor)(filename, async code => {
debug(`editor closed with code ${code}`);
if (code !== 0) return reject(new Error('Non zero exit code from $EDITOR'));
const updatedDoc = await readFile(filename, 'utf8');

debug(`read edited contents of ${filename}, sending to ReadMe`);

return fetch(`${config.get('host')}/api/v1/docs/${slug}`, {
method: 'put',
headers: cleanHeaders(key, {
Expand All @@ -85,6 +96,7 @@ module.exports = class EditDocsCommand {
})
.then(res => res.json())
.then(async res => {
debug(`response from PUT request: ${res}`);
// The reason we aren't using our handleRes() function here is
// because we need to use the `reject` function from
// the Promise that's wrapping this function.
Expand All @@ -93,6 +105,7 @@ module.exports = class EditDocsCommand {
}
console.info(`Doc successfully updated. Cleaning up local file.`);
await unlink(filename);
debug('file unlinked');
// Normally we should resolve with a value that is logged to the console,
// but since we need to wait for the temporary file to be removed,
// it's okay to resolve the promise with no value.
Expand Down
16 changes: 16 additions & 0 deletions src/cmds/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const { promisify } = require('util');
const { getProjectVersion } = require('../../lib/versionSelect');
const fetch = require('../../lib/fetch');
const { cleanHeaders, handleRes } = require('../../lib/fetch');
const { debug } = require('../../lib/logger');

const readFile = promisify(fs.readFile);

Expand Down Expand Up @@ -42,6 +43,9 @@ module.exports = class DocsCommand {
async run(opts) {
const { folder, key, version } = opts;

debug(`command: ${this.command}`);
debug(`opts: ${JSON.stringify(opts)}`);

if (!key) {
return Promise.reject(new Error('No project API key provided. Please use `--key`.'));
}
Expand All @@ -55,6 +59,8 @@ module.exports = class DocsCommand {
// Ideally we should ignore this parameter entirely if the category is included.
const selectedVersion = await getProjectVersion(version, key, false);

debug(`selectedVersion: ${selectedVersion}`);

// Find the files to sync
const readdirRecursive = folderToSearch => {
const filesInFolder = fs.readdirSync(folderToSearch, { withFileTypes: true });
Expand All @@ -70,6 +76,9 @@ module.exports = class DocsCommand {

// Strip out non-markdown files
const files = readdirRecursive(folder).filter(file => file.endsWith('.md') || file.endsWith('.markdown'));

debug(`number of files: ${files.length}`);

if (!files.length) {
return Promise.reject(new Error(`We were unable to locate Markdown files in ${folder}.`));
}
Expand Down Expand Up @@ -115,13 +124,17 @@ module.exports = class DocsCommand {

const updatedDocs = await Promise.all(
files.map(async filename => {
debug(`reading file ${filename}`);
const file = await readFile(filename, 'utf8');
const matter = frontMatter(file);
debug(`frontmatter for ${filename}: ${JSON.stringify(matter)}`);

// Stripping the subdirectories and markdown extension from the filename and lowercasing to get the default slug.
const slug = matter.data.slug || path.basename(filename).replace(path.extname(filename), '').toLowerCase();
const hash = crypto.createHash('sha1').update(file).digest('hex');

debug(`fetching data for ${slug}`);

return fetch(`${config.get('host')}/api/v1/docs/${slug}`, {
method: 'get',
headers: cleanHeaders(key, {
Expand All @@ -131,9 +144,12 @@ module.exports = class DocsCommand {
})
.then(res => res.json())
.then(res => {
debug(`GET /docs/:slug API response for ${slug}: ${JSON.stringify(res)}`);
if (res.error) {
debug(`error retrieving data for ${slug}, creating doc`);
return createDoc(slug, matter, hash, res);
}
debug(`data received for ${slug}, updating doc`);
return updateDoc(slug, matter, hash, res);
})
.catch(err => {
Expand Down
4 changes: 4 additions & 0 deletions src/cmds/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const read = promisify(require('read'));
const configStore = require('../lib/configstore');
const fetch = require('../lib/fetch');
const { handleRes } = require('../lib/fetch');
const { debug } = require('../lib/logger');

const testing = process.env.NODE_ENV === 'testing';

Expand Down Expand Up @@ -34,6 +35,9 @@ module.exports = class LoginCommand {
async run(opts) {
let { email, password, project, token } = opts;

debug(`command: ${this.command}`);
debug(`opts: ${JSON.stringify(opts)}`);

/* istanbul ignore next */
async function getCredentials() {
return {
Expand Down
3 changes: 3 additions & 0 deletions src/cmds/logout.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const config = require('config');
const configStore = require('../lib/configstore');
const { debug } = require('../lib/logger');

module.exports = class LogoutCommand {
constructor() {
Expand All @@ -13,6 +14,8 @@ module.exports = class LogoutCommand {
}

async run() {
debug(`command: ${this.command}`);

if (configStore.has('email') && configStore.has('project')) {
configStore.clear();
}
Expand Down
5 changes: 5 additions & 0 deletions src/cmds/oas.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { spawn } = require('child_process');
const path = require('path');
const { debug } = require('../lib/logger');

module.exports = class OASCommand {
constructor() {
Expand All @@ -13,12 +14,16 @@ module.exports = class OASCommand {
}

async run() {
debug(`command: ${this.command}`);
debug('spawning new process with `oas`');

const cp = spawn(path.join(__dirname, '..', '..', 'node_modules', '.bin', 'oas'), process.argv.slice(3), {
stdio: 'inherit',
});

return new Promise((resolve, reject) => {
cp.on('close', code => {
debug(`closing \`oas\` process with code: ${code}`);
if (code && code > 0) return reject();

return resolve();
Expand Down
6 changes: 6 additions & 0 deletions src/cmds/open.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const chalk = require('chalk');
const config = require('config');
const open = require('open');
const configStore = require('../lib/configstore');
const { debug } = require('../lib/logger');

module.exports = class OpenCommand {
constructor() {
Expand All @@ -15,7 +16,12 @@ module.exports = class OpenCommand {
}

async run(opts) {
debug(`command: ${this.command}`);
debug(`opts: ${JSON.stringify(opts)}`);

const project = configStore.get('project');
debug(`project: ${project}`);

if (!project) {
return Promise.reject(new Error(`Please login using \`${config.get('cli')} login\`.`));
}
Expand Down
Loading

0 comments on commit bdb3c6c

Please sign in to comment.