Skip to content
This repository has been archived by the owner on Jun 13, 2022. It is now read-only.

Commit

Permalink
feat(cli): create the 'update-incident' command
Browse files Browse the repository at this point in the history
  • Loading branch information
juliomrqz committed Mar 12, 2019
1 parent 8aef1f9 commit a22d72a
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 40 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"demo:generate": "cross-env STATUSFY_LERNA=true yarn workspace statusfy-demo generate",
"demo:start": "cross-env STATUSFY_LERNA=true yarn workspace statusfy-demo start",
"demo:delete-incident": "cross-env STATUSFY_LERNA=true yarn workspace statusfy-demo delete-incident",
"demo:update-incident": "cross-env STATUSFY_LERNA=true yarn workspace statusfy-demo update-incident",
"website:dev": "yarn workspace statusfy-website dev",
"website:generate": "yarn workspace statusfy-website generate",
"update-changelog": "conventional-changelog -p angular -r 2 -i CHANGELOG.md -s"
Expand Down
21 changes: 19 additions & 2 deletions packages/@statusfy/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ if (!semver.satisfies(process.version, requiredVersion)) {
process.exit(1)
}

const { init, dev, build, generate, start, newIncident, deleteIncident } = require('@statusfy/core/lib')
const {
init,
dev,
build,
generate,
start,
newIncident,
deleteIncident,
updateIncident
} = require('@statusfy/core/lib')
const sourceDir = path.resolve('.')

program
Expand Down Expand Up @@ -100,11 +109,19 @@ program

program
.command('delete-incident')
.description(`Creates a new incident after answering a few questions.`)
.description(`Delete an incident including translations.`)
.action(() => {
wrapCommand(deleteIncident)(sourceDir, { })
})


program
.command('update-incident')
.description(`Update an incident including translations.`)
.action(() => {
wrapCommand(updateIncident)(sourceDir, {})
})

// output help information on unknown commands
program
.arguments('<command>')
Expand Down
1 change: 1 addition & 0 deletions packages/@statusfy/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ exports.chalk = require('chalk')
exports.fse = require('fs-extra')
exports.hash = require('hash-sum')
exports.path = require('upath')
exports.LRU = require('lru-cache')
1 change: 1 addition & 0 deletions packages/@statusfy/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"gray-matter": "^4.0.1",
"hash-sum": "^1.0.2",
"lodash.isstring": "^4.0.1",
"lru-cache": "5.1.1",
"moment": "^2.22.2",
"postcss-combine-duplicated-selectors": "^7.0.0",
"postcss-import": "^12.0.0",
Expand Down
3 changes: 1 addition & 2 deletions packages/@statusfy/core/lib/content/database.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
const { readdir, stat, readFile } = require("fs");
const { promisify } = require("util");
const LRU = require("lru-cache");
const spawn = require("cross-spawn");
const drop = require("lodash.drop");
const sortBy = require("lodash.sortby");
const Moment = require("moment");
const MomentRange = require("moment-range");

const createMarkdown = require("@statusfy/markdown");
const { logger, hash, path, fse } = require("@statusfy/common");
const { logger, hash, path, fse, LRU } = require("@statusfy/common");

const moment = MomentRange.extendMoment(Moment);
const readdirP = promisify(readdir);
Expand Down
26 changes: 4 additions & 22 deletions packages/@statusfy/core/lib/delete-incident.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,16 @@
const inquirer = require("inquirer");

const { logger, fse, grayMatter, chalk, path } = require("@statusfy/common");
const { logger, fse, path } = require("@statusfy/common");
const loadConfig = require("./config/load");
const { getIncidentsFromProject } = require("./utils/functions");

