ensure sync directory exist

This commit is contained in:
mbecker20
2024-06-07 21:02:28 -07:00
parent 5eacb7191b
commit 078ba59002
15 changed files with 135 additions and 14 deletions

View File

@@ -1,3 +1,5 @@
use std::fs;
use anyhow::{anyhow, Context};
use monitor_client::entities::{
sync::ResourceSync, to_monitor_name, toml::ResourcesToml,
@@ -32,6 +34,9 @@ pub async fn get_remote_resources(
.transpose()?
.cloned();
fs::create_dir_all(&config.sync_directory)
.context("failed to create sync directory")?;
let mut logs =
git::clone(clone_args, &config.sync_directory, github_token)
.await

View File

@@ -217,7 +217,7 @@ export const AccountSelector = ({
>
<SelectTrigger
className="w-full lg:w-[200px] max-w-[50%]"
disabled={disabled || !id}
disabled={disabled}
>
<SelectValue placeholder={placeholder} />
</SelectTrigger>

View File

@@ -49,7 +49,11 @@ export const ResourceDescription = ({
const inv = useInvalidate();
const key =
type === "ServerTemplate" ? "server_template" : type.toLowerCase();
type === "ServerTemplate"
? "server_template"
: type === "ResourceSync"
? "sync"
: type.toLowerCase();
const resource = useRead(`Get${type}`, {
[key]: id,
@@ -244,10 +248,12 @@ export const CopyResource = ({
export const NewResource = ({
type,
readable_type,
server_id,
build_id,
}: {
type: UsableResource;
readable_type?: string;
server_id?: string;
build_id?: string;
}) => {
@@ -255,7 +261,11 @@ export const NewResource = ({
const { mutateAsync } = useWrite(`Create${type}`);
const [name, setName] = useState("");
const type_display =
type === "ServerTemplate" ? "server-template" : type.toLowerCase();
type === "ServerTemplate"
? "server-template"
: type === "ResourceSync"
? "resource-sync"
: type.toLowerCase();
const config =
type === "Deployment"
? {
@@ -267,7 +277,7 @@ export const NewResource = ({
: {};
return (
<NewLayout
entityType={type}
entityType={readable_type ?? type}
onSuccess={async () => {
const id = (await mutateAsync({ name, config }))._id?.$oid!;
nav(`/${usableResourcePath(type)}/${id}`);
@@ -276,7 +286,7 @@ export const NewResource = ({
onOpenChange={() => setName("")}
>
<div className="grid md:grid-cols-2 items-center">
{type} Name
{readable_type ?? type} Name
<Input
placeholder={`${type_display}-name`}
value={name}
@@ -296,7 +306,11 @@ export const DeleteResource = ({
}) => {
const nav = useNavigate();
const key =
type === "ServerTemplate" ? "server_template" : type.toLowerCase();
type === "ServerTemplate"
? "server_template"
: type === "ResourceSync"
? "sync"
: type.toLowerCase();
const resource = useRead(`Get${type}`, {
[key]: id,
} as any).data;

View File

@@ -7,7 +7,7 @@ import { RepoComponents } from "./repo";
import { ServerComponents } from "./server";
import { ProcedureComponents } from "./procedure/index";
import { ServerTemplateComponents } from "./server-template";
import { ResourceSyncComponents } from "./sync";
import { ResourceSyncComponents } from "./resource-sync";
export const ResourceComponents: {
[key in UsableResource]: RequiredResourceComponents;

View File

@@ -0,0 +1,57 @@
import { ConfirmButton } from "@components/util";
import { useExecute, useInvalidate, useRead, useWrite } from "@lib/hooks";
import { sync_no_changes } from "@lib/utils";
import { Loader2, RefreshCcw, SquarePlay } from "lucide-react";
export const RefreshSync = ({ id }: { id: string }) => {
const inv = useInvalidate();
const { mutate, isPending } = useWrite("RefreshResourceSyncPending", {
onSuccess: () => inv(["GetResourceSync", { sync: id }]),
});
const pending = isPending;
return (
<ConfirmButton
title="Refresh"
icon={
pending ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<RefreshCcw className="w-4 h-4" />
)
}
onClick={() => mutate({ sync: id })}
disabled={pending}
loading={pending}
/>
);
};
export const ExecuteSync = ({ id }: { id: string }) => {
const { mutate, isPending } = useExecute("RunSync");
const syncing = useRead(
"GetResourceSyncActionState",
{ sync: id },
{ refetchInterval: 5000 }
).data?.syncing;
const sync = useRead("GetResourceSync", { sync: id }).data;
if (!sync || sync_no_changes(sync)) return null;
const pending = isPending || syncing;
return (
<ConfirmButton
title="Execute Sync"
icon={
pending ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<SquarePlay className="w-4 h-4" />
)
}
onClick={() => mutate({ sync: id })}
disabled={pending}
loading={pending}
/>
);
};

View File

@@ -9,6 +9,7 @@ import { Types } from "@monitor/client";
import { ResourceSyncConfig } from "./config";
import { useState } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@ui/tabs";
import { ExecuteSync, RefreshSync } from "./actions";
const useResourceSync = (id?: string) =>
useRead("ListResourceSyncs", {}).data?.find((d) => d.id === id);
@@ -44,12 +45,12 @@ export const ResourceSyncComponents: RequiredResourceComponents = {
Dashboard: () => {
const syncs_count = useRead("ListResourceSyncs", {}).data?.length;
return (
<Link to="/syncs/" className="w-full">
<Link to="/resource-syncs/" className="w-full">
<Card className="hover:bg-accent/50 transition-colors cursor-pointer">
<CardHeader>
<div className="flex justify-between">
<div>
<CardTitle>Syncs</CardTitle>
<CardTitle>Resource Syncs</CardTitle>
<CardDescription>{syncs_count} Total</CardDescription>
</div>
<FolderSync className="w-4 h-4" />
@@ -60,7 +61,7 @@ export const ResourceSyncComponents: RequiredResourceComponents = {
);
},
New: () => <NewResource type="ResourceSync" />,
New: () => <NewResource type="ResourceSync" readable_type="Resource Sync" />,
Table: ({ resources }) => (
<ResourceSyncTable syncs={resources as Types.ResourceSyncListItem[]} />
@@ -73,7 +74,7 @@ export const ResourceSyncComponents: RequiredResourceComponents = {
Info: {},
Actions: {},
Actions: { RefreshSync, ExecuteSync },
Page: {},

View File

@@ -52,7 +52,12 @@ export const Sidebar = () => {
{RESOURCE_TARGETS.map((type) => {
const RTIcon = ResourceComponents[type].Icon;
const name = type === "ServerTemplate" ? "Template" : type;
const name =
type === "ServerTemplate"
? "Template"
: type === "ResourceSync"
? "Sync"
: type;
return (
<SidebarLink
key={type}

View File

@@ -125,7 +125,11 @@ const PrimaryDropdown = () => {
const [icon, title] = Components
? [
<Components.Icon />,
(type === "ServerTemplate" ? "Template" : type) + "s",
(type === "ServerTemplate"
? "Template"
: type === "ResourceSync"
? "Sync"
: type) + "s",
]
: location.pathname === "/"
? [<Home className="w-4 h-4" />, "Home"]

View File

@@ -192,6 +192,7 @@ export const useResourceParamType = () => {
const type = useParams().type;
if (!type) return undefined;
if (type === "server-templates") return "ServerTemplate";
if (type === "resource-syncs") return "ResourceSync";
return (type[0].toUpperCase() + type.slice(1, -1)) as UsableResource;
};

View File

@@ -137,6 +137,15 @@ const on_message = (
);
}
if (update.target.type === "ResourceSync") {
invalidate(
["ListResourceSyncs"],
["GetResourceSync"],
["GetResourceSyncActionState"],
["GetResourceSyncsSummary"]
);
}
if (
update.target.type === "System" &&
update.operation.includes("Variable")

View File

@@ -22,6 +22,7 @@ export const RESOURCE_TARGETS: UsableResource[] = [
"Builder",
"Alerter",
"ServerTemplate",
"ResourceSync",
];
export function env_to_text(envVars: Types.EnvironmentVar[] | undefined) {
@@ -97,6 +98,7 @@ export const convertTsMsToLocalUnixTsInSecs = (ts: number) =>
export const usableResourcePath = (resource: UsableResource) => {
if (resource === "ServerTemplate") return "server-templates";
if (resource === "ResourceSync") return "resource-syncs";
return `${resource.toLowerCase()}s`;
};
@@ -173,3 +175,21 @@ export const filterBySplit = <T>(
: items) ?? []
);
};
export const sync_no_changes = (sync: Types.ResourceSync) => {
const pending = sync.info?.pending;
if (!pending) return false;
return (
!pending.server_updates?.length &&
!pending.deployment_updates?.length &&
!pending.build_updates?.length &&
!pending.repo_updates?.length &&
!pending.procedure_updates?.length &&
!pending.alerter_updates?.length &&
!pending.builder_updates?.length &&
!pending.server_template_updates?.length &&
!pending.resource_sync_updates?.length &&
!pending.variable_updates?.length &&
!pending.user_group_updates?.length
);
};

View File

@@ -14,7 +14,12 @@ import { useState } from "react";
export const Resources = () => {
const type = useResourceParamType()!;
const name = type === "ServerTemplate" ? "Server Template" : type;
const name =
type === "ServerTemplate"
? "Server Template"
: type === "ResourceSync"
? "Resource Sync"
: type;
useSetTitle(name + "s");
const Components = ResourceComponents[type];
const [search, set] = useState("");