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

feat(commitlint): add initial configuration #115

Merged
merged 2 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://unpkg.com/@changesets/config@2.0.1/schema.json",
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"access": "public",
"baseBranch": "main",
"changelog": ["@mheob/changeset-changelog", { "repo": "mheob/config" }],
Expand Down
5 changes: 5 additions & 0 deletions .changeset/friendly-lemons-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@mheob/commitlint-config': major
---

initial release
22 changes: 22 additions & 0 deletions .commitlintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { existsSync, readdirSync } = require('node:fs');
const { resolve } = require('node:path');

const defaultConfig = require('@mheob/commitlint-config');

function getScopes() {
const defaultScopes = ['deps', 'release', 'repo'];
const packagesPath = resolve(__dirname, 'packages');
const packages = existsSync(packagesPath)
? readdirSync(packagesPath).map((packageName) => packageName.replace('-config', ''))
: [];
return [...defaultScopes, ...packages];
}

/** @type {import('cz-git').UserConfig} */
module.exports = {
...defaultConfig,
prompt: {
...defaultConfig.prompt,
scopes: getScopes(),
},
};
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
auto-install-peers=true
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,26 @@
"sort-package-json": "npx sort-package-json && turbo run sort-package-json",
"version-packages": "changeset version && pnpm exec prettier --write ."
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"lint-staged": {
"*.{cjs,js,jsx,ts,tsx}": "eslint --fix",
"!(pnpm-)*.{cjs,js,mjs,jsx,ts,tsx,json,md,mdx,yaml,yml}": "pnpm exec prettier --write",
"package.json": "npx sort-package-json"
},
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
},
"devDependencies": {
"@changesets/cli": "^2.26.0",
"@commitlint/cli": "^17.4.3",
"@commitlint/config-conventional": "^17.4.3",
"@mheob/changeset-changelog": "^2.0.1",
"@mheob/commitlint-config": "workspace:*",
"@mheob/eslint-config": "workspace:*",
"@mheob/prettier-config": "workspace:*",
"@types/node": "^18.13.0",
"commitizen": "^4.3.0",
"cz-git": "^1.4.1",
"eslint": "^8.34.0",
"husky": "^8.0.3",
"lint-staged": "^13.1.1",
Expand Down
21 changes: 21 additions & 0 deletions packages/commitlint-config/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License Copyright (c) 2023 Alexander Böhm

Permission is hereby granted, free
of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
(including the next paragraph) shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
69 changes: 69 additions & 0 deletions packages/commitlint-config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# My personal Commitlint config

To make my configurations a bit easier I share my [Commitlint](https://commitlint.js.org/) config.

Another notable tool for using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) is [cz-git](https://cz-git.qbb.sh/).

## Install

### With NPM

```sh
npm install -D @mheob/commitlint-config
```

### With YARN

```sh
yarn add -D @mheob/commitlint-config
```

### With PNPM

```sh
pnpm add -D @mheob/commitlint-config
```

## Usage

Add this config to your root `package.json`.

```json
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
```

Now create a `.commitlintrc.cjs` file in the root of your project with this content:

```js
/** @type {import('cz-git').UserConfig} */
module.exports = {
...require('@mheob/commitlint-config'),
};
```

If you want to use your own scopes or if you need to override some settings you can do it in the `.commitlintrc.cjs` this way:

```js
const fs = require('node:fs');
const path = require('node:path');

const defaultConfig = require('@mheob/commitlint-config');

// dynamically define the scopes
const apps = fs.readdirSync(path.resolve(__dirname, 'apps'));
const packages = fs.readdirSync(path.resolve(__dirname, 'packages'));

/** @type {import('cz-git').UserConfig} */
module.exports = {
...defaultConfig,
prompt: {
...defaultConfig.prompt,
scopes: ['deps', 'release', 'repo', ...apps, ...packages],
useEmoji: false,
},
};
```
42 changes: 42 additions & 0 deletions packages/commitlint-config/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@mheob/commitlint-config",
"version": "0.0.0",
"description": "My personal configuration for commitlint.",
"keywords": [
"commitlint",
"config"
],
"homepage": "https://github.com/mheob/config/tree/main/packages/commitlint-config",
"bugs": "https://github.com/mheob/config/issues",
"repository": {
"type": "git",
"url": "https://github.com/mheob/config"
},
"license": "MIT",
"author": "Alexander Böhm <[email protected]>",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
"lint": "eslint src/**/*.ts --fix",
"sort-package-json": "pnpm dlx sort-package-json"
},
"devDependencies": {
"@mheob/eslint-config": "workspace:*",
"@mheob/tsconfig": "workspace:*",
"commitizen": "^4.3.0",
"cz-git": "^1.4.1",
"eslint": "^8.34.0"
},
"peerDependencies": {
"commitizen": "^4.3.0",
"cz-git": "^1.4.1"
},
"publishConfig": {
"access": "public"
}
}
132 changes: 132 additions & 0 deletions packages/commitlint-config/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { execSync } from 'node:child_process';
import { existsSync, readdirSync } from 'node:fs';
import { resolve } from 'node:path';

