mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-26 07:20:39 +00:00
00043d193e
* ci(linter): add renovate/codeblock-in-spec-fixtures rule Add a custom oxlint rule that requires the codeBlock (or stripIndent) template helper from common-tags for multi-line string fixtures in spec files (enabled for **/*.spec.ts and test/** only). The rule only flags shapes whose value can round-trip through the common-tags helpers unchanged, since both codeBlock and stripIndent trim the end result and strip the shortest line indentation: - only literals spanning multiple source lines are flagged (escaped \n one-liners are left alone: tagging them is not value-preserving in general and gains nothing) - values with leading/trailing whitespace (e.g. fixtures ending in a newline) are not flagged - tagged templates, describe/it titles, and inline snapshot arguments are skipped All 55 pre-existing violations (22 files) were fixed with a one-off codemod that re-emits each fixture indented to the statement depth and verifies value preservation by evaluating codeBlock on the rewritten template (substitutions kept as opaque placeholders). One site (pip_requirements/artifacts.spec.ts) mixes line continuations with escaped newlines and was tagged verbatim instead of re-indented. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(linter): address review findings Make getSimpleRequirementsFile in pip-compile/extract.spec.ts value-preserving again: tagging the whole template with codeBlock trimmed the trailing blank line when deps is empty (the headerOnly.txt case), silently changing the fixture from ending in '#\n\n' to '#'. Tag only the static header and append the deps section via a single-line template, which reproduces the original string exactly for both empty and non-empty deps (verified by executing old vs new in node). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
109 lines
3.4 KiB
TypeScript
109 lines
3.4 KiB
TypeScript
import { codeBlock } from 'common-tags';
|
|
import { Fixtures } from '~test/fixtures.ts';
|
|
import { GlobalConfig } from '../../../config/global.ts';
|
|
import { extractPackageFile } from './index.ts';
|
|
|
|
const yamlFileMultiConfig = Fixtures.get('gitlab-ci.1.yaml');
|
|
const yamlFileSingleConfig = Fixtures.get('gitlab-ci.2.yaml');
|
|
const yamlWithEmptyIncludeConfig = Fixtures.get('gitlab-ci.3.yaml');
|
|
const yamlWithTriggerRef = Fixtures.get('gitlab-ci.4.yaml');
|
|
|
|
describe('modules/manager/gitlabci-include/extract', () => {
|
|
describe('extractPackageFile()', () => {
|
|
it('returns null for empty', () => {
|
|
expect(extractPackageFile('nothing here')).toBeNull();
|
|
});
|
|
|
|
it('returns null for include block without any actual includes', () => {
|
|
const res = extractPackageFile(yamlWithEmptyIncludeConfig);
|
|
expect(res).toBeNull();
|
|
});
|
|
|
|
it('extracts single include block', () => {
|
|
const res = extractPackageFile(yamlFileSingleConfig);
|
|
expect(res?.deps).toMatchSnapshot();
|
|
expect(res?.deps).toHaveLength(1);
|
|
});
|
|
|
|
it('extracts multiple include blocks', () => {
|
|
const res = extractPackageFile(yamlFileMultiConfig);
|
|
expect(res?.deps).toMatchSnapshot();
|
|
expect(res?.deps).toHaveLength(3);
|
|
});
|
|
|
|
it('extracts multiple embedded include blocks', () => {
|
|
const res = extractPackageFile(yamlWithTriggerRef);
|
|
expect(res?.deps).toHaveLength(2);
|
|
expect(res?.deps).toMatchObject([
|
|
{
|
|
currentValue: 'master',
|
|
datasource: 'gitlab-tags',
|
|
depName: 'mikebryant/include-source-example',
|
|
},
|
|
{
|
|
currentValue: '1.0.0',
|
|
datasource: 'gitlab-tags',
|
|
depName: 'mikebryant/include-source-example',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('ignores includes without project and file keys', () => {
|
|
const includeWithoutProjectRef = codeBlock`
|
|
include:
|
|
- 'https://gitlab.com/mikebryant/include-source-example.yml'
|
|
- remote: 'https://gitlab.com/mikebryant/include-source-example.yml'
|
|
- local: mikebryant/include-source-example
|
|
`;
|
|
const res = extractPackageFile(includeWithoutProjectRef);
|
|
expect(res).toBeNull();
|
|
});
|
|
|
|
it('normalizes configured endpoints', () => {
|
|
const endpoints = [
|
|
'http://gitlab.test/api/v4',
|
|
'http://gitlab.test/api/v4/',
|
|
];
|
|
|
|
for (const endpoint of endpoints) {
|
|
GlobalConfig.set({ platform: 'gitlab', endpoint });
|
|
const res = extractPackageFile(yamlFileMultiConfig);
|
|
expect(res?.deps[0].registryUrls).toEqual(['http://gitlab.test']);
|
|
}
|
|
});
|
|
|
|
it('supports multi-document files', () => {
|
|
const multiDocFile = codeBlock`
|
|
other:
|
|
content: to be ignored
|
|
---
|
|
include:
|
|
- project: mikebryant/include-source-example
|
|
ref: 1.0.0
|
|
---
|
|
include:
|
|
- project: mikebryant/include-source-example2
|
|
ref: 2.0.0
|
|
---
|
|
more:
|
|
content: to be ignored
|
|
`;
|
|
const res = extractPackageFile(multiDocFile);
|
|
expect(res).toMatchObject({
|
|
deps: [
|
|
{
|
|
currentValue: '1.0.0',
|
|
datasource: 'gitlab-tags',
|
|
depName: 'mikebryant/include-source-example',
|
|
},
|
|
{
|
|
currentValue: '2.0.0',
|
|
datasource: 'gitlab-tags',
|
|
depName: 'mikebryant/include-source-example2',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
});
|