Skip to content

Commit

Permalink
wip: $ ghjk envs sync
Browse files Browse the repository at this point in the history
  • Loading branch information
Yohe-Am committed Apr 9, 2024
1 parent bef28ad commit ff5aadf
Show file tree
Hide file tree
Showing 14 changed files with 260 additions and 160 deletions.
51 changes: 46 additions & 5 deletions .ghjk/lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"version": "3.12.1",
"depConfigs": {
"tar_aa": {
"version": "1.34",
"version": "1.35",
"depConfigs": {},
"portRef": "[email protected]"
},
Expand All @@ -37,7 +37,7 @@
"version": "3.12.1",
"depConfigs": {
"tar_aa": {
"version": "1.34",
"version": "1.35",
"depConfigs": {},
"portRef": "[email protected]"
},
Expand All @@ -50,7 +50,7 @@
"portRef": "[email protected]"
},
"9e3fa7742c431c34ae7ba8d1e907e50c937ccfb631fb4dcfb7a1773742abe267": {
"version": "1.34",
"version": "1.35",
"depConfigs": {},
"portRef": "[email protected]"
},
Expand All @@ -63,7 +63,7 @@
"version": "3.12.0",
"depConfigs": {
"tar_aa": {
"version": "1.34",
"version": "1.35",
"depConfigs": {},
"portRef": "[email protected]"
},
Expand Down Expand Up @@ -103,6 +103,15 @@
"7d7b0f4b9ec5375688fceab016687f3ac3fbc94c"
],
"allowedDeps": "48a429761f3837562b097b47afe07601ba4ffca5"
},
"ghjkEnvProvInstSet___test": {
"installs": [
"aa103d26454710ca5d7f43358123341380389864",
"c4cf06e095dadfbdd5e26070bc2b7baffc5ff45f",
"9283b97b5499e8da4dcfb7f14c1306c25e8e8a44",
"7d7b0f4b9ec5375688fceab016687f3ac3fbc94c"
],
"allowedDeps": "48a429761f3837562b097b47afe07601ba4ffca5"
}
}
}
Expand All @@ -117,7 +126,25 @@
{
"id": "envs",
"config": {
"envs": {}
"envs": {
"main": {
"provides": [
{
"ty": "ghjk.ports.InstallSetRef",
"setId": "ghjkEnvProvInstSet___main"
}
]
},
"test": {
"provides": [
{
"ty": "ghjk.ports.InstallSetRef",
"setId": "ghjkEnvProvInstSet___test"
}
]
}
},
"defaultEnv": "main"
}
}
],
Expand Down Expand Up @@ -523,6 +550,20 @@
"asdf_plugin_git": "a36b37f4eda81bf51a50d00362637690c7fea473",
"node_org": "5843605c861f0b7307c0192a1628c3823fe28ed9",
"cpy_bs_ghrel": "7a33163826283c47b52964a23b87a4762662c746"
},
"aa103d26454710ca5d7f43358123341380389864": {
"port": {
"ty": "denoWorker@v1",
"name": "protoc_ghrel",
"platforms": [
"aarch64-linux",
"x86_64-linux",
"aarch64-darwin",
"x86_64-darwin"
],
"version": "0.1.0",
"moduleSpecifier": "file:///ports/protoc.ts"
}
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions ghjk.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { ghjk } from "./mod.ts";
import { install, stdSecureConfig } from "./mod.ts";
import { env, install, stdSecureConfig } from "./mod.ts";
import * as ports from "./ports/mod.ts";

// these are just for quick testing
Expand All @@ -12,4 +12,10 @@ install(
ports.cpy_bs({ releaseTag: "20231002" }),
);

export const secureConfig = stdSecureConfig({ enableRuntimes: true });
env("test")
.install(ports.protoc());

export const secureConfig = stdSecureConfig({
enableRuntimes: true,
defaultBaseEnv: "test",
});
53 changes: 35 additions & 18 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
WellKnownProvision,
} from "./modules/envs/types.ts";

const DEFAULT_ENV_NAME = "main";
const DEFAULT_BASE_ENV_NAME = "main";