import type { UserConfig } from 'cz-git';

/**
* Returns all packages inside the given path.
*
* @param directoryPaths The directory paths with the containing the packages.
* @returns An array of package names.
*/
function getPackagesFromPath(...directoryPaths: string[]) {
const packages: string[] = [];

for (const directoryPath of directoryPaths) {
const path = resolve(process.cwd(), directoryPath);
if (!existsSync(path)) continue;
const packages = readdirSync(path);
packages.push(...packages);
}

return packages;
}

/**
* Returns all scopes.
*
* @returns An array of scopes.
*/
function getScopes() {
const defaultScopes = ['deps', 'release', 'repo'];
const packages = getPackagesFromPath('apps', 'packages');
return [...defaultScopes, ...packages];
}

/**
* Returns the issue number, if the branch name starts with a number.
*
* @example
* git branch name = `123-my-branch` => defaultIssues = `#123`
*
* @returns The issue number.
*/
function getIssue() {
const branchName = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
const firstNamePart = branchName.split('-')[0];
return firstNamePart && Number.parseInt(firstNamePart) ? `#${firstNamePart}` : undefined;
}

const options: UserConfig = {
rules: {
'body-leading-blank': [1, 'always'],
'body-max-line-length': [2, 'always', 100],
'footer-leading-blank': [1, 'always'],
'footer-max-line-length': [2, 'always', 100],
'header-max-length': [2, 'always', 100],
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
'subject-max-length': [2, 'always', 72],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [
2,
'always',
['chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'],
],
},
prompt: {
messages: {
type: "Select the type of change that you're committing:",
scope: 'Denote the SCOPE of this change (optional):',
customScope: 'Denote the SCOPE of this change:',
subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n',
body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
breaking: 'List any BREAKING CHANGES (optional). Use "|" to break new line:\n',
footerPrefixesSelect: 'Select the ISSUES type of changeList by this change (optional):',
customFooterPrefix: 'Input ISSUES prefix:',
footer: 'List any ISSUES by this change. E.g.: #31, #34:\n',
confirmCommit: 'Are you sure you want to proceed with the commit above?',
},
types: [
{ value: 'feat', name: 'feat: A new feature' },
{ value: 'fix', name: 'fix: A bug fix' },
{ value: 'docs', name: 'docs: Documentation only changes' },
{ value: 'style', name: 'style: Changes that do not affect the meaning of the code' },
{
value: 'refactor',
name: 'refactor: A code change that neither fixes a bug nor adds a feature',
},
{ value: 'perf', name: 'perf: A code change that improves performance' },
{ value: 'test', name: 'test: Adding missing tests or correcting existing tests' },
{ value: 'ci', name: 'ci: Changes to our CI configuration files and scripts' },
{ value: 'chore', name: "chore: Other changes that don't modify src or test files" },
{ value: 'revert', name: 'revert: Reverts a previous commit' },
],
useEmoji: false,
emojiAlign: 'center',
themeColorCode: '',
scopes: getScopes(),
enableMultipleScopes: true,
scopeEnumSeparator: ',',
allowCustomScopes: false,
allowEmptyScopes: false,
customScopesAlign: 'bottom',
customScopesAlias: 'custom',
emptyScopesAlias: 'empty',
upperCaseSubject: false,
markBreakingChangeMode: true,
allowBreakingChanges: ['feat', 'fix'],
breaklineNumber: 80,
breaklineChar: '|',
skipQuestions: [],
issuePrefixes: [{ value: 'closes', name: 'closes: ISSUES has been processed' }],
customIssuePrefixAlign: getIssue() ? 'bottom' : 'top',
emptyIssuePrefixAlias: 'skip',
customIssuePrefixAlias: 'custom',
allowCustomIssuePrefix: true,
allowEmptyIssuePrefix: true,
confirmColorize: true,
maxHeaderLength: 100,
maxSubjectLength: 72,
minSubjectLength: 0,
defaultBody: '',
defaultIssues: getIssue() ?? '',
defaultScope: '',
defaultSubject: '',
},
};

export = options;
9 changes: 9 additions & 0 deletions packages/commitlint-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "@mheob/tsconfig/commonjs.json",
"compilerOptions": {
"declaration": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*"]
}
Loading