-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathloader.ts
More file actions
97 lines (87 loc) · 2.58 KB
/
Copy pathloader.ts
File metadata and controls
97 lines (87 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import {
codeowners,
labels,
members,
org,
repos,
rulesets,
teams,
} from "@config/index";
import * as v from "valibot";
import {
CodeownersFileSchema,
type InfraConfig,
LabelGroupsSchema,
MembersFileSchema,
OrgConfigSchema,
ReposFileSchema,
RulesetsFileSchema,
TeamsFileSchema,
} from "@/types";
import { mergeTeamMemberships } from "./members";
import type { ValidationIssue } from "./types";
import { validateCrossRefs, validateMemberRefs } from "./validate";
type Schema<T> = v.BaseSchema<unknown, T, v.BaseIssue<unknown>>;
function parse<T>(schema: Schema<T>, data: unknown, file: string): T {
const { success, issues, output } = v.safeParse(schema, data);
if (!success) {
const msg = issues
.map((i) => {
const path = i.path?.map((p) => String(p.key)).join(".") ?? "root";
return `${path}: ${i.message}`;
})
.join("; ");
throw new Error(`Invalid ${file}: ${msg}`);
}
return output;
}
function reportIssues(issues: ValidationIssue[]) {
const errors = issues.filter((i) => i.severity === "error");
const warnings = issues.filter((i) => i.severity === "warning");
for (const w of warnings) {
console.warn(`config warning — ${w.path}: ${w.message}`);
}
if (errors.length > 0) {
const body = errors.map((i) => `- ${i.path}: ${i.message}`).join("\n");
throw new Error(`Config validation failed:\n${body}`);
}
}
export function loadConfig(): InfraConfig {
const labelGroups = parse(LabelGroupsSchema, labels, "labels.yaml");
const parsedOrg = parse(OrgConfigSchema, org, "org.yaml");
const { repos: parsedRepos } = parse(ReposFileSchema, repos, "repos.yaml");
const { rulesets: parsedRulesets } = parse(
RulesetsFileSchema,
rulesets,
"rulesets.yaml",
);
const parsedTeamsFile = parse(TeamsFileSchema, teams, "teams.yaml");
const parsedMembers = parse(MembersFileSchema, members, "members.yaml");
const { content: codeownersContent } = parse(
CodeownersFileSchema,
codeowners,
"codeowners.yaml",
);
const memberIssues = validateMemberRefs(parsedTeamsFile, parsedMembers);
reportIssues(memberIssues);
const parsedTeams = mergeTeamMemberships(parsedTeamsFile, parsedMembers);
const config: InfraConfig = {
org: parsedOrg,
repos: parsedRepos,
teams: parsedTeams,
rulesets: parsedRulesets,
labels: Object.assign({}, ...Object.values(labelGroups)),
codeownersContent,
};
const issues = validateCrossRefs(config, labelGroups);
reportIssues(issues);
return config;
}
export function initConfig(): InfraConfig {
try {
return loadConfig();
} catch (err) {
console.error(err instanceof Error ? err.message : String(err));
process.exit(1);
}
}