Skip to content

Commit 99f4f3f

Browse files
knocteMersho
andauthoredMar 14, 2024··
feat(cli): introduce new --last flag, to stop recommending HEAD~1 (#3916)
* test(cli): add regression test * feat(cli): implement new `--last` CLI flag The upgrade of ES2017 to ES2022 is because of the use of `Object.hasOwn` API which is less ugly than hardcoding `undefined`. * docs(ci): stop recommending HEAD~1 In a single-commit repo, this would lead to this error: ``` Error: fatal: ambiguous argument 'HEAD~1..HEAD': unknown revision or path not in the working tree. ``` Now that we have the `--last` flag, this should work for the case in which we want just to analyze the last commit, not specify a range of commits via `--from` and `--to`. Closes #3892 * fix: use --pretty=format:"%B" instead of --pretty=%B The latter adds unnecessary whitespace at the end of the commit msg. --------- Co-authored-by: Mehrshad <code.rezaei@gmail.com>
1 parent 391e8ca commit 99f4f3f

File tree

7 files changed

+56
-9
lines changed

7 files changed

+56
-9
lines changed
 

‎@commitlint/cli/src/cli.test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ test('should produce success output with --verbose flag', async () => {
5252
expect(actual.stderr).toEqual('');
5353
});
5454

55+
test('should produce last commit and success output with --verbose flag', async () => {
56+
const cwd = await gitBootstrap('fixtures/simple');
57+
await execa('git', ['add', 'commitlint.config.js'], {cwd});
58+
await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
59+
const actual = await cli(['--last', '--verbose'], {cwd})();
60+
expect(actual.stdout).toContain('0 problems, 0 warnings');
61+
expect(actual.stdout).toContain('test: this should work');
62+
expect(actual.stderr).toEqual('');
63+
});
64+
5565
test('should produce no output with --quiet flag', async () => {
5666
const cwd = await gitBootstrap('fixtures/default');
5767
const actual = await cli(['--quiet'], {cwd})('foo: bar');
@@ -529,6 +539,7 @@ test('should print help', async () => {
529539
-H, --help-url help url in error message [string]
530540
-f, --from lower end of the commit range to lint; applies if edit=false [string]
531541
--git-log-args additional git log arguments as space separated string, example '--first-parent --cherry-pick' [string]
542+
-l, --last just analyze the last commit; applies if edit=false [boolean]
532543
-o, --format output format of the results [string]
533544
-p, --parser-preset configuration preset to use for conventional-commits-parser [string]
534545
-q, --quiet toggle console output [boolean] [default: false]

‎@commitlint/cli/src/cli.ts

+25-2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ const cli = yargs(process.argv.slice(2))
9595
"additional git log arguments as space separated string, example '--first-parent --cherry-pick'",
9696
type: 'string',
9797
},
98+
last: {
99+
alias: 'l',
100+
description: 'just analyze the last commit; applies if edit=false',
101+
type: 'boolean',
102+
},
98103
format: {
99104
alias: 'o',
100105
description: 'output format of the results',
@@ -214,11 +219,25 @@ async function main(args: MainArgs): Promise<void> {
214219

215220
const fromStdin = checkFromStdin(raw, flags);
216221

222+
if (
223+
Object.hasOwn(flags, 'last') &&
224+
(Object.hasOwn(flags, 'from') || Object.hasOwn(flags, 'to') || flags.edit)
225+
) {
226+
const err = new CliError(
227+
'Please use the --last flag alone. The --last flag should not be used with --to or --from or --edit.',
228+
pkg.name
229+
);
230+
cli.showHelp('log');
231+
console.log(err.message);
232+
throw err;
233+
}
234+
217235
const input = await (fromStdin
218236
? stdin()
219237
: read({
220238
to: flags.to,
221239
from: flags.from,
240+
last: flags.last,
222241
edit: flags.edit,
223242
cwd: flags.cwd,
224243
gitLogArgs: flags['git-log-args'],
@@ -231,7 +250,7 @@ async function main(args: MainArgs): Promise<void> {
231250

232251
if (messages.length === 0 && !checkFromRepository(flags)) {
233252
const err = new CliError(
234-
'[input] is required: supply via stdin, or --env or --edit or --from and --to',
253+
'[input] is required: supply via stdin, or --env or --edit or --last or --from and --to',
235254
pkg.name
236255
);
237256
cli.showHelp('log');
@@ -374,7 +393,11 @@ function checkFromEdit(flags: CliFlags): boolean {
374393
}
375394

376395
function checkFromHistory(flags: CliFlags): boolean {
377-
return typeof flags.from === 'string' || typeof flags.to === 'string';
396+
return (
397+
typeof flags.from === 'string' ||
398+
typeof flags.to === 'string' ||
399+
typeof flags.last === 'boolean'
400+
);
378401
}
379402

380403
function normalizeFlags(flags: CliFlags): CliFlags {

‎@commitlint/cli/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface CliFlags {
99
'help-url'?: string;
1010
from?: string;
1111
'git-log-args'?: string;
12+
last?: boolean;
1213
format?: string;
1314
'parser-preset'?: string;
1415
quiet: boolean;

‎@commitlint/read/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@
3939
"@commitlint/test": "^19.0.0",
4040
"@commitlint/utils": "^19.0.0",
4141
"@types/git-raw-commits": "^2.0.3",
42-
"@types/minimist": "^1.2.4",
43-
"execa": "^8.0.1"
42+
"@types/minimist": "^1.2.4"
4443
},
4544
"dependencies": {
4645
"@commitlint/top-level": "^19.0.0",
4746
"@commitlint/types": "^19.0.3",
4847
"git-raw-commits": "^4.0.0",
49-
"minimist": "^1.2.8"
48+
"minimist": "^1.2.8",
49+
"execa": "^8.0.1"
5050
},
5151
"gitHead": "70f7f4688b51774e7ac5e40e896cdaa3f132b2bc"
5252
}

‎@commitlint/read/src/read.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ import type {GitOptions} from 'git-raw-commits';
44
import {getHistoryCommits} from './get-history-commits.js';
55
import {getEditCommit} from './get-edit-commit.js';
66

7+
import {execa} from 'execa';
8+
79
interface GetCommitMessageOptions {
810
cwd?: string;
911
from?: string;
1012
to?: string;
13+
last?: boolean;
1114
edit?: boolean | string;
1215
gitLogArgs?: string;
1316
}
@@ -16,12 +19,21 @@ interface GetCommitMessageOptions {
1619
export default async function getCommitMessages(
1720
settings: GetCommitMessageOptions
1821
): Promise<string[]> {
19-
const {cwd, from, to, edit, gitLogArgs} = settings;
22+
const {cwd, from, to, last, edit, gitLogArgs} = settings;
2023

2124
if (edit) {
2225
return getEditCommit(cwd, edit);
2326
}
2427

28+
if (last) {
29+
const executeGitCommand = await execa('git', [
30+
'log',
31+
'-1',
32+
'--pretty=format:"%B"',
33+
]);
34+
return [executeGitCommand.stdout];
35+
}
36+
2537
let gitOptions: GitOptions = {from, to};
2638
if (gitLogArgs) {
2739
gitOptions = {

‎docs/guides/ci-setup.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
4343
- name: Validate current commit (last commit) with commitlint
4444
if: github.event_name == 'push'
45-
run: npx commitlint --from HEAD~1 --to HEAD --verbose
45+
run: npx commitlint --last --verbose
4646

4747
- name: Validate PR commits with commitlint
4848
if: github.event_name == 'pull_request'

‎tsconfig.shared.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"compilerOptions": {
3-
"target": "ES2017",
4-
"lib": ["es2017"],
3+
"target": "ES2022",
4+
"lib": ["es2022"],
55
"declaration": true,
66
"declarationMap": true,
77
"sourceMap": true,

0 commit comments

Comments
 (0)
Please sign in to comment.