mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-25 23:11:31 +00:00
1ea8602aaa
* test(manager): cover twelve else-if branches The trailing `else if` of a chain leaves v8 counting an implicit else that no coverage-ignore hint can suppress. Fourteen of those were marked as structurally unreachable, but only two of them actually are -- each of these twelve has an input that takes it: - `bazel`: an archive url whose file name is only a suffix, which strips to an empty value, so neither value nor digest is set - `cargo`: a `[package]` section with no `version` at all - `composer`: an inline `package` repository, which the discriminated union does carry, contrary to the comment that claimed otherwise - `deps-edn`: an `:mvn/repos` entry whose spec is a plain string - `gomod`: an update where only the `go` directive changed, leaving no additional dependencies to count - `helmfile`: a release with an empty chart name, which is neither a local path nor an oci ref and yields an empty repo name - `nuget`: a lock file that is gone after the restore - `swift`: a comma where `from` expects a colon, and where `from:` expects a version -- both are labels the state machine searches for and then ignores - `terraform`: a module source too short to be a registry module - `tflint-plugin`: a quoted attribute that is neither version nor source - `travis`: a matrix `node_js` that is a number The stale comments go with them. Three more in `swift` were already wrong before this change: the branches they described were covered. Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io> * refactor(manager): collapse two exhaustive else-if chains `glasskube` and `gradle` were the only two of the fourteen trailing `else if` branches that really are unreachable, and both are provable from a type rather than from a reading of the surrounding code: - `glasskube` parses resources with a schema that admits exactly `Package`, `ClusterPackage` and `PackageRepository`, and filters anything else out - `gradle`'s `ContentDescriptorSpec.mode` is `'include' | 'exclude'` Turning the final `else if` into a plain `else` drops the phantom branch v8 was counting. With these, the manager tree reaches 100% branch coverage. The glasskube check is inverted so that the single-literal discriminant narrows for the compiler. Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io> * test(manager/travis): inline the numeric node_js fixture The three-line fixture went into `__fixtures__` only because every other fixture in this spec is loaded through `Fixtures.get`. A reader of the test should be able to see the input without opening a second file, so write it inline with `codeBlock`. Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io> --------- Co-authored-by: Claude Opus 5 <michael.kriese+claude-code@mend.io>
90 lines
2.7 KiB
TypeScript
90 lines
2.7 KiB
TypeScript
import { isString } from '@sindresorhus/is';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import { coerceArray } from '../../../util/array.ts';
|
|
import { regEx } from '../../../util/regex.ts';
|
|
import { GithubReleasesDatasource } from '../../datasource/github-releases/index.ts';
|
|
import type { PackageDependency } from '../types.ts';
|
|
import type { ExtractionResult } from './types.ts';
|
|
import { keyValueExtractionRegex } from './util.ts';
|
|
|
|
export function extractTFLintPlugin(
|
|
startingLine: number,
|
|
lines: string[],
|
|
// TODO: remove unused parameter
|
|
_pluginName: string,
|
|
): ExtractionResult {
|
|
let lineNumber = startingLine;
|
|
const deps: PackageDependency[] = [];
|
|
|
|
let pluginSource: string | null = null;
|
|
let currentVersion: string | null = null;
|
|
|
|
let braceCounter = 0;
|
|
do {
|
|
// istanbul ignore if
|
|
if (lineNumber > lines.length - 1) {
|
|
logger.debug(`Malformed TFLint configuration file detected.`);
|
|
}
|
|
|
|
const line = lines[lineNumber];
|
|
|
|
// istanbul ignore else
|
|
if (isString(line)) {
|
|
// `{` will be counted with +1 and `}` with -1.
|
|
// Therefore if we reach braceCounter == 0 then we found the end of the tflint configuration block.
|
|
const openBrackets = coerceArray(line.match(regEx(/\{/g))).length;
|
|
const closedBrackets = coerceArray(line.match(regEx(/\}/g))).length;
|
|
braceCounter = braceCounter + openBrackets - closedBrackets;
|
|
|
|
// only update fields inside the root block
|
|
if (braceCounter === 1) {
|
|
const kvMatch = keyValueExtractionRegex.exec(line);
|
|
if (kvMatch?.groups) {
|
|
if (kvMatch.groups.key === 'version') {
|
|
currentVersion = kvMatch.groups.value;
|
|
} else if (kvMatch.groups.key === 'source') {
|
|
pluginSource = kvMatch.groups.value;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// stop - something went wrong
|
|
braceCounter = 0;
|
|
}
|
|
lineNumber += 1;
|
|
} while (braceCounter !== 0);
|
|
|
|
const dep = analyseTFLintPlugin(pluginSource, currentVersion);
|
|
deps.push(dep);
|
|
|
|
// remove last lineNumber addition to not skip a line after the last bracket
|
|
lineNumber -= 1;
|
|
return { lineNumber, dependencies: deps };
|
|
}
|
|
|
|
function analyseTFLintPlugin(
|
|
source: string | null,
|
|
version: string | null,
|
|
): PackageDependency {
|
|
const dep: PackageDependency = {};
|
|
|
|
if (source) {
|
|
dep.depType = 'plugin';
|
|
|
|
const sourceParts = source.split('/');
|
|
if (sourceParts[0] === 'github.com') {
|
|
dep.currentValue = version;
|
|
dep.datasource = GithubReleasesDatasource.id;
|
|
dep.depName = sourceParts.slice(1).join('/');
|
|
} else {
|
|
dep.skipReason = 'unsupported-datasource';
|
|
dep.depName = source;
|
|
}
|
|
} else {
|
|
logger.debug({ dep }, 'tflint plugin has no source');
|
|
dep.skipReason = 'no-source';
|
|
}
|
|
|
|
return dep;
|
|
}
|