Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(esm): converted the package to esm #450

Merged
merged 11 commits into from Jun 2, 2023
Merged
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
@@ -0,0 +1,2 @@
# style: prettier
6964913a3286531f1b3aa0a264feee9e84bb2329
3 changes: 2 additions & 1 deletion .github/workflows/release.yml
Expand Up @@ -23,7 +23,8 @@ jobs:
with:
node-version: lts/*
cache: npm
- run: npm ci
- run: npm clean-install
- run: npm audit signatures
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/test.yml
Expand Up @@ -13,8 +13,9 @@ jobs:
strategy:
matrix:
node-version:
- 14.17
- 16
- 18.0.0
- 19
- 20
os:
- ubuntu-latest
- macos-latest
Expand All @@ -27,7 +28,7 @@ jobs:
with:
node-version: "${{ matrix.node-version }}"
cache: npm
- run: npm ci
- run: npm clean-install
- run: "npm run test:ci"
test:
runs-on: ubuntu-latest
Expand All @@ -36,9 +37,13 @@ jobs:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
node-version: 16
node-version: "lts/*"
cache: npm
- run: npm ci
- run: npm clean-install
- run: npm audit signatures
- name: Ensure dependencies are compatible with the engines range
run: npx ls-engines
- run: npm run lint
# https://github.com/lirantal/lockfile-lint#readme
- name: Scan lockfile for security issues
run: npx lockfile-lint --path package-lock.json
95 changes: 59 additions & 36 deletions README.md

Large diffs are not rendered by default.

48 changes: 24 additions & 24 deletions index.js
@@ -1,20 +1,22 @@
const {isUndefined} = require('lodash');
const parser = require('conventional-commits-parser').sync;
const filter = require('conventional-commits-filter');
const debug = require('debug')('semantic-release:commit-analyzer');
const loadParserConfig = require('./lib/load-parser-config.js');
const loadReleaseRules = require('./lib/load-release-rules.js');
const analyzeCommit = require('./lib/analyze-commit.js');
const compareReleaseTypes = require('./lib/compare-release-types.js');
const RELEASE_TYPES = require('./lib/default-release-types.js');
const DEFAULT_RELEASE_RULES = require('./lib/default-release-rules.js');
import { isUndefined } from "lodash-es";
import { sync as parser } from "conventional-commits-parser";
import filter from "conventional-commits-filter";
import debugFactory from "debug";
import loadParserConfig from "./lib/load-parser-config.js";
import loadReleaseRules from "./lib/load-release-rules.js";
import analyzeCommit from "./lib/analyze-commit.js";
import compareReleaseTypes from "./lib/compare-release-types.js";
import RELEASE_TYPES from "./lib/default-release-types.js";
import DEFAULT_RELEASE_RULES from "./lib/default-release-rules.js";

const debug = debugFactory("semantic-release:commit-analyzer");

/**
* Determine the type of release to create based on a list of commits.
*
* @param {Object} pluginConfig The plugin configuration.
* @param {String} pluginConfig.preset conventional-changelog preset ('angular', 'atom', 'codemirror', 'ember', 'eslint', 'express', 'jquery', 'jscs', 'jshint')
* @param {String} pluginConfig.config Requirable npm package with a custom conventional-changelog preset
* @param {String} pluginConfig.config Requireable npm package with a custom conventional-changelog preset
* @param {String|Array} pluginConfig.releaseRules A `String` to load an external module or an `Array` of rules.
* @param {Object} pluginConfig.parserOpts Additional `conventional-changelog-parser` options that will overwrite ones loaded by `preset` or `config`.
* @param {Object} context The semantic-release context.
Expand All @@ -23,43 +25,43 @@ const DEFAULT_RELEASE_RULES = require('./lib/default-release-rules.js');
*
* @returns {String|null} the type of release to create based on the list of commits or `null` if no release has to be done.
*/
async function analyzeCommits(pluginConfig, context) {
const {commits, logger} = context;
export async function analyzeCommits(pluginConfig, context) {
const { commits, logger } = context;
const releaseRules = loadReleaseRules(pluginConfig, context);
const config = await loadParserConfig(pluginConfig, context);
let releaseType = null;

filter(
commits
.filter(({message, hash}) => {
.filter(({ message, hash }) => {
if (!message.trim()) {
debug('Skip commit %s with empty message', hash);
debug("Skip commit %s with empty message", hash);
return false;
}

return true;
})
.map(({message, ...commitProps}) => ({rawMsg: message, message, ...commitProps, ...parser(message, config)}))
).every(({rawMsg, ...commit}) => {
.map(({ message, ...commitProps }) => ({ rawMsg: message, message, ...commitProps, ...parser(message, config) }))
).every(({ rawMsg, ...commit }) => {
logger.log(`Analyzing commit: %s`, rawMsg);
let commitReleaseType;

// Determine release type based on custom releaseRules
if (releaseRules) {
debug('Analyzing with custom rules');
debug("Analyzing with custom rules");
commitReleaseType = analyzeCommit(releaseRules, commit);
}

// If no custom releaseRules or none matched the commit, try with default releaseRules
if (isUndefined(commitReleaseType)) {
debug('Analyzing with default rules');
debug("Analyzing with default rules");
commitReleaseType = analyzeCommit(DEFAULT_RELEASE_RULES, commit);
}

if (commitReleaseType) {
logger.log('The release type for the commit is %s', commitReleaseType);
logger.log("The release type for the commit is %s", commitReleaseType);
} else {
logger.log('The commit should not trigger a release');
logger.log("The commit should not trigger a release");
}

// Set releaseType if commit's release type is higher
Expand All @@ -74,9 +76,7 @@ async function analyzeCommits(pluginConfig, context) {

return true;
});
logger.log('Analysis of %s commits complete: %s release', commits.length, releaseType || 'no');
logger.log("Analysis of %s commits complete: %s release", commits.length, releaseType || "no");

return releaseType;
}

module.exports = {analyzeCommits};
21 changes: 11 additions & 10 deletions lib/analyze-commit.js
@@ -1,22 +1,23 @@
const {isMatchWith, isString} = require('lodash');
const micromatch = require('micromatch');
const debug = require('debug')('semantic-release:commit-analyzer');
const RELEASE_TYPES = require('./default-release-types.js');
const compareReleaseTypes = require('./compare-release-types.js');
import { isMatchWith, isString } from "lodash-es";
import micromatch from "micromatch";
import debugFactory from "debug";
import RELEASE_TYPES from "./default-release-types.js";
import compareReleaseTypes from "./compare-release-types.js";

const debug = debugFactory("semantic-release:commit-analyzer");
/**
* Find all the rules matching and return the highest release type of the matching rules.
*
* @param {Array} releaseRules the rules to match the commit against.
* @param {Commit} commit a parsed commit.
* @return {string} the highest release type of the matching rules or `undefined` if no rule match the commit.
*/
module.exports = (releaseRules, commit) => {
export default (releaseRules, commit) => {
let releaseType;

releaseRules
.filter(
({breaking, revert, release, ...rule}) =>
({ breaking, revert, release, ...rule }) =>
// If the rule is not `breaking` or the commit doesn't have a breaking change note
(!breaking || (commit.notes && commit.notes.length > 0)) &&
// If the rule is not `revert` or the commit is not a revert
Expand All @@ -29,14 +30,14 @@ module.exports = (releaseRules, commit) => {
.every((match) => {
if (compareReleaseTypes(releaseType, match.release)) {
releaseType = match.release;
debug('The rule %o match commit with release type %o', match, releaseType);
debug("The rule %o match commit with release type %o", match, releaseType);
if (releaseType === RELEASE_TYPES[0]) {
debug('Release type %o is the highest possible. Stop analysis.', releaseType);
debug("Release type %o is the highest possible. Stop analysis.", releaseType);
return false;
}
} else {
debug(
'The rule %o match commit with release type %o but the higher release type %o has already been found for this commit',
"The rule %o match commit with release type %o but the higher release type %o has already been found for this commit",
match,
match.release,
releaseType
Expand Down
4 changes: 2 additions & 2 deletions lib/compare-release-types.js
@@ -1,4 +1,4 @@
const RELEASE_TYPES = require('./default-release-types.js');
import RELEASE_TYPES from "./default-release-types.js";

/**
* Test if a realease type is of higher level than a given one.
Expand All @@ -7,5 +7,5 @@ const RELEASE_TYPES = require('./default-release-types.js');
* @param {string} releaseType the release type to compare with.
* @return {Boolean} true if `releaseType` is higher than `currentReleaseType`.
*/
module.exports = (currentReleaseType, releaseType) =>
export default (currentReleaseType, releaseType) =>
!currentReleaseType || RELEASE_TYPES.indexOf(releaseType) < RELEASE_TYPES.indexOf(currentReleaseType);
44 changes: 22 additions & 22 deletions lib/default-release-rules.js
Expand Up @@ -3,32 +3,32 @@
*
* @type {Array}
*/
module.exports = [
{breaking: true, release: 'major'},
{revert: true, release: 'patch'},
export default [
{ breaking: true, release: "major" },
{ revert: true, release: "patch" },
// Angular
{type: 'feat', release: 'minor'},
{type: 'fix', release: 'patch'},
{type: 'perf', release: 'patch'},
{ type: "feat", release: "minor" },
{ type: "fix", release: "patch" },
{ type: "perf", release: "patch" },
// Atom
{emoji: ':racehorse:', release: 'patch'},
{emoji: ':bug:', release: 'patch'},
{emoji: ':penguin:', release: 'patch'},
{emoji: ':apple:', release: 'patch'},
{emoji: ':checkered_flag:', release: 'patch'},
{ emoji: ":racehorse:", release: "patch" },
{ emoji: ":bug:", release: "patch" },
{ emoji: ":penguin:", release: "patch" },
{ emoji: ":apple:", release: "patch" },
{ emoji: ":checkered_flag:", release: "patch" },
// Ember
{tag: 'BUGFIX', release: 'patch'},
{tag: 'FEATURE', release: 'minor'},
{tag: 'SECURITY', release: 'patch'},
{ tag: "BUGFIX", release: "patch" },
{ tag: "FEATURE", release: "minor" },
{ tag: "SECURITY", release: "patch" },
// ESLint
{tag: 'Breaking', release: 'major'},
{tag: 'Fix', release: 'patch'},
{tag: 'Update', release: 'minor'},
{tag: 'New', release: 'minor'},
{ tag: "Breaking", release: "major" },
{ tag: "Fix", release: "patch" },
{ tag: "Update", release: "minor" },
{ tag: "New", release: "minor" },
// Express
{component: 'perf', release: 'patch'},
{component: 'deps', release: 'patch'},
{ component: "perf", release: "patch" },
{ component: "deps", release: "patch" },
// JSHint
{type: 'FEAT', release: 'minor'},
{type: 'FIX', release: 'patch'},
{ type: "FEAT", release: "minor" },
{ type: "FIX", release: "patch" },
];
2 changes: 1 addition & 1 deletion lib/default-release-types.js
Expand Up @@ -3,4 +3,4 @@
*
* @type {Array}
*/
module.exports = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'];
export default ["major", "premajor", "minor", "preminor", "patch", "prepatch", "prerelease"];
21 changes: 12 additions & 9 deletions lib/load-parser-config.js
@@ -1,21 +1,24 @@
const {promisify} = require('util');
const {isPlainObject} = require('lodash');
const importFrom = require('import-from');
const conventionalChangelogAngular = require('conventional-changelog-angular');
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";
import { isPlainObject } from "lodash-es";
import importFrom from "import-from";
import conventionalChangelogAngular from "conventional-changelog-angular";

/**
* Load `conventional-changelog-parser` options. Handle presets that return either a `Promise<Array>` or a `Promise<Function>`.
*
* @param {Object} pluginConfig The plugin configuration.
* @param {Object} pluginConfig.preset conventional-changelog preset ('angular', 'atom', 'codemirror', 'ember', 'eslint', 'express', 'jquery', 'jscs', 'jshint')
* @param {String} pluginConfig.config Requirable npm package with a custom conventional-changelog preset
* @param {Object} pluginConfig.parserOpts Additionnal `conventional-changelog-parser` options that will overwrite ones loaded by `preset` or `config`.
* @param {String} pluginConfig.config Requireable npm package with a custom conventional-changelog preset
* @param {Object} pluginConfig.parserOpts Additional `conventional-changelog-parser` options that will overwrite ones loaded by `preset` or `config`.
* @param {Object} context The semantic-release context.
* @param {String} context.cwd The current working directory.
* @return {Promise<Object>} a `Promise` that resolve to the `conventional-changelog-parser` options.
*/
module.exports = async ({preset, config, parserOpts, presetConfig}, {cwd}) => {
export default async ({ preset, config, parserOpts, presetConfig }, { cwd }) => {
let loadedConfig;
const __dirname = dirname(fileURLToPath(import.meta.url));

if (preset) {
const presetPackage = `conventional-changelog-${preset.toLowerCase()}`;
Expand All @@ -26,11 +29,11 @@ module.exports = async ({preset, config, parserOpts, presetConfig}, {cwd}) => {
loadedConfig = conventionalChangelogAngular;
}

loadedConfig = await (typeof loadedConfig === 'function'
loadedConfig = await (typeof loadedConfig === "function"
? isPlainObject(presetConfig)
? loadedConfig(presetConfig)
: promisify(loadedConfig)()
: loadedConfig);

return {...loadedConfig.parserOpts, ...parserOpts};
return { ...loadedConfig.parserOpts, ...parserOpts };
};
13 changes: 8 additions & 5 deletions lib/load-release-rules.js
@@ -1,6 +1,8 @@
const {isUndefined} = require('lodash');
const importFrom = require('import-from');
const RELEASE_TYPES = require('./default-release-types.js');
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { isUndefined } from "lodash-es";
import importFrom from "import-from";
import RELEASE_TYPES from "./default-release-types.js";

/**
* Load and validate the `releaseRules` rules.
Expand All @@ -15,12 +17,13 @@ const RELEASE_TYPES = require('./default-release-types.js');
*
* @return {Array} the loaded and validated `releaseRules`.
*/
module.exports = ({releaseRules}, {cwd}) => {
export default ({ releaseRules }, { cwd }) => {
let loadedReleaseRules;
const __dirname = dirname(fileURLToPath(import.meta.url));

if (releaseRules) {
loadedReleaseRules =
typeof releaseRules === 'string'
typeof releaseRules === "string"
? importFrom.silent(__dirname, releaseRules) || importFrom(cwd, releaseRules)
: releaseRules;

Expand Down