mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 15:26:20 +00:00
Address greptile comments
This commit is contained in:
@@ -9,16 +9,6 @@ const versionSchema = z
|
|||||||
.min(1)
|
.min(1)
|
||||||
.max(50)
|
.max(50)
|
||||||
.regex(new RE2(/^[a-zA-Z0-9._/-]+$/), "Invalid version format");
|
.regex(new RE2(/^[a-zA-Z0-9._/-]+$/), "Invalid version format");
|
||||||
const booleanSchema = z.boolean().default(false);
|
|
||||||
const queryBooleanSchema = z
|
|
||||||
.union([z.boolean(), z.string()])
|
|
||||||
.transform((val) => {
|
|
||||||
if (typeof val === "string") {
|
|
||||||
return val === "true" || val === "1";
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
})
|
|
||||||
.default(false);
|
|
||||||
|
|
||||||
export const registerUpgradePathRouter = async (server: FastifyZodProvider) => {
|
export const registerUpgradePathRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
@@ -28,9 +18,6 @@ export const registerUpgradePathRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: publicEndpointLimit
|
rateLimit: publicEndpointLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
querystring: z.object({
|
|
||||||
includePrerelease: queryBooleanSchema
|
|
||||||
}),
|
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
versions: z.array(
|
versions: z.array(
|
||||||
@@ -47,8 +34,7 @@ export const registerUpgradePathRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
try {
|
try {
|
||||||
const { includePrerelease } = req.query;
|
const versions = await req.server.services.upgradePath.getGitHubReleases();
|
||||||
const versions = await req.server.services.upgradePath.getGitHubReleases(includePrerelease);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
versions
|
versions
|
||||||
@@ -72,8 +58,7 @@ export const registerUpgradePathRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
fromVersion: versionSchema,
|
fromVersion: versionSchema,
|
||||||
toVersion: versionSchema,
|
toVersion: versionSchema
|
||||||
includePrerelease: booleanSchema
|
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -112,15 +97,9 @@ export const registerUpgradePathRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
try {
|
try {
|
||||||
const { fromVersion, toVersion, includePrerelease } = req.body;
|
const { fromVersion, toVersion } = req.body;
|
||||||
|
|
||||||
req.log.info({ fromVersion, toVersion, includePrerelease }, "Calculating upgrade path");
|
const result = await req.server.services.upgradePath.calculateUpgradePath(fromVersion, toVersion);
|
||||||
|
|
||||||
const result = await req.server.services.upgradePath.calculateUpgradePath(
|
|
||||||
fromVersion,
|
|
||||||
toVersion,
|
|
||||||
includePrerelease
|
|
||||||
);
|
|
||||||
|
|
||||||
req.log.info(
|
req.log.info(
|
||||||
{ pathLength: result.path.length, hasBreaking: result.breakingChanges.length > 0 },
|
{ pathLength: result.path.length, hasBreaking: result.breakingChanges.length > 0 },
|
||||||
|
|||||||
@@ -19,17 +19,15 @@ const versionSchema = z
|
|||||||
.min(1)
|
.min(1)
|
||||||
.max(50)
|
.max(50)
|
||||||
.regex(new RE2(/^[a-zA-Z0-9._/-]+$/), "Invalid version format");
|
.regex(new RE2(/^[a-zA-Z0-9._/-]+$/), "Invalid version format");
|
||||||
const booleanSchema = z.boolean().default(false);
|
|
||||||
|
|
||||||
interface CalculateUpgradePathParams {
|
interface CalculateUpgradePathParams {
|
||||||
fromVersion: string;
|
fromVersion: string;
|
||||||
toVersion: string;
|
toVersion: string;
|
||||||
includePrerelease?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFactory) => {
|
export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFactory) => {
|
||||||
const getGitHubReleases = async (includePrerelease = false): Promise<FormattedRelease[]> => {
|
const getGitHubReleases = async (): Promise<FormattedRelease[]> => {
|
||||||
const cacheKey = `upgrade-path:releases:${includePrerelease}`;
|
const cacheKey = "upgrade-path:releases";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const cached = await keyStore.getItem(cacheKey);
|
const cached = await keyStore.getItem(cacheKey);
|
||||||
@@ -39,7 +37,7 @@ export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFacto
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const releases = await fetchReleases(booleanSchema.parse(includePrerelease));
|
const releases = await fetchReleases(false);
|
||||||
|
|
||||||
const filteredReleases = releases.filter((v) => !v.tagName.includes("nightly"));
|
const filteredReleases = releases.filter((v) => !v.tagName.includes("nightly"));
|
||||||
|
|
||||||
@@ -62,13 +60,19 @@ export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFacto
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const yamlPath = path.join(__dirname, "..", "..", "..", "upgrade-path.yaml");
|
const yamlPath = path.join(__dirname, "..", "..", "..", "upgrade-path.yaml");
|
||||||
|
const resolvedPath = path.resolve(yamlPath);
|
||||||
|
const expectedBaseDir = path.resolve(__dirname, "..", "..", "..");
|
||||||
|
if (!resolvedPath.startsWith(expectedBaseDir)) {
|
||||||
|
throw new Error("Invalid configuration file path");
|
||||||
|
}
|
||||||
|
|
||||||
const yamlContent = await readFile(yamlPath, "utf8");
|
const yamlContent = await readFile(yamlPath, "utf8");
|
||||||
|
|
||||||
if (yamlContent.length > 1024 * 1024) {
|
if (yamlContent.length > 1024 * 1024) {
|
||||||
throw new Error("Config file too large");
|
throw new Error("Config file too large");
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = yaml.load(yamlContent) as UpgradePathConfig;
|
const config = yaml.load(yamlContent, { schema: yaml.FAILSAFE_SCHEMA }) as UpgradePathConfig;
|
||||||
const versionConfig = config?.versions || {};
|
const versionConfig = config?.versions || {};
|
||||||
|
|
||||||
await keyStore.setItemWithExpiry(cacheKey, 24 * 60 * 60, JSON.stringify(versionConfig));
|
await keyStore.setItemWithExpiry(cacheKey, 24 * 60 * 60, JSON.stringify(versionConfig));
|
||||||
@@ -85,7 +89,8 @@ export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFacto
|
|||||||
|
|
||||||
const normalizeVersion = (version: string): string => {
|
const normalizeVersion = (version: string): string => {
|
||||||
// Extract just the X.X.X.X part from any version format
|
// Extract just the X.X.X.X part from any version format
|
||||||
const versionMatch = version.match(/(\d+\.\d+\.\d+(?:\.\d+)?)/);
|
const versionRegex = new RE2(/(\d+\.\d+\.\d+(?:\.\d+)?)/);
|
||||||
|
const versionMatch = version.match(versionRegex);
|
||||||
if (versionMatch) {
|
if (versionMatch) {
|
||||||
return versionMatch[1];
|
return versionMatch[1];
|
||||||
}
|
}
|
||||||
@@ -122,7 +127,7 @@ export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFacto
|
|||||||
};
|
};
|
||||||
|
|
||||||
const validateParams = (params: CalculateUpgradePathParams) => {
|
const validateParams = (params: CalculateUpgradePathParams) => {
|
||||||
const { fromVersion, toVersion, includePrerelease = false } = params;
|
const { fromVersion, toVersion } = params;
|
||||||
|
|
||||||
versionSchema.parse(fromVersion);
|
versionSchema.parse(fromVersion);
|
||||||
versionSchema.parse(toVersion);
|
versionSchema.parse(toVersion);
|
||||||
@@ -135,12 +140,12 @@ export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFacto
|
|||||||
throw new Error("Nightly releases are not supported for upgrade path calculation");
|
throw new Error("Nightly releases are not supported for upgrade path calculation");
|
||||||
}
|
}
|
||||||
|
|
||||||
return { fromVersion, toVersion, includePrerelease: booleanSchema.parse(includePrerelease) };
|
return { fromVersion, toVersion };
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateUpgradePath = async (params: CalculateUpgradePathParams): Promise<UpgradePathResult> => {
|
const calculateUpgradePath = async (params: CalculateUpgradePathParams): Promise<UpgradePathResult> => {
|
||||||
const { fromVersion, toVersion, includePrerelease } = validateParams(params);
|
const { fromVersion, toVersion } = validateParams(params);
|
||||||
const cacheKey = `upgrade-path:${fromVersion}:${toVersion}:${includePrerelease}`;
|
const cacheKey = `upgrade-path:${fromVersion}:${toVersion}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const cached = await keyStore.getItem(cacheKey);
|
const cached = await keyStore.getItem(cacheKey);
|
||||||
@@ -149,7 +154,7 @@ export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFacto
|
|||||||
// Cache miss, continue to fetch from source
|
// Cache miss, continue to fetch from source
|
||||||
}
|
}
|
||||||
|
|
||||||
const [releases, config] = await Promise.all([getGitHubReleases(includePrerelease), getUpgradePathConfig()]);
|
const [releases, config] = await Promise.all([getGitHubReleases(), getUpgradePathConfig()]);
|
||||||
|
|
||||||
const cleanFrom = normalizeVersion(fromVersion);
|
const cleanFrom = normalizeVersion(fromVersion);
|
||||||
const cleanTo = normalizeVersion(toVersion);
|
const cleanTo = normalizeVersion(toVersion);
|
||||||
@@ -264,7 +269,6 @@ export const upgradePathServiceFactory = ({ keyStore }: TUpgradePathServiceFacto
|
|||||||
return {
|
return {
|
||||||
getGitHubReleases,
|
getGitHubReleases,
|
||||||
getUpgradePathConfig,
|
getUpgradePathConfig,
|
||||||
calculateUpgradePath: (fromVersion: string, toVersion: string, includePrerelease = false) =>
|
calculateUpgradePath: (fromVersion: string, toVersion: string) => calculateUpgradePath({ fromVersion, toVersion })
|
||||||
calculateUpgradePath({ fromVersion, toVersion, includePrerelease })
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,2 @@
|
|||||||
export type {
|
export type { CalculateUpgradePathParams, GitHubVersion, UpgradePathResult } from "./queries";
|
||||||
CalculateUpgradePathParams,
|
|
||||||
GetUpgradePathVersionsParams,
|
|
||||||
GitHubVersion,
|
|
||||||
UpgradePathResult
|
|
||||||
} from "./queries";
|
|
||||||
export { useCalculateUpgradePath, useGetUpgradePathVersions } from "./queries";
|
export { useCalculateUpgradePath, useGetUpgradePathVersions } from "./queries";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
|
import { useMutation, useQuery, UseQueryOptions } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
@@ -35,36 +35,26 @@ export interface UpgradePathResult {
|
|||||||
config: Record<string, unknown>;
|
config: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetUpgradePathVersionsParams {
|
|
||||||
includePrerelease?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CalculateUpgradePathParams {
|
export interface CalculateUpgradePathParams {
|
||||||
fromVersion: string;
|
fromVersion: string;
|
||||||
toVersion: string;
|
toVersion: string;
|
||||||
includePrerelease?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const upgradePathKeys = {
|
const upgradePathKeys = {
|
||||||
all: ["upgrade-path"] as const,
|
all: ["upgrade-path"] as const,
|
||||||
versions: (params: GetUpgradePathVersionsParams) =>
|
versions: () => [...upgradePathKeys.all, "versions"] as const,
|
||||||
[...upgradePathKeys.all, "versions", params] as const,
|
|
||||||
calculate: (params: CalculateUpgradePathParams) =>
|
calculate: (params: CalculateUpgradePathParams) =>
|
||||||
[...upgradePathKeys.all, "calculate", params] as const
|
[...upgradePathKeys.all, "calculate", params] as const
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetUpgradePathVersions = (
|
export const useGetUpgradePathVersions = (
|
||||||
params: GetUpgradePathVersionsParams,
|
|
||||||
options?: Omit<UseQueryOptions<{ versions: GitHubVersion[] }>, "queryKey" | "queryFn">
|
options?: Omit<UseQueryOptions<{ versions: GitHubVersion[] }>, "queryKey" | "queryFn">
|
||||||
) => {
|
) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: upgradePathKeys.versions(params),
|
queryKey: upgradePathKeys.versions(),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await apiRequest.get<{ versions: GitHubVersion[] }>(
|
const { data } = await apiRequest.get<{ versions: GitHubVersion[] }>(
|
||||||
"/api/v1/upgrade-path/versions",
|
"/api/v1/upgrade-path/versions"
|
||||||
{
|
|
||||||
params
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
@@ -73,11 +63,13 @@ export const useGetUpgradePathVersions = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useCalculateUpgradePath = () => {
|
export const useCalculateUpgradePath = () => {
|
||||||
return async (params: CalculateUpgradePathParams): Promise<UpgradePathResult> => {
|
return useMutation({
|
||||||
const { data } = await apiRequest.post<UpgradePathResult>(
|
mutationFn: async (params: CalculateUpgradePathParams): Promise<UpgradePathResult> => {
|
||||||
"/api/v1/upgrade-path/calculate",
|
const { data } = await apiRequest.post<UpgradePathResult>(
|
||||||
params
|
"/api/v1/upgrade-path/calculate",
|
||||||
);
|
params
|
||||||
return data;
|
);
|
||||||
};
|
return data;
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
/* eslint-disable no-nested-ternary */
|
/* eslint-disable no-nested-ternary */
|
||||||
import { useMemo, useState } from "react";
|
import React, { useMemo, useState } from "react";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { SingleValue } from "react-select";
|
import { SingleValue } from "react-select";
|
||||||
import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
|
import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { Button, FilterableSelect, FormControl } from "@app/components/v2";
|
import { Button, FilterableSelect, FormControl } from "@app/components/v2";
|
||||||
@@ -60,29 +59,31 @@ export const UpgradePathPage = () => {
|
|||||||
data: versions,
|
data: versions,
|
||||||
isLoading: versionsLoading,
|
isLoading: versionsLoading,
|
||||||
isFetching: versionsFetching
|
isFetching: versionsFetching
|
||||||
} = useGetUpgradePathVersions(
|
} = useGetUpgradePathVersions({
|
||||||
{
|
enabled: true,
|
||||||
includePrerelease: false
|
staleTime: 24 * 60 * 60 * 1000,
|
||||||
},
|
refetchOnWindowFocus: false
|
||||||
{
|
});
|
||||||
enabled: true,
|
|
||||||
staleTime: 24 * 60 * 60 * 1000,
|
|
||||||
refetchOnWindowFocus: false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const calculateMutation = useMutation({
|
const calculateMutation = useCalculateUpgradePath();
|
||||||
mutationFn: useCalculateUpgradePath(),
|
|
||||||
onSuccess: (data) => {
|
// Handle mutation results
|
||||||
setUpgradeResult(data);
|
React.useEffect(() => {
|
||||||
},
|
if (calculateMutation.isSuccess && calculateMutation.data) {
|
||||||
onError: (error: unknown) => {
|
setUpgradeResult(calculateMutation.data);
|
||||||
|
}
|
||||||
|
}, [calculateMutation.isSuccess, calculateMutation.data]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (calculateMutation.isError) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: (error as any)?.response?.data?.message || "Failed to calculate upgrade path",
|
text:
|
||||||
|
(calculateMutation.error as any)?.response?.data?.message ||
|
||||||
|
"Failed to calculate upgrade path",
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
}, [calculateMutation.isError, calculateMutation.error]);
|
||||||
|
|
||||||
const versionOptions = useMemo(() => {
|
const versionOptions = useMemo(() => {
|
||||||
if (!versions?.versions) return [];
|
if (!versions?.versions) return [];
|
||||||
@@ -125,8 +126,7 @@ export const UpgradePathPage = () => {
|
|||||||
|
|
||||||
calculateMutation.mutate({
|
calculateMutation.mutate({
|
||||||
fromVersion,
|
fromVersion,
|
||||||
toVersion,
|
toVersion
|
||||||
includePrerelease: false
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user