feat: add commands for managing deployments and resources

- Implemented `down` command to delete managed resources, with an option to delete ingress and PVCs.
- Added `exec` command to execute commands inside deployment pods.
- Created `logs` command to show deployment logs with an option to follow the output.
- Introduced `start` command to start deployments without rebuilding images.
- Developed `stop` command to scale managed deployments to zero.

refactor: enhance resource management and Kubernetes interactions

- Refactored resource handling in `lib/apply.ts` to support sorting and applying resources.
- Improved logging functionality with a new logger in `lib/logger.ts`.
- Enhanced build process in `lib/build.ts` to support remote builds and syncing with Git repositories.
- Added functions to manage deployments and pods in `lib/shared.ts`.

chore: update dependencies and TypeScript configuration

- Updated package.json to include `listr2` for task management.
- Modified tsconfig.json to exclude build artifacts and fixtures.
This commit is contained in:
2026-08-09 00:18:14 +07:00 Unverified
parent c08fb36d2e
commit 8f331d4cc7
17 changed files with 1299 additions and 50 deletions
+97 -7
View File
@@ -1,6 +1,100 @@
import { defineCommand } from "citty";
import { Listr } from "listr2";
import type { ComposeSpecification } from "../schema/docker.d";
import { ctx } from "../lib/context";
import { serviceToDeployment } from "../lib/convert";
import {
applyResource,
deleteResource,
getStaleResources,
sortResources,
} from "../lib/apply";
import { buildServices } from "../lib/build";
import { composeToKubernetes, type KubernetesResource } from "../lib/convert";
type UpContext = {
compose?: ComposeSpecification;
resources?: KubernetesResource[];
staleResources?: KubernetesResource[];
};
export async function runUp(build: boolean) {
const { project, compose, cwd } = ctx();
await new Listr<UpContext>([
{
title: "Read compose",
task: async (taskCtx, task) => {
taskCtx.compose = await compose();
task.output = `${Object.keys(taskCtx.compose.services ?? {}).length} services`;
},
},
{
title: "Build images",
enabled: () => build,
skip: (taskCtx) =>
Object.values(taskCtx.compose?.services ?? {}).some((service) => service.build)
? false
: "No buildable services",
task: async (taskCtx, task) => {
const built = await buildServices(project, taskCtx.compose!, cwd, (message) => {
task.output = message;
});
task.output = `Built ${built} image${built === 1 ? "" : "s"}`;
},
},
{
title: "Render manifests",
task: async (taskCtx, task) => {
taskCtx.resources = await composeToKubernetes(project, taskCtx.compose!, cwd);
task.output = `${taskCtx.resources.length} resources`;
},
},
{
title: "Plan reconciliation",
task: async (taskCtx, task) => {
taskCtx.staleResources = (await getStaleResources(
project,
taskCtx.resources!,
)) as KubernetesResource[];
task.output = `${taskCtx.staleResources.length} stale resource${taskCtx.staleResources.length === 1 ? "" : "s"}`;
},
},
{
title: "Apply resources",
task: (taskCtx, task) => {
const resources = sortResources(taskCtx.resources!);
task.output = `${resources.length} resources queued`;
return task.newListr(
resources.map((resource) => ({
title: `${resource.kind} ${resource.metadata?.name}`,
task: () => applyResource(resource),
})),
{ concurrent: false, exitOnError: true },
);
},
},
{
title: "Delete stale resources",
skip: (taskCtx) =>
taskCtx.staleResources && taskCtx.staleResources.length > 0
? false
: "No stale resources",
task: (taskCtx, task) => {
const resources = sortResources(taskCtx.staleResources!).reverse();
task.output = `${resources.length} resources queued`;
return task.newListr(
resources.map((resource) => ({
title: `${resource.kind} ${resource.metadata?.name}`,
task: () => deleteResource(resource),
})),
{ concurrent: false, exitOnError: true },
);
},
},
], { rendererOptions: { collapseErrors: false } }).run();
}
export const up = defineCommand({
meta: {
@@ -16,11 +110,7 @@ export const up = defineCommand({
negativeDescription: "Don't build an image, even if it's policy",
},
},
async run() {
const { project, compose } = ctx();
const cmp = await compose();
console.dir(serviceToDeployment(project, "app", cmp.services!.app!), {
depth: 999,
});
async run({ args }) {
await runUp(args.build);
},
});