Skip to content

Commit

Permalink
Feat: recover the complete changelog.md (#10)
Browse files Browse the repository at this point in the history
* Style: add red color to warnings

* Feat: recover the complete changelog.md

* Test: for new feature complete changelog.md

* Feat: cli support for recover complete changelog.md

* Chore: add new dependecies

* Docs: add description for new feat

* Fix: problem with babel

* CI: tmp fix, downgrade to [email protected] on windows

* Refactor: remove unnecessary try catch

* Test: update for better coverage

* Test: remove Object.keys

* Test: fix tests

* Refactor: create changelog parts

* Test: update for new feat and update to fs-extra

* Style: remove index
  • Loading branch information
aichbauer authored Sep 13, 2017
1 parent 82d1fcc commit 67e04d0
Show file tree
Hide file tree
Showing 12 changed files with 698 additions and 439 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,14 @@ So there are a few tasks `semantic-git-release-cli` will do for you:
- updates the `version` in `package.json`
- creates or updates the `CHANGELOG.md`
- commits and tags the new `version`

## Recover the CHANGELOG.md

If you are start to use `semantic-git-release-cli` but already released (and tagged) versions. Simply use the recover mode.

```sh
# generates the complete CHANGELOG.md
sgr --recover # or short `sgr -r`
# generates the complete CHANGELOG.md and creates a backup of the current CHANGELOG.md in .sgr_backup
sgr -r backup # or short `sgr -r b`
```
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ install:
- ps: Install-Product node $env:nodejs_version
# install modules
- npm config set loglevel warn
- npm i -g npm
- npm i -g npm@5.3
- npm i

# Post-install test scripts.
Expand Down
18 changes: 14 additions & 4 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ import getLatestVersion from './helpers/getLatestVersion';
import pkg from '../package.json';
import questions from './questions';
import tasks from './tasks';
import recoverTasks from './recover-tasks';

const argv = yargs
.usage('Usage: $0')
.alias('v', 'version')
.describe('v', 'Version number')
.help('h')
.alias('h', 'help')
.alias('r', 'recover')
.describe('r', 'Recover the complete CHANGELOG.md')
.argv;

updateNotifier({ pkg }).notify();
Expand All @@ -40,7 +43,7 @@ const cli = () => {
} else if (!isAdded(cwd) && commits.length === 0) {
return console.warn(chalk.red('Error: no changes... try to git add <files>'));
} else if (commits.length === 0) {
return console.warn(chalk.red('Error: no commits yet... try to git commit -m <message>'));
return console.warn(chalk.red('Error: no commits yet... try to git commit -m <message>'));
} else if (!getGitRemotes(cwd)) {
return console.warn(chalk.red('Error: it seems you do not have a remote repository set... try to git remote add origin <remote-url>'));
} else if (latestVersion === '') {
Expand All @@ -53,18 +56,25 @@ const cli = () => {
if (answers.ownVersion) {
return tasks(commits, answers.ownVersion)
.run()
.catch(() => console.warn('Error: whoops, try to solve the problem mentioned above...'));
.catch(() => console.warn(chalk.red('Error: whoops, try to solve the problem mentioned above...')));
}

return tasks(commits, answers.version)
.run()
.catch(() => console.warn('Error: whoops, try to solve the problem mentioned above...'));
.catch(() => console.warn(chalk.red('Error: whoops, try to solve the problem mentioned above...')));
})
.catch((err) => console.warn(err));
.catch((err) => console.warn(chalk.red(err)));
};

if (argv.v) {
console.info(`v${pkg.version}`);
} else if (argv.recover) {
if (argv.recover === 'b' || argv.recover === 'backup') {
recoverTasks(true).run();
} else {
recoverTasks(false).run();
}
} else {
cli();
}

44 changes: 44 additions & 0 deletions lib/helpers/changelogParts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import moment from 'moment';
import gitCommitInfo from 'git-commit-info';

const header = (version, date = '') => {
if (date === '') {
return `${version} - ${moment().format('MMMM, DD YYYY')}`;
}

return `${version} - ${moment(date, 'ddd MMM D HH:mm:ss YYYY Z').format('MMMM, DD YYYY')}`;
};

const oneCommit = (commitInfo) => (
`* ${commitInfo.shortHash} ${commitInfo.message.split('\n')[0]} (${commitInfo.author})`
);

const body = (commits, version) => {
const cwd = process.cwd();
let changelogData = '';

commits.forEach((commit, i) => {
const commitInfo = gitCommitInfo({ commit, cwd });

/* istanbul ignore next */
if (!commitInfo.shortHash ||
!commitInfo.author ||
!commitInfo.message ||
commitInfo.message.split('\n')[0] === version) {
return;
}

changelogData = `${changelogData} ${oneCommit(commitInfo)}\n`;

if (commits.length - 1 === i) {
changelogData = `${changelogData}\n`;
}
});

return changelogData;
};

export {
header,
body,
};
103 changes: 103 additions & 0 deletions lib/helpers/generateCompleteChangelog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import fs from 'fs-extra';
import gitCommitInfo from 'git-commit-info';
import getCommitRange from 'git-commit-range';
import moment from 'moment';
import path from 'path';
import prependFile from 'prepend-file';
import taggedCommits from 'tagged-git-commits';
import {
header,
body,
} from './changelogParts';

