mirror of
https://github.com/moghtech/komodo.git
synced 2026-03-11 17:44:19 -05:00
cancel build
This commit is contained in:
4
.vscode/resolver.code-snippets
vendored
4
.vscode/resolver.code-snippets
vendored
@@ -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}",
|
||||
"}"
|
||||
|
||||
@@ -38,6 +38,7 @@ enum ExecuteRequest {
|
||||
|
||||
// ==== BUILD ====
|
||||
RunBuild(RunBuild),
|
||||
CancelBuild(CancelBuild),
|
||||
|
||||
// ==== REPO ====
|
||||
CloneRepo(CloneRepo),
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,8 @@ enum ReadRequest {
|
||||
GetBuildActionState(GetBuildActionState),
|
||||
GetBuildMonthlyStats(GetBuildMonthlyStats),
|
||||
GetBuildVersions(GetBuildVersions),
|
||||
#[to_string_resolver]
|
||||
ListDockerOrganizations(ListDockerOrganizations),
|
||||
|
||||
// ==== REPO ====
|
||||
GetReposSummary(GetReposSummary),
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user