/* eslint-disable require-await */
module.exports = async function deleteIncident(sourceDir, cliOptions = {}) {
process.env.NODE_ENV = "development";

const config = loadConfig(sourceDir).config;
const contentDir = path.join(sourceDir, config.content.dir);
const files = await fse.readdir(contentDir);
const incidentsList = [];

for (let i = 0; i < files.length; i++) {
const f = path.resolve(contentDir, files[i]);
const ext = path.extname(f);
const fileName = path.basename(f);

if (ext === ".md") {
const fileContent = await fse.readFile(f);
const { data } = grayMatter.parse(fileContent);

incidentsList.push(
`${fileName} > ${chalk.yellow(data.title)} (${chalk.green(
data.date.toUTCString()
)})`
);
}
}
const incidentsList = await getIncidentsFromProject(contentDir);

const questions = [
{
Expand All @@ -54,12 +37,11 @@ module.exports = async function deleteIncident(sourceDir, cliOptions = {}) {
const deletedFiles = [];

for (let j = 0; j < locales.length; j++) {
const incidentFileName = incident.split(">")[0].trim();
const locale = locales[j];
const localeIncidentPath = path.join(
contentDir,
config.defaultLocale !== locale ? locale : "",
incidentFileName
incident.name
);
const exists = await fse.pathExists(localeIncidentPath);

Expand Down
1 change: 1 addition & 0 deletions packages/@statusfy/core/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ exports.generate = require("./generate");
exports.start = require("./start");
exports.newIncident = require("./new-incident");
exports.deleteIncident = require("./delete-incident");
exports.updateIncident = require("./update-incident");
exports.Statusfy = require("./statusfy");
3 changes: 2 additions & 1 deletion packages/@statusfy/core/lib/init/template-package.json.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"start": "statusfy start",
"generate": "statusfy generate",
"new-incident": "statusfy new-incident",
"delete-incident": "statusfy delete-incident"
"delete-incident": "statusfy delete-incident",
"update-incident": "statusfy update-incident"
},
"dependencies": {
"statusfy": "^<%= options.statusfyVersion %>"
Expand Down
13 changes: 2 additions & 11 deletions packages/@statusfy/core/lib/new-incident.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,9 @@ const fs = require("fs");
const inquirer = require("inquirer");
const opener = require("opener");

const { logger, fse, grayMatter, slugify, path } = require("@statusfy/common");
const { logger, fse, slugify, path } = require("@statusfy/common");
const loadConfig = require("./config/load");

function generateIncident(data, content, format) {
let matterContent = grayMatter.stringify(content, data, format);

if (["json", "toml"].includes(format)) {
matterContent = matterContent.replace(/^---/, `---${format}`);
}

return matterContent;
}
const { generateIncident } = require("./utils/functions");

/* eslint-disable require-await */
module.exports = async function newIncident(sourceDir, cliOptions = {}) {
Expand Down
155 changes: 155 additions & 0 deletions packages/@statusfy/core/lib/update-incident.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
const inquirer = require("inquirer");

const { logger, fse, grayMatter, LRU, path } = require("@statusfy/common");
const loadConfig = require("./config/load");
const {
getIncidentsFromProject,
generateIncident
} = require("./utils/functions");
const cache = new LRU();

const getIncidentData = async filePath => {
const key = `data:${filePath}`;
let data = cache.get(key);

if (!data) {
const fileContent = await fse.readFile(filePath);
data = grayMatter.parse(fileContent);

cache.set(key, data);
}

return data;
};

/* eslint-disable require-await */
module.exports = async function updateIncident(sourceDir, cliOptions = {}) {
process.env.NODE_ENV = "development";

const config = loadConfig(sourceDir).config;
const contentDir = path.join(sourceDir, config.content.dir);
const incidentsList = await getIncidentsFromProject(contentDir);

const questions = [
{
type: "list",
name: "incident",
message: "What incident do you want to update?",
paginated: true,
choices: incidentsList
},
{
type: "confirm",
name: "resolved",
message: "The incident has been resolved?",
async default(answers) {
const { resolved } = (await getIncidentData(
answers.incident.path
)).data;
return Boolean(resolved);
}
},
{
type: "list",
name: "severity",
message: "What is the severity of the incident?",
choices: [
"under-maintenance",
"degraded-performance",
"partial-outage",
"major-outage"
],
async default(answers) {
const { severity } = (await getIncidentData(
answers.incident.path
)).data;
return severity;
}
},
{
type: "checkbox",
name: "affectedsystems",
message: "What are the affected systems?",
choices: config.content.systems,
validate: value => {
if (value.length > 0) {
return true;
}

return "You must have an affected system!";
},
async default(answers) {
const { affectedsystems } = (await getIncidentData(
answers.incident.path
)).data;
return affectedsystems;
}
},
{
type: "confirm",
name: "confirm",
message: "Are you sure you want to update the incident?",
default: false
}
];

inquirer.prompt(questions).then(async answers => {
const { incident, resolved, severity, affectedsystems, confirm } = answers;

try {
if (confirm) {
const modified = new Date().toISOString();
const locales = config.locales.map(l => l.code);
const updatedFiles = [];

for (let j = 0; j < locales.length; j++) {
const locale = locales[j];
const localeIncidentPath = path.join(
contentDir,
config.defaultLocale !== locale ? locale : "",
incident.name
);
const exists = await fse.pathExists(localeIncidentPath);

if (exists) {
try {
const data = await getIncidentData(localeIncidentPath);
const newMatter = {
...data.data,
modified,
severity,
affectedsystems,
resolved
};

const content = generateIncident(
newMatter,
data.content,
config.content.frontMatterFormat || "yaml"
);

await fse.writeFile(localeIncidentPath, content);

updatedFiles.push(localeIncidentPath);
} catch (error) {
logger.error(error);
}
} else {
logger.warn(`This file couldn't be found:\n${localeIncidentPath}`);
}
}

if (updatedFiles.length > 0) {
const prefix =
updatedFiles.length === 1
? "This file was successfully updated"
: "These files were successfully updated";

logger.success(`${prefix}: \n${updatedFiles.join("\n")}`);
}
}
} catch (error) {
logger.fatal(error);
}
});
};
44 changes: 44 additions & 0 deletions packages/@statusfy/core/lib/utils/functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { fse, grayMatter, chalk, path } = require("@statusfy/common");

const getIncidentsFromProject = async contentDir => {
const files = await fse.readdir(contentDir);
const incidentsList = [];

for (let i = 0; i < files.length; i++) {
const f = path.resolve(contentDir, files[i]);
const ext = path.extname(f);
const fileName = path.basename(f);

if (ext === ".md") {
const fileContent = await fse.readFile(f);
const { data } = grayMatter.parse(fileContent);

incidentsList.push({
value: {
name: fileName,
path: f
},
name: `${fileName} > ${chalk.yellow(data.title)} (${chalk.green(
data.date.toUTCString()
)})`
});
}
}

return incidentsList;
};

const generateIncident = (data, content, format) => {
let matterContent = grayMatter.stringify(content, data, format);

if (["json", "toml"].includes(format)) {
matterContent = matterContent.replace(/^---/, `---${format}`);
}

return matterContent;
};

module.exports = {
getIncidentsFromProject,
generateIncident
};
1 change: 0 additions & 1 deletion packages/@statusfy/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
"lodash.get": "^4.4.2",
"lodash.isstring": "^4.0.1",
"lodash.sortby": "^4.7.0",
"lru-cache": "5.1.1",
"moment": "^2.22.2",
"moment-range": "^4.0.2",
"nodemon": "^1.18.4",
Expand Down
3 changes: 2 additions & 1 deletion packages/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"start": "npm run prepare && statusfy start",
"generate": "npm run prepare && statusfy generate",
"new-incident": "statusfy new-incident",
"delete-incident": "statusfy delete-incident"
"delete-incident": "statusfy delete-incident",
"update-incident": "statusfy update-incident"
},
"author": {
"name": "Bazzite",
Expand Down

0 comments on commit a22d72a

Please sign in to comment.