const writeBackup = () => {
const cwd = process.cwd();

fs.renameSync(
path.join(cwd, 'CHANGELOG.md'),
path.join(cwd, '.sgr_backup', `CHANGELOG.${moment().unix()}.bak.md`),
);
};

const backupChangelog = () => {
const cwd = process.cwd();

if (fs.existsSync(path.join(cwd, '.sgr_backup'))) {
return writeBackup();
}

fs.mkdirSync(path.join(cwd, '.sgr_backup'));

return writeBackup();
};

const getAllTags = () => {
const cwd = process.cwd();
const tags = taggedCommits({
path: cwd,
lookBehind: Number.POSITIVE_INFINITY,
});

return tags;
};

const writeToFile = (tags, exists, backup) => {
const cwd = process.cwd();
let changelogData = '';
let commits = [];
let tagDate = '';

if (exists && backup) {
backupChangelog();
} else if (exists) {
fs.truncateSync(path.join(cwd, 'CHANGELOG.md'), 0);
}

tags.forEach((tag, idx) => {
if (idx === 0) {
commits = getCommitRange({
path: cwd,
});
commits = getCommitRange({
path: cwd,
from: commits[commits.length - 1],
to: tag.hash,
});
} else {
commits = getCommitRange({
path: cwd,
from: tags[idx - 1].hash,
to: tag.hash,
});
}

tagDate = gitCommitInfo({
cwd,
commit: tag.hash,
}).date;

const version = tag.version.slice(1, tag.version.length);

changelogData = `${header(version, tagDate)}\n\n${body(commits, version)}`;

prependFile.sync(path.join(cwd, 'CHANGELOG.md'), changelogData);
});
};

const generateCompleteChangelog = (backup) => {
const cwd = process.cwd();

try {
const exists = fs.existsSync(path.join(cwd, 'CHANGELOG.md'));

if (!exists) {
fs.writeFileSync(path.join(cwd, 'CHANGELOG.md'), '');
}

return writeToFile(getAllTags(), exists, backup);
} catch (err) {
return false;
}
};

export default generateCompleteChangelog;
43 changes: 15 additions & 28 deletions lib/helpers/updateChangelog.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,28 @@
import fs from 'fs';
import gitCommitInfo from 'git-commit-info';
import moment from 'moment';
import fs from 'fs-extra';
import path from 'path';
import prependFile from 'prepend-file';
import {
header,
body,
} from './changelogParts';

const writeToFile = (commits = [], version, exists) => {
const writeToFile = (commits = [], version) => {
const cwd = process.cwd();
const changelogData = `${header(version)}\n\n${body(commits, version)}`;

let changelogData;

if (exists) {
const changelog = fs.readFileSync(path.join(cwd, 'CHANGELOG.md'), 'utf8');
changelogData = `\n${changelog}`;
} else {
changelogData = '';
}

const stream = fs.createWriteStream(path.join(cwd, 'CHANGELOG.md'), 'utf8');

stream.write(`${version} - ${moment().format('MMMM, DD YYYY')}\n\n`);

commits.forEach((commithash) => {
const commitInfo = gitCommitInfo({ commit: commithash, cwd });

stream.write(`* ${commitInfo.shortHash} ${commitInfo.message.split('\n')[0]} (${commitInfo.author})\n`);
});

stream.write(changelogData);

return stream.end();
prependFile.sync(path.join(cwd, 'CHANGELOG.md'), changelogData);
};

const updateChangelog = (commits = [], version) => {
try {
const cwd = process.cwd();
const cwd = process.cwd();

try {
const exists = fs.existsSync(path.join(cwd, 'CHANGELOG.md'));

if (!exists) {
fs.writeFileSync(path.join(cwd, 'CHANGELOG.md'), '');
}

return writeToFile(commits, version, exists);
} catch (err) {
return false;
Expand Down
16 changes: 16 additions & 0 deletions lib/recover-tasks/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Listr from 'listr';

import generateCompleteChangelog from '../helpers/generateCompleteChangelog';

const recoverTasks = (backup) => (
new Listr([
{
title: 'Recover the complete CHANGELOG.md',
task: () => {
generateCompleteChangelog(backup);
},
},
])
);

export default recoverTasks;
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
"homepage": "https://github.com/aichbauer/node-semantic-git-release-cli#readme",
"devDependencies": {
"ava": "^0.18.2",
"babel-cli": "^6.24.0",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.2.1",
"coveralls": "^2.12.0",
Expand All @@ -66,7 +65,9 @@
"nyc": "^10.1.2"
},
"dependencies": {
"babel-cli": "^6.26.0",
"chalk": "^2.0.1",
"count-git-tags": "^1.0.0",
"execa": "^0.6.3",
"fs-extra": "^3.0.1",
"get-git-remotes": "^1.0.1",
Expand All @@ -78,6 +79,7 @@
"is-git-repository": "^1.1.1",
"listr": "^0.12.0",
"moment": "^2.18.1",
"prepend-file": "^1.3.1",
"semver": "^5.3.0",
"tagged-git-commits": "^1.0.0",
"update-notifier": "^2.1.0",
Expand Down
Loading

0 comments on commit 67e04d0

Please sign in to comment.