Skip to content

Commit

Permalink
feat(.changelogrc.js): transfer repository over to semantic-release C…
Browse files Browse the repository at this point in the history
…I/CD
  • Loading branch information
Xunnamius committed Jan 5, 2021
1 parent 1fcfd40 commit b9d2bf0
Show file tree
Hide file tree
Showing 50 changed files with 17,008 additions and 6,649 deletions.
212 changes: 212 additions & 0 deletions .changelogrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
// ? See https://github.com/conventional-changelog/conventional-changelog

const debug = require('debug')(
`${require('./package.json').name}:conventional-changelog-config`
);

const escapeRegExpStr = require('escape-string-regexp');
const semver = require('semver');
const sjx = require('shelljs');

// ? Commit types that trigger releases by default (using angular configuration)
// ? See https://github.com/semantic-release/commit-analyzer/blob/master/lib/default-release-rules.js
const DEFAULT_RELEASED_TYPES = ['feat', 'fix', 'perf'];

// ? Same options as commit-analyzer's releaseRules (see
// ? https://github.com/semantic-release/commit-analyzer#releaserules) with the
// ? addition of the `title` property to set the resulting section title
const ADDITIONAL_RELEASE_RULES = [
{ type: 'build', release: 'patch', title: 'Build System' }
];

const changelogTitle =
`# Changelog\n\n` +
`All notable changes to this project will be documented in this file.\n\n` +
`The format is based on [Conventional Commits](https://conventionalcommits.org),\n` +
`and this project adheres to [Semantic Versioning](https://semver.org).`;

// ? Strings in commit messages that, when found, are skipped
// ! These also have to be updated in build-test-deploy.yml and cleanup.yml
const SKIP_COMMANDS = '[skip ci], [ci skip], [skip cd], [cd skip]'.split(', ');

debug('SKIP_COMMANDS=', SKIP_COMMANDS);

sjx.config.silent = true;

// ! XXX: dark magic to synchronously deal with this async package
const wait = sjx.exec(
`node -e 'require("conventional-changelog-angular").then(o => console.log(o.writerOpts.transform.toString()));'`
);

if (wait.code != 0) throw new Error('failed to acquire angular transformation');

const transform = Function(`"use strict";return (${wait.stdout})`)();
const sentenceCase = (s) => s.toString().charAt(0).toUpperCase() + s.toString().slice(1);

const extraReleaseTriggerCommitTypes = ADDITIONAL_RELEASE_RULES.map((r) => r.type);
const allReleaseTriggerCommitTypes = [
DEFAULT_RELEASED_TYPES,
extraReleaseTriggerCommitTypes
].flat();

debug('extra types that trigger releases = %O', extraReleaseTriggerCommitTypes);
debug('all types that trigger releases = %O', allReleaseTriggerCommitTypes);

// ? Releases made before this repo adopted semantic-release. They will be
// ? collected together under a single header
const legacyReleases = [];
let shouldGenerate = true;

