Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions src/flows/multi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ function maskFleet(
const knownVisibility = new Map<SlugKey, RepoVisibility>();
// Private slugs discovery filtered out are masked but never placeholdered.
const filteredPrivateSlugs: Private<string>[] = [];
// parseConfig refuses a bad repos list and misplaced filters before any file is read; a library caller that
// builds the config by hand meets the same refusals here.
if (cfg.reposInput) {
const parsed = yield* parseReposInput(cfg.reposInput);
if (parsed.discover) {
Expand Down
26 changes: 25 additions & 1 deletion src/flows/run-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { err, ok, type Result, safeTry } from "neverthrow";
import { LIST_SEPARATOR } from "../discovery/repos-input.js";
import { LIST_SEPARATOR, parseReposInput } from "../discovery/repos-input.js";
import { LAYERINGS } from "../engine/layers.js";
import type { Problem } from "../problem.js";
import { PRIVATE_REPORT_CHANNELS } from "../report/delivery.js";
Expand Down Expand Up @@ -96,6 +96,28 @@ function readSnapshotBase(input: Inputs, env: ConfigEnv) {
});
}

/**
* The target problems the inputs alone decide: a repos list that mixes "*" with names or carries a bad entry, and
* discovery filters set where no "*" discovery runs. Refused here, before any file is read, so an unreadable
* repos-dir cannot hide them; resolveTargets meets the same problems for a library caller that builds the config
* by hand.
*/
function refuseTargetInputs(
reposInput: string,
discoveryFiltersSet: readonly string[],
): Result<void, Problem> {
const filtersWithout = (targets: "explicit-repos" | "repos-dir"): Result<void, Problem> =>
discoveryFiltersSet.length > 0
? err({ code: "discovery-filters-without-wildcard", filters: discoveryFiltersSet, targets })
: ok(undefined);
if (!reposInput) {
return filtersWithout("repos-dir");
}
return parseReposInput(reposInput).andThen((parsed) =>
parsed.discover ? ok(undefined) : filtersWithout("explicit-repos"),
);
}

/** The file arm: one repository, the fleet inputs refused. */
function parseSnapshotFileArm(
input: Inputs,
Expand Down Expand Up @@ -175,6 +197,7 @@ function parseSnapshotConfig(
if (!reposInput && !reposDir) {
return err({ code: "input-snapshot-dir-without-targets" });
}
yield* refuseTargetInputs(reposInput, filters.discoveryFiltersSet);
return ok({
...base,
form: "dir" as const,
Expand Down Expand Up @@ -276,6 +299,7 @@ export function parseConfig(
if (settingsFile !== DEFAULT_SETTINGS_FILE) {
return err({ code: "input-settings-file-with-multi" });
}
yield* refuseTargetInputs(reposInput, discoveryFiltersSet);
const adminOwner = githubRepository.split("/")[0] ?? "";
return ok({
...common,
Expand Down
38 changes: 38 additions & 0 deletions test/flows/inputs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,3 +553,41 @@ describe("mode: snapshot", () => {
);
});
});

describe("target inputs the file system cannot change", () => {
// Before, these were refused inside resolveTargets after the repos directory was read, so an unreadable directory
// reported itself and hid the input error; parseConfig never touches the directory.
const FLEET = { GITHUB_REPOSITORY: "admin/fleet" };
test.each<[string, Partial<Record<InputName, string>>, Problem]>([
[
"a repos list mixing * with names",
{ repos: "*,o/r" },
{ code: "repos-input-wildcard-mixed" },
],
[
"a repos list with a bad entry",
{ repos: "o/r,not-a-slug" },
{ code: "repos-input-invalid-entries", invalid: ["not-a-slug"], duplicated: [] },
],
[
"discovery filters beside explicit repos",
{ repos: "o/r", forks: "exclude" },
{ code: "discovery-filters-without-wildcard", filters: ["forks"], targets: "explicit-repos" },
],
[
"discovery filters beside repos-dir alone",
{ "repos-dir": "repos", forks: "exclude" },
{ code: "discovery-filters-without-wildcard", filters: ["forks"], targets: "repos-dir" },
],
])(
"%s is refused when the inputs are parsed, for apply and for a snapshot dir",
(_case, inputs, problem) => {
expect(rejection(parse({ token: "t", ...inputs }, FLEET))).toEqual(problem);
expect(
rejection(
parse({ token: "t", mode: "snapshot", "snapshot-dir": "snaps", ...inputs }, FLEET),
),
).toEqual(problem);
},
);
});
Loading