Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
152b182
fix(cli): added logic to accumulate lint results before formatting
harshit078 Apr 15, 2026
1930fc3
Merge branch 'main' into fix-lint-multiple-files
harshit078 Apr 15, 2026
8dcbcfb
fix(cli): updated lint test
harshit078 Apr 15, 2026
1c82361
fix: updated both lint md and added changset
harshit078 Apr 15, 2026
19092db
fix: address cursor comments
harshit078 Apr 15, 2026
1799891
Merge branch 'main' into fix-lint-multiple-files
harshit078 Apr 17, 2026
2eec3c0
Merge branch 'main' into fix-lint-multiple-files
harshit078 Apr 20, 2026
c1fa6a2
fix: comments addressed by cursor
harshit078 Apr 22, 2026
545b1a0
Merge branch 'main' into fix-lint-multiple-files
harshit078 Apr 22, 2026
a893ee5
Merge branch 'main' into fix-lint-multiple-files
harshit078 May 1, 2026
c7806a7
Merge branch 'main' into fix-lint-multiple-files
harshit078 May 6, 2026
bdef0c5
fix: address commments and simplify
harshit078 May 6, 2026
ed308eb
Merge branch 'main' into fix-lint-multiple-files
harshit078 May 6, 2026
de3b116
fix: update failing e2e tests and updated snapshots
harshit078 May 7, 2026
0c7cf32
Merge branch 'main' into fix-lint-multiple-files
harshit078 May 13, 2026
e7b4f1a
fix: address comments and undo files not needed a change
harshit078 May 19, 2026
2a2073e
fix: addressed checkstyle comment and redo logic and docs
harshit078 May 19, 2026
e9f204b
Merge branch 'main' into fix-lint-multiple-files
harshit078 May 19, 2026
bb8e8b1
Merge branch 'main' into fix-lint-multiple-files
harshit078 May 19, 2026
adb88e3
fix: linting issue in changeset and solve failing test
harshit078 May 20, 2026
889daad
Merge branch 'main' into fix-lint-multiple-files
harshit078 May 21, 2026
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
5 changes: 5 additions & 0 deletions .changeset/empty-cities-sink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@redocly/cli': patch
---

Fixed `lint --format=checkstyle` to produce a single combined XML document when multiple APIs are passed to the command, instead of concatenated per-file documents.
6 changes: 1 addition & 5 deletions docs/@v2/commands/lint.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,7 @@ However, if you have a configuration file, but it doesn't include any rules or e
### Specify output format

The standard `codeframe` output format works well in most situations, but `redocly` can also produce output to integrate with other tools.

{% admonition type="warning" name="Lint one API at a time" %}
Some formats, such as `checkstyle` or `json`, don't work well when multiple APIs are linted in a single command.
Try linting each API separately when you pass the command output to another tool.
{% /admonition %}
When multiple APIs are linted in a single command, the `checkstyle` format produces a single combined XML document with one `<file>` element per API.

#### Codeframe (default)

Expand Down
20 changes: 18 additions & 2 deletions packages/cli/src/__tests__/commands/lint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('handleLint', () => {
return {
...actual,
lint: vi.fn(async (): Promise<NormalizedProblem[]> => []),
getTotals: vi.fn(() => ({ errors: 0 }) as Totals),
getTotals: vi.fn(() => ({ errors: 0, warnings: 0, ignored: 0 }) as Totals),
doesYamlFileExist: vi.fn((path) => path === 'redocly.yaml'),
logger: {
info: vi.fn(),
Expand Down Expand Up @@ -211,13 +211,29 @@ describe('handleLint', () => {
expect(formatProblems).toHaveBeenCalledWith(['problem'], {
format: 'stylish',
maxProblems: 2,
totals: { errors: 0 },
totals: { errors: 0, warnings: 0, ignored: 0 },
version: '2.0.0',
command: 'lint',
});
expect(getExecutionTime).toHaveBeenCalledWith(42);
});

it('should aggregate problems from multiple APIs into a single formatProblems call', async () => {
vi.mocked(lint)
.mockResolvedValueOnce(['problem-a'] as any)
.mockResolvedValueOnce(['problem-b'] as any);
await commandWrapper(handleLint)({
...argvMock,
apis: ['a.yaml', 'b.yaml'],
format: 'checkstyle',
});
expect(formatProblems).toHaveBeenCalledTimes(1);
expect(formatProblems).toHaveBeenCalledWith(
['problem-a', 'problem-b'],
expect.objectContaining({ format: 'checkstyle' })
);
});

it('should catch error in handleError if something fails', async () => {
vi.mocked(lint).mockRejectedValueOnce('error');
await commandWrapper(handleLint)(argvMock);
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/src/commands/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export async function handleLint({

const totals: Totals = { errors: 0, warnings: 0, ignored: 0 };
let totalIgnored = 0;
const isCheckstyle = argv.format === 'checkstyle';
const checkstyleResults: Awaited<ReturnType<typeof lint>> = [];

// TODO: use shared externalRef resolver, blocked by preprocessors now as they can mutate documents
for (const { path, alias } of apis) {
Expand Down Expand Up @@ -93,6 +95,8 @@ export async function handleLint({
config.addIgnore(m);
totalIgnored++;
}
} else if (isCheckstyle) {
checkstyleResults.push(...results);
} else {
formatProblems(results, {
format: argv.format,
Expand All @@ -110,6 +114,16 @@ export async function handleLint({
}
}

if (isCheckstyle && !argv['generate-ignore-file']) {
formatProblems(checkstyleResults, {
format: argv.format,
maxProblems: argv['max-problems'],
totals,
version,
command: 'lint',
});
}
Comment thread
cursor[bot] marked this conversation as resolved.

if (argv['generate-ignore-file']) {
config.saveIgnore();
logger.info(`Explicitly ignored ${totalIgnored} ${pluralize('problem', totalIgnored)}.\n\n`);
Expand Down
Loading