cancel build

This commit is contained in:
mbecker20
2024-03-25 04:41:47 -07:00
parent 5d0050535d
commit c7ce80c5e3
12 changed files with 159 additions and 29 deletions

View File

@@ -4,8 +4,8 @@
"prefix": "resolve",
"body": [
"#[async_trait]",
"impl Resolve<${1}, ResolverArgs> for State {",
"\tasync fn resolve(&self, ${1} { ${0} }: ${1}, _: ResolverArgs) -> anyhow::Result<${2}> {",
"impl Resolve<${1}, User> for State {",
"\tasync fn resolve(&self, ${1} { ${0} }: ${1}, _: User) -> anyhow::Result<${2}> {",
"\t\ttodo!()",
"\t}",
"}"

View File

@@ -38,6 +38,7 @@ enum ExecuteRequest {
// ==== BUILD ====
RunBuild(RunBuild),
CancelBuild(CancelBuild),
// ==== REPO ====
CloneRepo(CloneRepo),

View File

@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, sync::OnceLock};
use anyhow::Context;
use async_timing_util::unix_timestamp_ms;
@@ -21,9 +21,10 @@ use mungos::{
options::FindOptions,
},
};
use resolver_api::Resolve;
use resolver_api::{Resolve, ResolveToString};
use crate::{
config::core_config,
db::db_client,
helpers::resource::StateResource,
state::{action_states, State},
@@ -235,3 +236,22 @@ impl Resolve<GetBuildVersions, User> for State {
Ok(versions)
}
}
fn docker_organizations() -> &'static String {
static DOCKER_ORGANIZATIONS: OnceLock<String> = OnceLock::new();
DOCKER_ORGANIZATIONS.get_or_init(|| {
serde_json::to_string(&core_config().docker_organizations)
.expect("failed to serialize docker organizations")
})
}
#[async_trait]
impl ResolveToString<ListDockerOrganizations, User> for State {
async fn resolve_to_string(
&self,
ListDockerOrganizations {}: ListDockerOrganizations,
_: User,
) -> anyhow::Result<String> {
Ok(docker_organizations().clone())
}
}

View File

@@ -82,6 +82,8 @@ enum ReadRequest {
GetBuildActionState(GetBuildActionState),
GetBuildMonthlyStats(GetBuildMonthlyStats),
GetBuildVersions(GetBuildVersions),
#[to_string_resolver]
ListDockerOrganizations(ListDockerOrganizations),
// ==== REPO ====
GetReposSummary(GetReposSummary),

View File

@@ -154,3 +154,16 @@ pub struct BuildVersionResponseItem {
pub version: Version,
pub ts: I64,
}
//
#[typeshare]
#[derive(
Serialize, Deserialize, Debug, Clone, Default, Request, EmptyTraits,
)]
#[empty_traits(MonitorReadRequest)]
#[response(ListDockerOrganizationsResponse)]
pub struct ListDockerOrganizations {}
#[typeshare]
pub type ListDockerOrganizationsResponse = Vec<String>;

View File

