Skip to content

Commit

Permalink
feat(cli): introduce new --last flag, to stop recommending HEAD~1 (#3916
Browse files Browse the repository at this point in the history
)

* 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>
  • Loading branch information
knocte and Mersho authored Mar 14, 2024
1 parent 391e8ca commit 99f4f3f
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 9 deletions.
11 changes: 11 additions & 0 deletions @commitlint/cli/src/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ test('should produce success output with --verbose flag', async () => {
expect(actual.stderr).toEqual('');
});

test('should produce last commit and success output with --verbose flag', async () => {
const cwd = await gitBootstrap('fixtures/simple');
await execa('git', ['add', 'commitlint.config.js'], {cwd});
await execa('git', ['commit', '-m', '"test: this should work"'], {cwd});
const actual = await cli(['--last', '--verbose'], {cwd})();
expect(actual.stdout).toContain('0 problems, 0 warnings');
expect(actual.stdout).toContain('test: this should work');
expect(actual.stderr).toEqual('');
});

test('should produce no output with --quiet flag', async () => {
const cwd = await gitBootstrap('fixtures/default');
const actual = await cli(['--quiet'], {cwd})('foo: bar');
Expand Down Expand Up @@ -529,6 +539,7 @@ test('should print help', async () => {
-H, --help-url help url in error message [string]
-f, --from lower end of the commit range to lint; applies if edit=false [string]
--git-log-args additional git log arguments as space separated string, example '--first-parent --cherry-pick' [string]
-l, --last just analyze the last commit; applies if edit=false [boolean]
-o, --format output format of the results [string]
-p, --parser-preset configuration preset to use for conventional-commits-parser [string]
-q, --quiet toggle console output [boolean] [default: false]
Expand Down
27 changes: 25 additions & 2 deletions @commitlint/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ const cli = yargs(process.argv.slice(2))
"additional git log arguments as space separated string, example '--first-parent --cherry-pick'",
type: 'string',
},
last: {
alias: 'l',
description: 'just analyze the last commit; applies if edit=false',
type: 'boolean',
},
format: {
alias: 'o',
description: 'output format of the results',
Expand Down Expand Up @@ -214,11 +219,25 @@ async function main(args: MainArgs): Promise<void> {

const fromStdin = checkFromStdin(raw, flags);

if (
Object.hasOwn(flags, 'last') &&
(Object.hasOwn(flags, 'from') || Object.hasOwn(flags, 'to') || flags.edit)
) {
const err = new CliError(
'Please use the --last flag alone. The --last flag should not be used with --to or --from or --edit.',
pkg.name
);
cli.showHelp('log');
console.log(err.message);
throw err;
}

const input = await (fromStdin
? stdin()
: read({
to: flags.to,
from: flags.from,
last: flags.last,
edit: flags.edit,
cwd: flags.cwd,
gitLogArgs: flags['git-log-args'],
Expand All @@ -231,7 +250,7 @@ async function main(args: MainArgs): Promise<void> {

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

function checkFromHistory(flags: CliFlags): boolean {
return typeof flags.from === 'string' || typeof flags.to === 'string';
return (
typeof flags.from === 'string' ||
typeof flags.to === 'string' ||
typeof flags.last === 'boolean'
);
}

function normalizeFlags(flags: CliFlags): CliFlags {
Expand Down
1 change: 1 addition & 0 deletions @commitlint/cli/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface CliFlags {
'help-url'?: string;
from?: string;
'git-log-args'?: string;
last?: boolean;
format?: string;
'parser-preset'?: string;
quiet: boolean;
Expand Down
6 changes: 3 additions & 3 deletions @commitlint/read/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@
"@commitlint/test": "^19.0.0",
"@commitlint/utils": "^19.0.0",
"@types/git-raw-commits": "^2.0.3",
"@types/minimist": "^1.2.4",
"execa": "^8.0.1"
"@types/minimist": "^1.2.4"
},
"dependencies": {
"@commitlint/top-level": "^19.0.0",
"@commitlint/types": "^19.0.3",
"git-raw-commits": "^4.0.0",
"minimist": "^1.2.8"
"minimist": "^1.2.8",
"execa": "^8.0.1"
},
"gitHead": "70f7f4688b51774e7ac5e40e896cdaa3f132b2bc"
}
14 changes: 13 additions & 1 deletion @commitlint/read/src/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import type {GitOptions} from 'git-raw-commits';
import {getHistoryCommits} from './get-history-commits.js';
import {getEditCommit} from './get-edit-commit.js';

import {execa} from 'execa';

interface GetCommitMessageOptions {
cwd?: string;
from?: string;
to?: string;
last?: boolean;
edit?: boolean | string;
gitLogArgs?: string;
}
Expand All @@ -16,12 +19,21 @@ interface GetCommitMessageOptions {
export default async function getCommitMessages(
settings: GetCommitMessageOptions
): Promise<string[]> {
const {cwd, from, to, edit, gitLogArgs} = settings;
const {cwd, from, to, last, edit, gitLogArgs} = settings;

if (edit) {
return getEditCommit(cwd, edit);
}

if (last) {
const executeGitCommand = await execa('git', [
'log',
'-1',
'--pretty=format:"%B"',
]);
return [executeGitCommand.stdout];
}

let gitOptions: GitOptions = {from, to};
if (gitLogArgs) {
gitOptions = {
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/ci-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Validate current commit (last commit) with commitlint
if: github.event_name == 'push'
run: npx commitlint --from HEAD~1 --to HEAD --verbose
run: npx commitlint --last --verbose

- name: Validate PR commits with commitlint
if: github.event_name == 'pull_request'
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.shared.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["es2017"],
"target": "ES2022",
"lib": ["es2022"],
"declaration": true,
"declarationMap": true,
"sourceMap": true,
Expand Down

0 comments on commit 99f4f3f

Please sign in to comment.