Skip to content

Commit

Permalink
feat: Add linter for PR title using built-in package (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevintyj authored Nov 22, 2023
1 parent 73028da commit d803a7a
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 4 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/prlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: 📝 Lint PR title
on:
pull_request:
types: [opened, edited, reopened, synchronize]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 🔖Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦Setup PNPM
uses: pnpm/action-setup@v2
with:
version: 8
- name: 🌳Setup Node
uses: actions/setup-node@v3
with:
node-version: 20
cache: pnpm

- name: 🛠️Install dependencies from lockfile
run: pnpm install --frozen-lockfile

- name: 🧾Print versions
run: |
git --version
node --version
pnpm --version
pnpm commitlint --version
- name: 📝Validate PR title with commitlint
uses: ./packages/commitlint
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# dist
dist

# commited dist files
!packages/commitlint/dist

# dependencies
node_modules

Expand Down
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default antfu(
'**/dist',
'.idea',
'**/__fixtures__',
'eslint.config.js',
'packages/conventionalsets-action',
],
overrides: {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@antfu/eslint-config": "^1.1.0",
"@changesets/cli": "^2.26.2",
"@commitlint/cli": "^18.2.0",
"@commitlint/config-conventional": "^18.1.0",
"@vitest/coverage-v8": "^0.34.6",
"eslint": "^8.53.0",
"husky": "^8.0.3",
Expand Down
9 changes: 9 additions & 0 deletions packages/commitlint/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: Commitlint (prlint)
author: Kevin Taeyoon Jin <[email protected]>
description: Ensure PR title match commitlint config
runs:
using: node20
main: dist/index.cjs
branding:
icon: git-pull-request
color: green
96 changes: 96 additions & 0 deletions packages/commitlint/dist/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict';

var github = require('@actions/github');
var core = require('@actions/core');
var process = require('process');
var fs = require('fs');
var load = require('@commitlint/load');
var lint = require('@commitlint/lint');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}

var github__namespace = /*#__PURE__*/_interopNamespace(github);
var process__default = /*#__PURE__*/_interopDefault(process);
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
var load__default = /*#__PURE__*/_interopDefault(load);
var lint__default = /*#__PURE__*/_interopDefault(lint);

// src/index.ts
function handleError(err, fail = true) {
if (err instanceof Error) {
core.error(err);
fail && core.setFailed(err.message);
} else {
const message = typeof err == "string" ? err : "Unknown error has occurred!";
core.error(message);
fail && core.setFailed(message);
}
}
var errHandle_default = handleError;

// src/log.ts
var SEPARATOR = "=====================";
function logWithTile(title, content) {
return `${title}
${SEPARATOR}
${content}`;
}
var log_default = logWithTile;

// src/lint.ts
var defaultConfig = {
extends: "@commitlint/config-conventional"
};
function getLintOptions(configuration) {
var _a;
return {
defaultIgnores: configuration.defaultIgnores ? configuration.defaultIgnores : true,
ignores: configuration.ignores ? configuration.ignores : void 0,
parserOpts: typeof ((_a = configuration.parserPreset) == null ? void 0 : _a.parserOpts) == "object" ? configuration.parserPreset.parserOpts : void 0,
plugins: configuration.plugins ? configuration.plugins : void 0,
helpUrl: configuration.helpUrl ? configuration.helpUrl : void 0
};
}
async function verifyTitle(title, configPath = "") {
const commitlintConfig = fs__namespace.existsSync(configPath) ? await load__default.default({}, { file: configPath, cwd: process__default.default.cwd() }) : await load__default.default(defaultConfig);
const linterResult = await lint__default.default(title, commitlintConfig.rules, getLintOptions(commitlintConfig));
if (linterResult.valid) {
return true;
} else {
const errors = linterResult.errors.map((error2) => {
return `${error2.name}: ${error2.message}`;
}).join("\n");
throw new Error(log_default("Commitlint check failed!", errors));
}
}

// src/index.ts
async function run() {
const pullRequestPayload = github__namespace.context.payload.pull_request;
if (!(pullRequestPayload == null ? void 0 : pullRequestPayload.title))
throw new Error("Pull Request or Title not found!");
const pullRequestObject = {
title: pullRequestPayload.title,
number: pullRequestPayload.number
};
await verifyTitle(pullRequestObject.title, "commitlint.config.js");
}
run().catch(errHandle_default);
68 changes: 68 additions & 0 deletions packages/commitlint/dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as github from '@actions/github';
import { error, setFailed } from '@actions/core';
import process from 'process';
import * as fs from 'fs';
import load from '@commitlint/load';
import lint from '@commitlint/lint';

// src/index.ts
function handleError(err, fail = true) {
if (err instanceof Error) {
error(err);
fail && setFailed(err.message);
} else {
const message = typeof err == "string" ? err : "Unknown error has occurred!";
error(message);
fail && setFailed(message);
}
}
var errHandle_default = handleError;

// src/log.ts
var SEPARATOR = "=====================";
function logWithTile(title, content) {
return `${title}
${SEPARATOR}
${content}`;
}
var log_default = logWithTile;

// src/lint.ts
var defaultConfig = {
extends: "@commitlint/config-conventional"
};
function getLintOptions(configuration) {
var _a;
return {
defaultIgnores: configuration.defaultIgnores ? configuration.defaultIgnores : true,
ignores: configuration.ignores ? configuration.ignores : void 0,
parserOpts: typeof ((_a = configuration.parserPreset) == null ? void 0 : _a.parserOpts) == "object" ? configuration.parserPreset.parserOpts : void 0,
plugins: configuration.plugins ? configuration.plugins : void 0,
helpUrl: configuration.helpUrl ? configuration.helpUrl : void 0
};
}
async function verifyTitle(title, configPath = "") {
const commitlintConfig = fs.existsSync(configPath) ? await load({}, { file: configPath, cwd: process.cwd() }) : await load(defaultConfig);
const linterResult = await lint(title, commitlintConfig.rules, getLintOptions(commitlintConfig));
if (linterResult.valid) {
return true;
} else {
const errors = linterResult.errors.map((error2) => {
return `${error2.name}: ${error2.message}`;
}).join("\n");
throw new Error(log_default("Commitlint check failed!", errors));
}
}

// src/index.ts
async function run() {
const pullRequestPayload = github.context.payload.pull_request;
if (!(pullRequestPayload == null ? void 0 : pullRequestPayload.title))
throw new Error("Pull Request or Title not found!");
const pullRequestObject = {
title: pullRequestPayload.title,
number: pullRequestPayload.number
};
await verifyTitle(pullRequestObject.title, "commitlint.config.js");
}
run().catch(errHandle_default);
2 changes: 2 additions & 0 deletions packages/commitlint/src/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as fs from 'node:fs';
import type { LintOptions, ParserOptions, QualifiedConfig } from '@commitlint/types';
import load from '@commitlint/load';
import lint from '@commitlint/lint';
import { setOutput } from '@actions/core';
import logWithTile from './log';

const defaultConfig = {
Expand Down Expand Up @@ -44,6 +45,7 @@ export async function verifyTitle(title: string, configPath: string = ''): Promi
const linterResult = await lint(title, commitlintConfig.rules, getLintOptions(commitlintConfig));

if (linterResult.valid) {
setOutput('✅ Commitlint tests passed!\n', linterResult);
return true;
}
else {
Expand Down
5 changes: 3 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,5 @@
"noUnusedParameters": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
"exclude": ["node_modules", "**/dist"]
}

0 comments on commit d803a7a

Please sign in to comment.