module.exports = {
changelogTitle,
additionalReleaseRules: ADDITIONAL_RELEASE_RULES.map(({ title, ...r }) => r),
parserOpts: {
mergePattern: /^Merge pull request #(\d+) from (.*)$/,
mergeCorrespondence: ['id', 'source'],
noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES', 'BREAKING'],
// eslint-disable-next-line no-console
warn: console.warn.bind(console)
},
writerOpts: {
generateOn: (commit) => {
const decision =
shouldGenerate === 'always' ||
(shouldGenerate &&
!!semver.valid(commit.version) &&
!semver.prerelease(commit.version));
debug(`::generateOn shouldGenerate=${shouldGenerate} decision=${decision}`);
shouldGenerate = true;
return decision;
},
transform: (commit, context) => {
const version = commit.version || null;
const firstRelease = version === context.gitSemverTags?.slice(-1)[0].slice(1);

debug('::transform encountered commit = %O', commit);
debug(`::transform commit version = ${version}`);
debug(`::transform commit firstRelease = ${firstRelease}`);

if (commit.revert) {
debug('::transform coercing to type "revert"');
commit.type = 'revert';
} else if (commit.type == 'revert') {
debug('::transform ignoring malformed revert commit');
return null;
}

commit.originalType = commit.type;

if (!firstRelease || commit.type) {
// ? This commit does not have a type, but has a version. It must be a
// ? legacy release!
if (version && !commit.type) {
debug('::transform determined commit is legacy release');
legacyReleases.push(commit);
commit = null;
shouldGenerate = false;
} else {
let fakeFix = false;

if (extraReleaseTriggerCommitTypes.includes(commit.type)) {
debug(`::transform encountered custom commit type: ${commit.type}`);
commit.type = 'fix';
fakeFix = true;
}

commit = transform(commit, context);

debug('::transform angular transformed commit = %O', commit);

if (commit) {
if (fakeFix) {
commit.type = ADDITIONAL_RELEASE_RULES.find(
(r) => r.type == commit.originalType
)?.title;
debug('::transform debug: %O', ADDITIONAL_RELEASE_RULES);
debug(`::transform commit type set to custom title: ${commit.type}`);
} else commit.type = sentenceCase(commit.type);

// ? Ignore any commits with skip commands in them
if (SKIP_COMMANDS.some((cmd) => commit.subject?.includes(cmd))) {
debug(`::transform saw skip command in commit message; commit skipped`);
return null;
}

if (commit.subject) {
// ? Make scope-less commit subjects sentence case in the
// ? changelog per my tastes
if (!commit.scope) commit.subject = sentenceCase(commit.subject);

// ? Italicize reverts per my tastes
if (commit.originalType == 'revert') commit.subject = `*${commit.subject}*`;
}

// ? For breaking changes, make all scopes and subjects bold.
// ? Scope-less subjects are made sentence case. All per my
// ? tastes
commit.notes.forEach((note) => {
if (note.text) {
debug('::transform saw BC notes for this commit');
const [firstLine, ...remainder] = note.text.trim().split('\n');
note.text =
`**${!commit.scope ? sentenceCase(firstLine) : firstLine}**` +
remainder.reduce((result, line) => `${result}\n${line}`, '');
}
});
}
}
}

// ? If this is the commit representing the earliest release (and there
// ? are legacy releases), use this commit to report collected legacy
// ? releases
else {
debug('::transform generating summary legacy release commit');
shouldGenerate = 'always';

const getShortHash = (h) => h.substring(0, 7);
const shortHash = getShortHash(commit.hash);
const url = context.repository
? `${context.host}/${context.owner}/${context.repository}`
: context.repoUrl;

const subject = legacyReleases
.reverse()
.map(({ hash, version }) => ({
url: `[${getShortHash(hash)}](${url}/commit/${hash})`,
version
}))
.reduce(
(subject, { url, version }) => `Version ${version} (${url})\n\n- ${subject}`,
`Version ${commit.version}`
);

commit = {
type: null,
scope: null,
subject,
id: null,
source: null,
merge: null,
header: null,
body: null,
footer: null,
notes: [],
references: [],
mentions: [],
revert: null,
hash: commit.hash,
shortHash,
gitTags: null,
committerDate: 'pre-CI/CD',
version: 'Archived Releases'
};
}

debug('::transform final commit = %O', commit);
return commit;
}
}
};

debug('exports = %O', module.exports);
2 changes: 2 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
coverage:
range: '70...100'
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = space
indent_size = 2
22 changes: 22 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# When running in the CI pipeline, all required environment variables must be
# defined as repository secrets!

# MongoDB connect URI
#
# Affects: externals/is-next-compat
# Optional: yes
# Default: empty
#
# Specify auth credentials if necessary
# MUST SPECIFY A DATABASE AT THE END! e.g. mongodb://.../your-database-here
MONGODB_URI=mongodb://127.0.0.1:27017/is-next-compat

# GitHub Personal Access Token (PAT)
#
# Affects: externals/is-next-compat
# Optional: yes
# Default: empty
#
# The token used to interact with the API with higher limits. If empty, GitHub
# will rate limit you pretty quick. See https://github.com/settings/tokens
GITHUB_PAT=0123456789abcdef
Loading

0 comments on commit b9d2bf0

Please sign in to comment.