export type EnvDefArgs = {
name: string;
Expand Down Expand Up @@ -135,7 +135,7 @@ class GhjkfileBuilder {
env = new EnvBuilder(this, (fin) => finalizer = fin, args.name);
this.#seenEnvs[args.name] = [env, finalizer!];
}
if (args.envBase) {
if (args.envBase !== undefined) {
env.base(args.envBase);
}
if (args.installs) {
Expand All @@ -162,8 +162,14 @@ class GhjkfileBuilder {

toConfig(secureConfig: PortsModuleSecureConfig | undefined) {
try {
const envsConfig = this.#processEnvs();
const tasksConfig = this.#processTasks(envsConfig);
const defaultEnv = secureConfig?.defaultEnv ?? DEFAULT_BASE_ENV_NAME;
const defaultBaseEnv = secureConfig?.defaultBaseEnv ??
DEFAULT_BASE_ENV_NAME;
const envsConfig = this.#processEnvs(
defaultEnv,
defaultBaseEnv,
);
const tasksConfig = this.#processTasks(envsConfig, defaultBaseEnv);
const portsConfig = this.#processInstalls(
secureConfig?.masterPortDepAllowList ?? stdDeps(),
);
Expand Down Expand Up @@ -208,7 +214,10 @@ class GhjkfileBuilder {

// this processes the defined envs, normalizing dependency (i.e. "envBase")
// relationships to produce the standard EnvsModuleConfig
#processEnvs() {
#processEnvs(
defaultEnv: string,
defaultBaseEnv: string,
) {
const all = {} as Record<
string,
ReturnType<EnvFinalizer> & { envBaseResolved: null | string }
Expand All @@ -223,7 +232,7 @@ class GhjkfileBuilder {
const envBaseResolved = typeof envBase === "string"
? envBase
: envBase
? DEFAULT_ENV_NAME
? defaultBaseEnv
: null;
all[name] = { ...final, envBaseResolved };
if (envBaseResolved) {
Expand All @@ -238,14 +247,16 @@ class GhjkfileBuilder {
}
}
const processed = {} as Record<string, { installSetId?: string }>;
const out: EnvsModuleConfig = { envs: {} };
const workingSet = indie;
const out: EnvsModuleConfig = { envs: {}, defaultEnv };
const workingSet = [...indie];
while (workingSet.length > 0) {
const item = workingSet.pop()!;
const final = all[item];

const base = final.envBaseResolved
? processed[final.envBaseResolved]
: null;

let processedInstallSetId: string | undefined;
{
const installSet = this.#installSets.get(final.installSetId);
Expand Down Expand Up @@ -286,23 +297,29 @@ class GhjkfileBuilder {
...Object.entries(final.vars).map((
[key, val],
) => {
const prov: WellKnownProvision = { ty: "envVar", key, val };
const prov: WellKnownProvision = { ty: "posix.envVar", key, val };
return prov;
}),
],
};
if (processedInstallSetId) {
const prov: InstallSetRefProvision = {
ty: "ghjkPortsInstallSetRef",
ty: "ghjk.ports.InstallSetRef",
setId: processedInstallSetId,
};
out.envs[final.name].provides.push(prov);
}

const curRevDeps = revDeps.get(final.name);
if (curRevDeps) {
workingSet.push(...curRevDeps);
revDeps.delete(final.name);
}
}
return out;
}

#processTasks(envsConfig: EnvsModuleConfig) {
#processTasks(envsConfig: EnvsModuleConfig, defaultBaseEnv: string) {
const out: TasksModuleConfig = {
envs: {},
tasks: {},
Expand All @@ -317,7 +334,7 @@ class GhjkfileBuilder {
const envBaseResolved = typeof envBase === "string"
? envBase
: envBase
? DEFAULT_ENV_NAME
? defaultBaseEnv
: null;

const envBaseRecipe = envBaseResolved
Expand All @@ -344,11 +361,11 @@ class GhjkfileBuilder {
| InstallSetRefProvision
)[]
) {
if (prov.ty == "envVar") {
if (prov.ty == "posix.envVar") {
if (!mergedEnvVars[prov.key]) {
mergedEnvVars[prov.key] = prov.val;
}
} else if (prov.ty == "ghjkPortsInstallSetRef") {
} else if (prov.ty == "ghjk.ports.InstallSetRef") {
const baseSet = this.#installSets.get(prov.setId)!;
const mergedInstallsSet = new Set([
...taskInstallSet.installs,
Expand All @@ -373,7 +390,7 @@ class GhjkfileBuilder {
const setId = `ghjkTaskInstSet___${name}`;
this.#installSets.set(setId, taskInstallSet);
const prov: InstallSetRefProvision = {
ty: "ghjkPortsInstallSetRef",
ty: "ghjk.ports.InstallSetRef",
setId,
};
taskEnvRecipe.provides.push(prov);
Expand All @@ -383,7 +400,7 @@ class GhjkfileBuilder {
...Object.entries(mergedEnvVars).map((
[key, val],
) => {
const prov: WellKnownProvision = { ty: "envVar", key, val };
const prov: WellKnownProvision = { ty: "posix.envVar", key, val };
return prov;
}),
);
Expand Down Expand Up @@ -514,7 +531,7 @@ class EnvBuilder {

const file = new GhjkfileBuilder();
const mainEnv = file.addEnv({
name: DEFAULT_ENV_NAME,
name: DEFAULT_BASE_ENV_NAME,
envBase: false,
allowedPortDeps: stdDeps(),
});
Expand Down Expand Up @@ -579,7 +596,7 @@ export function stdSecureConfig(
args: {
additionalAllowedPorts?: PortsModuleSecureConfig["masterPortDepAllowList"];
enableRuntimes?: boolean;
},
} & Pick<PortsModuleSecureConfig, "defaultEnv" | "defaultBaseEnv">,
): PortsModuleSecureConfig {
const { additionalAllowedPorts, enableRuntimes = false } = args;
const out: PortsModuleSecureConfig = {
Expand Down
56 changes: 40 additions & 16 deletions modules/envs/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,56 +9,80 @@
export * from "./types.ts";

import { cliffy_cmd, zod } from "../../deps/cli.ts";
import { Json } from "../../utils/mod.ts";
import { $, Json, unwrapParseRes } from "../../utils/mod.ts";

import validators from "./types.ts";
import type { EnvsModuleConfigX } from "./types.ts";
import type { GhjkCtx, ModuleManifest } from "../types.ts";
import { ModuleBase } from "../mod.ts";

import { Blackboard } from "../../host/types.ts";
import { reduceStrangeProvisions } from "./reducer.ts";
import { cookPosixEnv } from "./posix.ts";

export type EnvsCtx = {
activeEnv: string;
config: EnvsModuleConfigX;
};

export type EnvsCtx = {};
const lockValidator = zod.object({
version: zod.string(),
});

type EnvsLockEnt = zod.infer<typeof lockValidator>;

export class EnvsModule extends ModuleBase<EnvsCtx, EnvsLockEnt> {
processManifest(
_ctx: GhjkCtx,
manifest: ModuleManifest,
_bb: Blackboard,
bb: Blackboard,
_lockEnt: EnvsLockEnt | undefined,
) {
const res = validators.envsModuleConfig.safeParse(manifest.config);
if (!res.success) {
throw new Error("error parsing module config", {
cause: {
config: manifest.config,
zodErr: res.error,
},
});
function unwrapParseCurry<I, O>(res: zod.SafeParseReturnType<I, O>) {
return unwrapParseRes<I, O>(res, {
id: manifest.id,
config: manifest.config,
bb,
}, "error parsing module config");
}
const config: EnvsModuleConfigX = {
...res.data,
};
const config = unwrapParseCurry(
validators.envsModuleConfig.safeParse(manifest.config),
);

const activeEnv = config.defaultEnv;

return Promise.resolve({
activeEnv,
config,
});
}

command(
_gcx: GhjkCtx,
_ecx: EnvsCtx,
gcx: GhjkCtx,
ecx: EnvsCtx,
) {
const root: cliffy_cmd.Command<any, any, any, any> = new cliffy_cmd
.Command()
.description("Envs module, the cornerstone")
.alias("e")
.alias("env")
.action(function () {
this.showHelp();
})
.command(
"sync",
new cliffy_cmd.Command().description("Syncs the environment.")
.action(async () => {
const envName = ecx.activeEnv;

const env = ecx.config.envs[envName];
// TODO: diff env and ask confirmation from user
const reducedEnv = await reduceStrangeProvisions(gcx, env);
const envDir = $.path(gcx.ghjkDir).join("envs", envName).toString();

await cookPosixEnv(reducedEnv, envDir, true);
}),
)
.description("Envs module.");
return root;
}
Expand Down
Loading

0 comments on commit ff5aadf

Please sign in to comment.