Files
renovate/lib/modules/platform/github/schema.ts
Sebastian Poxhofer b2d3b64c48 refactor(lint): enforce err key for errors in logger metadata (#45759)
* refactor(lint): enforce err key for errors in logger metadata

* refactor(lint): flag error message and stack strings in logger-err-key
2026-09-09 13:55:14 +00:00

186 lines
4.7 KiB
TypeScript

import { z } from 'zod/v4';
import { logger } from '../../../logger/index.ts';
import {
DeepNullish,
LooseArray,
Nullish,
} from '../../../util/schema-utils/index.ts';
const Ecosystem = z.enum([
'actions',
'composer',
'go',
'maven',
'npm',
'nuget',
'pip',
'rubygems',
'rust',
]);
export type Ecosystem = z.infer<typeof Ecosystem>;
const Package = z.object({
ecosystem: Ecosystem.catch((ctx) => {
logger.debug(
{ ecosystem: ctx.input },
'Skipping vulnerability alert with unsupported ecosystem',
);
return undefined as any;
}),
name: z.string(),
});
const Severity = z.enum(['low', 'medium', 'high', 'critical']);
const SecurityVulnerability = z
.object({
first_patched_version: Nullish(z.object({ identifier: z.string() })),
package: Package,
severity: Severity,
vulnerable_version_range: z.string(),
})
.nullable();
const CvssSeverity = z.object({
vector_string: z.string().nullable(),
score: z.number().nullable(),
});
const SecurityAdvisory = z.object({
ghsa_id: z.string(),
summary: z.string(),
description: z.string(),
identifiers: z.array(
z.object({
type: z.string(),
value: z.string(),
}),
),
references: z.array(z.object({ url: z.string() })).optional(),
severity: Severity,
cvss_severities: Nullish(
DeepNullish(
z.object({
cvss_v3: CvssSeverity.optional(),
cvss_v4: CvssSeverity.optional(),
}),
),
),
});
export type SecurityAdvisory = z.infer<typeof SecurityAdvisory>;
export const GithubVulnerabilityAlerts = LooseArray(
z.object({
dismissed_reason: Nullish(z.string()),
security_advisory: SecurityAdvisory,
security_vulnerability: SecurityVulnerability,
dependency: z.object({
manifest_path: z.string(),
}),
}),
{
onError: ({ error }) => {
logger.debug(
{ err: error },
'Vulnerability Alert: Failed to parse some alerts',
);
},
},
).transform((alerts) =>
alerts.filter((alert) => alert.security_vulnerability?.package?.ecosystem),
);
export type GithubVulnerabilityAlerts = z.infer<
typeof GithubVulnerabilityAlerts
>;
export type GithubVulnerabilityAlert = GithubVulnerabilityAlerts[number];
// https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#get-repository-content
const GithubResponseMetadata = z.object({
name: z.string(),
path: z.string(),
});
export const GithubFileMeta = GithubResponseMetadata.extend({
type: z.literal('file'),
});
export type GithubFileMeta = z.infer<typeof GithubFileMeta>;
export const GithubFile = GithubFileMeta.extend({
content: z.string(),
encoding: z.string(),
});
export type GithubFile = z.infer<typeof GithubFile>;
export const GithubDirectory = GithubResponseMetadata.extend({
type: z.literal('dir'),
});
export type GithubDirectory = z.infer<typeof GithubDirectory>;
export const GithubOtherContent = GithubResponseMetadata.extend({
type: z.literal('symlink').or(z.literal('submodule')),
});
export type GithubOtherContent = z.infer<typeof GithubOtherContent>;
export const GithubElement = GithubFile.or(GithubFileMeta)
.or(GithubDirectory)
.or(GithubOtherContent);
export type GithubElement = z.infer<typeof GithubElement>;
export const GithubContentResponse = z.array(GithubElement).or(GithubElement);
export const GithubBranchProtection = z.object({
required_status_checks: Nullish(
z.object({
strict: z.boolean(),
}),
),
});
export type GithubBranchProtection = z.infer<typeof GithubBranchProtection>;
const GithubRulesetRule = z.discriminatedUnion('type', [
z.object({
type: z.literal('non_fast_forward'),
}),
z.object({
type: z.literal('required_status_checks'),
parameters: z.object({
strict_required_status_checks_policy: z.boolean().optional(),
}),
}),
// prevents deletion
z.object({
type: z.literal('deletion'),
}),
]);
export const GithubBranchRulesets = LooseArray(GithubRulesetRule);
export type GithubBranchRulesets = z.infer<typeof GithubBranchRulesets>;
const GithubIssueBase = z.object({
number: z.number(),
state: z.string().transform((val) => val.toLowerCase()),
title: z.string(),
body: z.string(),
});
const GithubGraphqlIssue = GithubIssueBase.extend({
updatedAt: z.string(),
}).transform((issue) => {
const lastModified = issue.updatedAt;
const { number, state, title, body } = issue;
return { number, state, title, body, lastModified };
});
const GithubRestIssue = GithubIssueBase.extend({
updated_at: z.string(),
}).transform((issue) => {
const lastModified = issue.updated_at;
const { number, state, title, body } = issue;
return { number, state, title, body, lastModified };
});
export const GithubIssue = z.union([GithubGraphqlIssue, GithubRestIssue]);
export type GithubIssue = z.infer<typeof GithubIssue>;