@@ -8,7 +8,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
console.log("generating typescript types...");
const gen_command =
"RUST_BACKTRACE=1 typeshare . --lang=typescript --output-file=./client/ts/src/types.ts";
"RUST_BACKTRACE=1 typeshare . --lang=typescript --output-file=./client/core/ts/src/types.ts";
exec(gen_command, (error, stdout, stderr) => {
if (error) {

View File

@@ -57,6 +57,7 @@ export type ReadResponses = {
GetBuildActionState: Types.GetBuildActionStateResponse;
GetBuildMonthlyStats: Types.GetBuildMonthlyStatsResponse;
GetBuildVersions: Types.GetBuildVersionsResponse;
ListDockerOrganizations: Types.ListDockerOrganizationsResponse;
// ==== REPO ====
GetReposSummary: Types.GetReposSummaryResponse;
@@ -180,6 +181,7 @@ export type ExecuteResponses = {
// ==== BUILD ====
RunBuild: Types.Update;
CancelBuild: Types.CancelBuildResponse;
// ==== REPO ====
CloneRepo: Types.Update;

View File

@@ -124,6 +124,8 @@ export interface BuildVersionResponseItem {
export type GetBuildVersionsResponse = BuildVersionResponseItem[];
export type ListDockerOrganizationsResponse = string[];
export type BuilderConfig =
| { type: "Server", params: ServerBuilderConfig }
| { type: "Aws", params: AwsBuilderConfig };
@@ -308,9 +310,9 @@ export type GetUsersResponse = User[];
export type ProcedureConfig =
| { type: "Execution", data: Execution }
/** Vec<ProcedureId> */
| { type: "Sequence", data: string[] }
| { type: "Sequence", data: EnabledId[] }
/** Vec<ProdecureId> */
| { type: "Parallel", data: string[] };
| { type: "Parallel", data: EnabledId[] };
export type Procedure = Resource<ProcedureConfig, undefined>;
@@ -729,6 +731,7 @@ export type _PartialSlackAlerterConfig = Partial<SlackAlerterConfig>;
/** Passing empty Vec is the same as not filtering by that field */
export interface ResourceQuery<T> {
names?: string[];
/** Pass Vec of tag ids */
tags?: string[];
specific?: T;
}
@@ -1032,6 +1035,9 @@ export interface GetBuildVersions {
patch?: number;
}
export interface ListDockerOrganizations {
}
export interface GetBuilder {
id: string;
}
@@ -1642,6 +1648,12 @@ export interface CloneArgs {
github_account?: string;
}
/** Allows to enable / disabled procedures in the sequence / parallel vec on the fly */
export interface EnabledId {
id: string;
enabled: boolean;
}
export interface ServerHealth {
cpu: SeverityLevel;
mem: SeverityLevel;
@@ -1666,6 +1678,7 @@ export type ExecuteRequest =
| { type: "StopAllContainers", params: StopAllContainers }
| { type: "RemoveContainer", params: RemoveContainer }
| { type: "RunBuild", params: RunBuild }
| { type: "CancelBuild", params: CancelBuild }
| { type: "CloneRepo", params: CloneRepo }
| { type: "PullRepo", params: PullRepo }
| { type: "RunProcedure", params: RunProcedure };
@@ -1710,6 +1723,7 @@ export type ReadRequest =
| { type: "GetBuildActionState", params: GetBuildActionState }
| { type: "GetBuildMonthlyStats", params: GetBuildMonthlyStats }
| { type: "GetBuildVersions", params: GetBuildVersions }
| { type: "ListDockerOrganizations", params: ListDockerOrganizations }
| { type: "GetReposSummary", params: GetReposSummary }
| { type: "GetRepo", params: GetRepo }
| { type: "ListRepos", params: ListRepos }

View File

@@ -54,6 +54,9 @@ export const Omnibar = () => {
useEffect(() => {
const down = (e: KeyboardEvent) => {
console.log(e);
const target = e.target as any;
if (target.matches("input") || target.matches("textarea")) return;
if (e.shiftKey && e.key === "S") {
e.preventDefault();
set(true);

View File

@@ -1,19 +1,30 @@
import { ConfigInner } from "@components/config";
import { ResourceSelector, AccountSelector } from "@components/config/util";
import {
ResourceSelector,
AccountSelector,
ConfigItem,
} from "@components/config/util";
import { NewResource } from "@components/layouts";
import { ConfirmButton } from "@components/util";
import { useExecute, useRead, useWrite } from "@lib/hooks";
import { fmt_date_with_minutes, fmt_version } from "@lib/utils";
import {
env_to_text,
fmt_date_with_minutes,
fmt_version,
text_to_env,
} from "@lib/utils";
import { Types } from "@monitor/client";
import { RequiredResourceComponents } from "@types";
import { DataTable } from "@ui/data-table";
import { Input } from "@ui/input";
import { Hammer, History, Loader2 } from "lucide-react";
import { useState } from "react";
import { Ban, Hammer, History, Loader2 } from "lucide-react";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { ResourceComponents } from "..";
import { BuildChart } from "@components/dashboard/builds-chart";
import { useTagsFilter } from "@components/tags";
import { Textarea } from "@ui/textarea";
import { useToast } from "@ui/use-toast";
const useBuild = (id?: string) =>
useRead("ListBuilds", {}).data?.find((d) => d.id === id);
@@ -39,8 +50,33 @@ const NewBuild = () => {
);
};
export const BuildArgs = ({
vars,
set,
}: {
vars: Types.EnvironmentVar[];
set: (input: Partial<Types.BuildConfig>) => void;
}) => {
const [args, setArgs] = useState(env_to_text(vars));
useEffect(() => {
!!args && set({ build_args: text_to_env(args) });
}, [args, set]);
return (
<ConfigItem label="Build Args" className="flex-col gap-4 items-start">
<Textarea
className="min-h-[300px]"
placeholder="VARIABLE=value"
value={args}
onChange={(e) => setArgs(e.target.value)}
/>
</ConfigItem>
);
};
export const BuildConfig = ({ id }: { id: string }) => {
const config = useRead("GetBuild", { id }).data?.config;
// const orgs = useRead("GetAccounts")
const [update, set] = useState<Partial<Types.BuildConfig>>({});
const { mutate } = useWrite("UpdateBuild");
@@ -65,6 +101,8 @@ export const BuildConfig = ({ id }: { id: string }) => {
/>
</div>
),
},
git: {
repo: true,
branch: true,
github_account: (account, set) => (
@@ -77,8 +115,6 @@ export const BuildConfig = ({ id }: { id: string }) => {
/>
),
},
},
docker: {
docker: {
build_path: true,
dockerfile_path: true,
@@ -95,6 +131,14 @@ export const BuildConfig = ({ id }: { id: string }) => {
// docker_organization,
},
},
"Build Args": {
"Build Args": {
build_args: (vars, set) => (
<BuildArgs vars={vars ?? []} set={set} />
),
skip_secret_interp: true,
},
},
}}
/>
);
@@ -192,22 +236,53 @@ export const BuildComponents: RequiredResourceComponents = {
else return <Hammer className="w-4 h-4" />;
},
Actions: ({ id }) => {
const { toast } = useToast();
const building = useRead("GetBuildActionState", { id }).data?.building;
const { mutate, isPending } = useExecute("RunBuild");
return (
<ConfirmButton
title={building ? "Building" : "Build"}
icon={
building ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<Hammer className="h-4 w-4" />
)
}
onClick={() => mutate({ build_id: id })}
disabled={building || isPending}
/>
const { mutate: run_mutate, isPending: runPending } = useExecute(
"RunBuild",
{
onMutate: () => {
toast({ title: "Run Build Sent" });
},
}
);
const { mutate: cancel_mutate, isPending: cancelPending } = useExecute(
"CancelBuild",
{
onMutate: () => {
toast({ title: "Cancel Build Sent" });
},
onSuccess: () => {
toast({ title: "Build Cancelled" });
},
}
);
if (building) {
return (
<ConfirmButton
title="Cancel Build"
variant="destructive"
icon={<Ban className="h-4 w-4" />}
onClick={() => cancel_mutate({ build_id: id })}
disabled={cancelPending}
/>
);
} else {
return (
<ConfirmButton
title="Build"
icon={
runPending ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<Hammer className="h-4 w-4" />
)
}
onClick={() => run_mutate({ build_id: id })}
disabled={runPending}
/>
);
}
},
Table: BuildTable,
New: NewBuild,

View File

@@ -100,8 +100,8 @@ export const DeploymentConfig = ({ id }: { id: string }) => {
},
environment: {
environment: {
skip_secret_interp: true,
environment: (vars, set) => <EnvVars vars={vars ?? []} set={set} />,
skip_secret_interp: true,
},
},
}}

View File

@@ -1,7 +1,7 @@
[gen-ts-types]
description = "generates typescript types for the ts client"
path = "."
cmd = "node ./client/ts/generate_types.mjs"
cmd = "node ./client/core/ts/generate_types.mjs"
[start-frontend]
path = "frontend"