summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth <me@liz.coffee>2025-06-02 18:07:31 -0700
committerElizabeth <me@liz.coffee>2025-06-02 18:07:31 -0700
commitd9c418425b035f00c950e6a83df9470d7af80413 (patch)
tree07c7445d7800a6ac6a3cf6b404ebcf4e27aad245
parent98f5c21aa65bbbca01a186a754249335b4afef57 (diff)
downloadci-d9c418425b035f00c950e6a83df9470d7af80413.tar.gz
ci-d9c418425b035f00c950e6a83df9470d7af80413.zip
Use log traceable in metric traceable
-rw-r--r--.zed/settings.json1
-rwxr-xr-xmod.ts47
-rw-r--r--server/job.ts316
-rw-r--r--server/mod.ts10
-rw-r--r--u/fn/either.ts188
-rw-r--r--u/process/argv.ts10
-rw-r--r--u/server/activity/fourohfour.ts9
-rw-r--r--u/server/request.ts11
-rw-r--r--u/server/response.ts10
-rw-r--r--u/trace/itrace.ts46
-rw-r--r--u/trace/logger.ts4
-rw-r--r--u/trace/metrics.ts4
-rw-r--r--u/trace/trace.ts32
-rw-r--r--worker/executor.ts4
-rw-r--r--worker/jobs/ci_pipeline.run5
-rwxr-xr-xworker/scripts/ansible_playbook6
-rwxr-xr-xworker/scripts/build_docker_image7
-rw-r--r--worker/secret.ts344
18 files changed, 515 insertions, 539 deletions
diff --git a/.zed/settings.json b/.zed/settings.json
index cf1756f..78b2d5d 100644
--- a/.zed/settings.json
+++ b/.zed/settings.json
@@ -1,4 +1,5 @@
{
+ "formatter": "prettier",
"lsp": {
"deno": {
"settings": {
diff --git a/mod.ts b/mod.ts
index 81a2bc2..0af8943 100755
--- a/mod.ts
+++ b/mod.ts
@@ -1,31 +1,36 @@
#!/usr/bin/env -S deno run --allow-env --allow-net
-import { argv } from "@emprespresso/pengueno";
+import { argv, IEither, Either } from "@emprespresso/pengueno";
import { runServer } from "@emprespresso/ci_server";
-const main = (_argv = Deno.args) => {
- const defaults = {
- "--port": "9000",
- "--host": "0.0.0.0",
- };
- const _args = argv(["--run-server", "--port", "--host"], defaults, _argv);
- const args = _args.fold((err, args) => {
- if (!args || err) throw err;
- return {
+const _defaults = {
+ "--port": "9000",
+ "--host": "0.0.0.0",
+};
+const main = (
+ _argv = Deno.args,
+ defaults = _defaults,
+): Promise<IEither<Error, void>> =>
+ argv(["--run-server", "--port", "--host"], defaults, _argv)
+ .mapRight((args) => ({
server_mode: "--run-server" in args,
port: parseInt(args["--port"]),
host: args["--host"],
- };
- });
-
- const promises: Array<Promise<void>> = [];
- if (args.server_mode) {
- promises.push(runServer(args.port, args.host));
- }
-
- return Promise.all(promises);
-};
+ }))
+ .flatMapAsync((runConfig) => {
+ if (runConfig.server_mode) {
+ return runServer(runConfig.port, runConfig.host);
+ }
+ return Promise.resolve(Either.right(undefined));
+ });
if (import.meta.main) {
- await main();
+ await main().then((eitherDone) =>
+ eitherDone.fold(({ isLeft, value }) => {
+ if (!isLeft) return;
+
+ console.error(value);
+ Deno.exit(1);
+ }),
+ );
}
diff --git a/server/job.ts b/server/job.ts
index 4e12b45..af11ac0 100644
--- a/server/job.ts
+++ b/server/job.ts
@@ -1,21 +1,21 @@
import {
- getStdout,
- type Mapper,
- memoize,
- Either,
- ErrorSource,
- type IActivity,
- type IEither,
- type ITraceable,
- jsonModel,
- JsonResponse,
- LogLevel,
- Metric,
- PenguenoError,
- type PenguenoRequest,
- type ServerTrace,
- TraceUtil,
- validateExecutionEntries,
+ getStdout,
+ type Mapper,
+ memoize,
+ Either,
+ ErrorSource,
+ type IActivity,
+ type IEither,
+ type ITraceable,
+ jsonModel,
+ JsonResponse,
+ LogLevel,
+ Metric,
+ PenguenoError,
+ type PenguenoRequest,
+ type ServerTrace,
+ TraceUtil,
+ validateExecutionEntries,
} from "@emprespresso/pengueno";
import { isJob, type Job } from "@emprespresso/ci_model";
@@ -23,98 +23,88 @@ import { isJob, type Job } from "@emprespresso/ci_model";
const wellFormedJobMetric = Metric.fromName("Job.WellFormed");
const jobJsonTransformer = (
- j: ITraceable<unknown, ServerTrace>,
+ j: ITraceable<unknown, ServerTrace>,
): IEither<PenguenoError, Job> =>
- j
- .bimap(TraceUtil.withMetricTrace(wellFormedJobMetric))
- .map((tJson) => {
- if (!isJob(tJson) || !validateExecutionEntries(tJson)) {
- const err = "seems like a pwetty mawfomed job \\(-.-)/";
- tJson.trace.addTrace(LogLevel.WARN).trace(err);
- return Either.left<PenguenoError, Job>(
- new PenguenoError(err, 400),
- );
- }
- return Either.right<PenguenoError, Job>(tJson);
- })
- .peek((tJob) =>
- tJob.trace.trace(
- tJob
- .get()
- .fold(({ isLeft }) =>
- isLeft
- ? wellFormedJobMetric.failure
- : wellFormedJobMetric.success,
- ),
- ),
- )
- .get();
+ j
+ .bimap(TraceUtil.withMetricTrace(wellFormedJobMetric))
+ .map((tJson) => {
+ if (!isJob(tJson) || !validateExecutionEntries(tJson)) {
+ const err = "seems like a pwetty mawfomed job \\(-.-)/";
+ tJson.trace.addTrace(LogLevel.WARN).trace(err);
+ return Either.left<PenguenoError, Job>(new PenguenoError(err, 400));
+ }
+ return Either.right<PenguenoError, Job>(tJson);
+ })
+ .peek((tJob) =>
+ tJob.trace.trace(
+ tJob
+ .get()
+ .fold(({ isLeft }) =>
+ isLeft ? wellFormedJobMetric.failure : wellFormedJobMetric.success,
+ ),
+ ),
+ )
+ .get();
export interface IJobHookActivity {
- processHook: IActivity;
+ processHook: IActivity;
}
const jobHookRequestMetric = Metric.fromName("JobHook.process");
export class JobHookActivityImpl implements IJobHookActivity {
- constructor(
- private readonly queuer: IJobQueuer<ITraceable<Job, ServerTrace>>,
- ) {}
+ constructor(
+ private readonly queuer: IJobQueuer<ITraceable<Job, ServerTrace>>,
+ ) {}
- private trace(r: ITraceable<PenguenoRequest, ServerTrace>) {
- return r
- .bimap(TraceUtil.withClassTrace(this))
- .bimap(TraceUtil.withMetricTrace(jobHookRequestMetric));
- }
+ private trace(r: ITraceable<PenguenoRequest, ServerTrace>) {
+ return r
+ .bimap(TraceUtil.withClassTrace(this))
+ .bimap(TraceUtil.withMetricTrace(jobHookRequestMetric));
+ }
- public processHook(r: ITraceable<PenguenoRequest, ServerTrace>) {
- return this.trace(r)
- .map(jsonModel(jobJsonTransformer))
- .map(async (tEitherJobJson) => {
- const eitherJob = await tEitherJobJson.get();
- return eitherJob.flatMapAsync(async (job) => {
- const eitherQueued = await tEitherJobJson
- .move(job)
- .map(this.queuer.queue)
- .get();
- return eitherQueued.mapLeft(
- (e) => new PenguenoError(e.message, 500),
- );
- });
- })
- .peek(
- TraceUtil.promiseify((tJob) =>
- tJob.get().fold(({ isRight, value }) => {
- if (isRight) {
- tJob.trace.trace(jobHookRequestMetric.success);
- tJob.trace.trace(
- `all queued up and weady to go :D !! ${value}`,
- );
- return;
- }
-
- tJob.trace.trace(
- value.source === ErrorSource.SYSTEM
- ? jobHookRequestMetric.failure
- : jobHookRequestMetric.warn,
- );
- tJob.trace.addTrace(value.source).trace(`${value}`);
- }),
- ),
- )
- .map(
- TraceUtil.promiseify(
- (tEitherQueuedJob) =>
- new JsonResponse(r, tEitherQueuedJob.get(), {
- status: tEitherQueuedJob
- .get()
- .fold(({ isRight, value }) =>
- isRight ? 200 : value.status,
- ),
- }),
- ),
- )
+ public processHook(r: ITraceable<PenguenoRequest, ServerTrace>) {
+ return this.trace(r)
+ .map(jsonModel(jobJsonTransformer))
+ .map(async (tEitherJobJson) => {
+ const eitherJob = await tEitherJobJson.get();
+ return eitherJob.flatMapAsync(async (job) => {
+ const eitherQueued = await tEitherJobJson
+ .move(job)
+ .map(this.queuer.queue)
.get();
- }
+ return eitherQueued.mapLeft((e) => new PenguenoError(e.message, 500));
+ });
+ })
+ .peek(
+ TraceUtil.promiseify((tJob) =>
+ tJob.get().fold(({ isRight, value }) => {
+ if (isRight) {
+ tJob.trace.trace(jobHookRequestMetric.success);
+ tJob.trace.trace(`all queued up and weady to go :D !! ${value}`);
+ return;
+ }
+
+ tJob.trace.trace(
+ value.source === ErrorSource.SYSTEM
+ ? jobHookRequestMetric.failure
+ : jobHookRequestMetric.warn,
+ );
+ tJob.trace.addTrace(value.source).trace(`${value}`);
+ }),
+ ),
+ )
+ .map(
+ TraceUtil.promiseify(
+ (tEitherQueuedJob) =>
+ new JsonResponse(r, tEitherQueuedJob.get(), {
+ status: tEitherQueuedJob
+ .get()
+ .fold(({ isRight, value }) => (isRight ? 200 : value.status)),
+ }),
+ ),
+ )
+ .get();
+ }
}
// -- </job.hook> --
@@ -123,82 +113,72 @@ export class JobHookActivityImpl implements IJobHookActivity {
type QueuePosition = string;
export class QueueError extends Error {}
export interface IJobQueuer<TJob> {
- queue: Mapper<TJob, Promise<IEither<QueueError, QueuePosition>>>;
+ queue: Mapper<TJob, Promise<IEither<QueueError, QueuePosition>>>;
}
export class LaminarJobQueuer
- implements IJobQueuer<ITraceable<Job, ServerTrace>>
+ implements IJobQueuer<ITraceable<Job, ServerTrace>>
{
- constructor(private readonly queuePositionPrefix: string) {}
+ constructor(private readonly queuePositionPrefix: string) {}
- private static GetJobTypeTrace = (jobType: string) =>
- `LaminarJobQueue.Queue.${jobType}`;
- private static JobTypeMetrics = memoize((jobType: string) =>
- Metric.fromName(LaminarJobQueuer.GetJobTypeTrace(jobType)),
- );
+ private static GetJobTypeTrace = (jobType: string) =>
+ `LaminarJobQueue.Queue.${jobType}`;
+ private static JobTypeMetrics = memoize((jobType: string) =>
+ Metric.fromName(LaminarJobQueuer.GetJobTypeTrace(jobType)),
+ );
- public queue(j: ITraceable<Job, ServerTrace>) {
- const { type: jobType } = j.get();
- const trace = LaminarJobQueuer.GetJobTypeTrace(jobType);
- const metric = LaminarJobQueuer.JobTypeMetrics(trace);
+ public queue(j: ITraceable<Job, ServerTrace>) {
+ const { type: jobType } = j.get();
+ const trace = LaminarJobQueuer.GetJobTypeTrace(jobType);
+ const metric = LaminarJobQueuer.JobTypeMetrics(trace);
- return j
- .bimap(TraceUtil.withTrace(trace))
- .bimap(TraceUtil.withMetricTrace(metric))
- .map((j) => {
- const { type: jobType, arguments: args } = j.get();
- const laminarCommand = [
- "laminarc",
- "queue",
- jobType,
- ...Object.entries(args).map(
- ([key, val]) => `"${key}"="${val}"`,
- ),
- ];
- return laminarCommand;
- })
- .peek((c) =>
- c.trace.trace(
- `im so excited to see how this queue job will end!! (>ᴗ<): ${c
- .get()
- .toString()}`,
- ),
- )
- .map(getStdout)
- .peek(
- TraceUtil.promiseify((q) =>
- q.trace.trace(
- q
- .get()
- .fold(({ isLeft }) =>
- isLeft ? metric.failure : metric.success,
- ),
- ),
- ),
- )
- .map(
- TraceUtil.promiseify((q) =>
- q.get().fold(({ isLeft, value }) => {
- if (isLeft) {
- q.trace
- .addTrace(LogLevel.ERROR)
- .trace(value.toString());
- return Either.left<Error, string>(value);
- }
- q.trace
- .addTrace(LogLevel.DEBUG)
- .trace(`stdout ${value}`);
- const [jobName, jobId] = value.split(":");
- const jobUrl = `${this.queuePositionPrefix}/jobs/${jobName}/${jobId}`;
+ return j
+ .bimap(TraceUtil.withTrace(trace))
+ .bimap(TraceUtil.withMetricTrace(metric))
+ .map((j) => {
+ const { type: jobType, arguments: args } = j.get();
+ const laminarCommand = [
+ "laminarc",
+ "queue",
+ jobType,
+ ...Object.entries(args).map(([key, val]) => `"${key}"="${val}"`),
+ ];
+ return laminarCommand;
+ })
+ .peek((c) =>
+ c.trace.trace(
+ `im so excited to see how this queue job will end!! (>ᴗ<): ${c
+ .get()
+ .toString()}`,
+ ),
+ )
+ .map(getStdout)
+ .peek(
+ TraceUtil.promiseify((q) =>
+ q.trace.trace(
+ q
+ .get()
+ .fold(({ isLeft }) => (isLeft ? metric.failure : metric.success)),
+ ),
+ ),
+ )
+ .map(
+ TraceUtil.promiseify((q) =>
+ q.get().fold(({ isLeft, value }) => {
+ if (isLeft) {
+ q.trace.addTrace(LogLevel.ERROR).trace(value.toString());
+ return Either.left<Error, string>(value);
+ }
+ q.trace.addTrace(LogLevel.DEBUG).trace(`stdout ${value}`);
+ const [jobName, jobId] = value.split(":");
+ const jobUrl = `${this.queuePositionPrefix}/jobs/${jobName}/${jobId}`;
- q.trace.trace(
- `all queued up and weady to go~ (˘ω˘) => ${jobUrl}`,
- );
- return Either.right<Error, string>(jobUrl);
- }),
- ),
- )
- .get();
- }
+ q.trace.trace(`all queued up and weady to go~ (˘ω˘) => ${jobUrl}`);
+ return Either.right<Error, string>(jobUrl);
+ }),
+ ),
+ )
+ .get();
+ }
}
// -- </job.queuer> --
diff --git a/server/mod.ts b/server/mod.ts
index 9dc57aa..1fd4e99 100644
--- a/server/mod.ts
+++ b/server/mod.ts
@@ -5,12 +5,18 @@ export * from "./health.ts";
export * from "./job.ts";
import { CiHookServer } from "./mod.ts";
+import { Either, type IEither } from "@emprespresso/pengueno";
const server = new CiHookServer();
-export const runServer = (port: number, host: string) => {
+export const runServer = (
+ port: number,
+ host: string,
+): Promise<IEither<Error, void>> => {
const serverConfig = {
host,
port,
};
- return Deno.serve(serverConfig, (req) => server.serve(req)).finished;
+ return Either.fromFailable<Error, Deno.HttpServer>(() =>
+ Deno.serve(serverConfig, (req) => server.serve(req)),
+ ).flatMapAsync((server) => Either.fromFailableAsync(server.finished));
};
diff --git a/u/fn/either.ts b/u/fn/either.ts
index 124557c..bf90f16 100644
--- a/u/fn/either.ts
+++ b/u/fn/either.ts
@@ -4,115 +4,111 @@ type IEitherTag = "IEither";
const iEitherTag: IEitherTag = "IEither";
export interface _Either<LeftT, RightT, T> {
- readonly isLeft: LeftT;
- readonly isRight: RightT;
- readonly value: T;
+ readonly isLeft: LeftT;
+ readonly isRight: RightT;
+ readonly value: T;
}
export type Left<E> = _Either<true, false, E>;
export type Right<T> = _Either<false, true, T>;
export interface IEither<E, T> {
- readonly _tag: IEitherTag;
-
- mapBoth: <_E, _T>(
- errBranch: Mapper<E, _E>,
- okBranch: Mapper<T, _T>,
- ) => IEither<_E, _T>;
- fold: <_T>(folder: Mapper<Left<E> | Right<T>, _T>) => _T;
- moveRight: <_T>(t: _T) => IEither<E, _T>;
- mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>;
- mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>;
- flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>;
- flatMapAsync: <_T>(
- mapper: Mapper<T, Promise<IEither<E, _T>>>,
- ) => Promise<IEither<E, _T>>;
+ readonly _tag: IEitherTag;
+
+ mapBoth: <_E, _T>(
+ errBranch: Mapper<E, _E>,
+ okBranch: Mapper<T, _T>,
+ ) => IEither<_E, _T>;
+ fold: <_T>(folder: Mapper<Left<E> | Right<T>, _T>) => _T;
+ moveRight: <_T>(t: _T) => IEither<E, _T>;
+ mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>;
+ mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>;
+ flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>;
+ flatMapAsync: <_T>(
+ mapper: Mapper<T, Promise<IEither<E, _T>>>,
+ ) => Promise<IEither<E, _T>>;
}
export class Either<E, T> implements IEither<E, T> {
- private readonly self: Left<E> | Right<T>;
-
- private constructor(
- err?: E,
- ok?: T,
- public readonly _tag: IEitherTag = iEitherTag,
- ) {
- this.self = <Left<E> | Right<T>>{
- isLeft: typeof err !== "undefined",
- isRight: typeof ok !== "undefined",
- value: typeof err !== "undefined" ? err : ok!,
- };
+ private readonly self: Left<E> | Right<T>;
+
+ private constructor(
+ err?: E,
+ ok?: T,
+ public readonly _tag: IEitherTag = iEitherTag,
+ ) {
+ this.self = <Left<E> | Right<T>>{
+ isLeft: typeof err !== "undefined",
+ isRight: typeof ok !== "undefined",
+ value: typeof err !== "undefined" ? err : ok!,
+ };
+ }
+
+ public moveRight<_T>(t: _T) {
+ return this.mapRight(() => t);
+ }
+
+ public fold<_T>(folder: Mapper<Left<E> | Right<T>, _T>): _T {
+ return folder(this.self);
+ }
+
+ public mapBoth<_E, _T>(
+ errBranch: Mapper<E, _E>,
+ okBranch: Mapper<T, _T>,
+ ): IEither<_E, _T> {
+ if (this.self.isLeft) return Either.left(errBranch(this.self.value));
+ return Either.right(okBranch(this.self.value));
+ }
+
+ public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> {
+ if (this.self.isRight) return mapper(this.self.value);
+ return Either.left<E, _T>(this.self.value);
+ }
+
+ public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> {
+ if (this.self.isRight) return Either.right<E, _T>(mapper(this.self.value));
+ return Either.left<E, _T>(this.self.value);
+ }
+
+ public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> {
+ if (this.self.isLeft) return Either.left<_E, T>(mapper(this.self.value));
+ return Either.right<_E, T>(this.self.value);
+ }
+
+ public async flatMapAsync<_T>(
+ mapper: Mapper<T, Promise<IEither<E, _T>>>,
+ ): Promise<IEither<E, _T>> {
+ if (this.self.isLeft) {
+ return Promise.resolve(Either.left<E, _T>(this.self.value));
}
-
- public moveRight<_T>(t: _T) {
- return this.mapRight(() => t);
- }
-
- public fold<_T>(folder: Mapper<Left<E> | Right<T>, _T>): _T {
- return folder(this.self);
- }
-
- public mapBoth<_E, _T>(
- errBranch: Mapper<E, _E>,
- okBranch: Mapper<T, _T>,
- ): IEither<_E, _T> {
- if (this.self.isLeft) return Either.left(errBranch(this.self.value));
- return Either.right(okBranch(this.self.value));
- }
-
- public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> {
- if (this.self.isRight) return mapper(this.self.value);
- return Either.left<E, _T>(this.self.value);
- }
-
- public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> {
- if (this.self.isRight)
- return Either.right<E, _T>(mapper(this.self.value));
- return Either.left<E, _T>(this.self.value);
- }
-
- public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> {
- if (this.self.isLeft)
- return Either.left<_E, T>(mapper(this.self.value));
- return Either.right<_E, T>(this.self.value);
- }
-
- public async flatMapAsync<_T>(
- mapper: Mapper<T, Promise<IEither<E, _T>>>,
- ): Promise<IEither<E, _T>> {
- if (this.self.isLeft) {
- return Promise.resolve(Either.left<E, _T>(this.self.value));
- }
- return await mapper(this.self.value).catch((err) =>
- Either.left<E, _T>(err),
- );
- }
-
- static left<E, T>(e: E): IEither<E, T> {
- return new Either<E, T>(e, undefined);
- }
- static right<E, T>(t: T): IEither<E, T> {
- return new Either<E, T>(undefined, t);
- }
-
- static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> {
- try {
- return Either.right<E, T>(s());
- } catch (e) {
- return Either.left<E, T>(e as E);
- }
+ return await mapper(this.self.value).catch((err) =>
+ Either.left<E, _T>(err),
+ );
+ }
+
+ static left<E, T>(e: E): IEither<E, T> {
+ return new Either<E, T>(e, undefined);
+ }
+ static right<E, T>(t: T): IEither<E, T> {
+ return new Either<E, T>(undefined, t);
+ }
+
+ static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> {
+ try {
+ return Either.right<E, T>(s());
+ } catch (e) {
+ return Either.left<E, T>(e as E);
}
+ }
- static async fromFailableAsync<E, T>(
- s: Promise<T>,
- ): Promise<IEither<E, T>> {
- try {
- return Either.right<E, T>(await s);
- } catch (e) {
- return Either.left<E, T>(e as E);
- }
+ static async fromFailableAsync<E, T>(s: Promise<T>): Promise<IEither<E, T>> {
+ try {
+ return Either.right<E, T>(await s);
+ } catch (e) {
+ return Either.left<E, T>(e as E);
}
+ }
}
export const isEither = <E, T>(o: unknown): o is IEither<E, T> => {
- return isObject(o) && "_tag" in o && o._tag === "IEither";
+ return isObject(o) && "_tag" in o && o._tag === "IEither";
};
diff --git a/u/process/argv.ts b/u/process/argv.ts
index 7190531..8e85477 100644
--- a/u/process/argv.ts
+++ b/u/process/argv.ts
@@ -37,11 +37,11 @@ export const argv = <K extends string, V extends string>(
.map((arg) => [arg, getArg(arg, argv)] as [K, IEither<Error, V>])
.map(([arg, specified]): [K, IEither<Error, V>] => [
arg,
- specified.fold(({ isLeft, isRight, value}): IEither<Error, V> => {
- if (isRight) {
- return Either.right(value);
- }
- const hasDefaultVal = isLeft && defaultArgs && arg in defaultArgs;
+ specified.fold(({ isLeft, isRight, value }): IEither<Error, V> => {
+ if (isRight) {
+ return Either.right(value);
+ }
+ const hasDefaultVal = isLeft && defaultArgs && arg in defaultArgs;
if (hasDefaultVal) {
return Either.right(defaultArgs[arg]!);
}
diff --git a/u/server/activity/fourohfour.ts b/u/server/activity/fourohfour.ts
index ed8c7eb..33cfe5f 100644
--- a/u/server/activity/fourohfour.ts
+++ b/u/server/activity/fourohfour.ts
@@ -7,12 +7,13 @@ import {
} from "@emprespresso/pengueno";
const messages = [
- "D: Meow-t found! Your API call ran away!",
- "404-bidden! But like...in a cute way >:3 !",
- ":o Your data went on a paw-sible vacation!",
+ "D: meow-t found! your api call ran away!",
+ "404-bidden! but like...in a cute way >:3 !",
+ ":< your data went on a paw-sible vacation!",
"uwu~ not found, but found our hearts instead!",
];
-const randomFourOhFour = () => messages[Math.random() * messages.length];
+const randomFourOhFour = () =>
+ messages[Math.floor(Math.random() * messages.length)];
export interface IFourOhFourActivity {
fourOhFour: IActivity;
diff --git a/u/server/request.ts b/u/server/request.ts
index c857f88..5dd9d7b 100644
--- a/u/server/request.ts
+++ b/u/server/request.ts
@@ -1,4 +1,5 @@
-import { LogMetricTraceable } from "@emprespresso/pengueno";
+import { LogMetricTraceable, LogTraceable } from "@emprespresso/pengueno";
+import { TraceUtil } from "../trace/util.ts";
const greetings = [
"hewwo :D",
@@ -39,9 +40,11 @@ export class PenguenoRequest extends Request {
const id = crypto.randomUUID();
const url = new URL(request.url);
const { pathname } = url;
- const traceSupplier = () => `[${id} <- ${request.method}'d @ ${pathname}]`;
- return LogMetricTraceable.from(
+ const logTraceable = LogTraceable.of(
new PenguenoRequest(url, { ...request }, id, new Date()),
- ).bimap((_request) => [_request.get(), traceSupplier]);
+ ).bimap(
+ TraceUtil.withTrace(`Id=${id} Method=${request.method} Path=${pathname}`),
+ );
+ return LogMetricTraceable.ofLogTraceable(logTraceable);
}
}
diff --git a/u/server/response.ts b/u/server/response.ts
index 4531157..629dbb5 100644
--- a/u/server/response.ts
+++ b/u/server/response.ts
@@ -28,12 +28,12 @@ const getResponse = (
};
};
-const ResponseCodeMetrics = [1, 2, 3, 4, 5].map((x) =>
+const ResponseCodeMetrics = [0, 1, 2, 3, 4, 5].map((x) =>
Metric.fromName(`response.${x}xx`),
);
export const getResponseMetric = (status: number) => {
- const index = Math.floor(status / 100) + 1;
- return ResponseCodeMetrics[index] ?? ResponseCodeMetrics[5 - 1];
+ const index = Math.floor(status / 100);
+ return ResponseCodeMetrics[index] ?? ResponseCodeMetrics[5];
};
export class PenguenoResponse extends Response {
@@ -67,7 +67,9 @@ export class JsonResponse extends PenguenoResponse {
super(
req,
JSON.stringify(
- e.fold(({ isLeft, value }) => (isLeft ? { error: value } : { ok: value })),
+ e.fold(({ isLeft, value }) =>
+ isLeft ? { error: value } : { ok: value },
+ ),
),
optsWithJsonContentType,
);
diff --git a/u/trace/itrace.ts b/u/trace/itrace.ts
index ed707c5..35164b5 100644
--- a/u/trace/itrace.ts
+++ b/u/trace/itrace.ts
@@ -9,29 +9,29 @@ export interface ITrace<TraceWith> {
}
export type ITraceableTuple<T, TraceWith> = [T, BaseTraceWith | TraceWith];
-export type ITraceableMapper<T, U, TraceWith, W = ITraceable<T, TraceWith>> = (
+export type ITraceableMapper<T, _T, TraceWith, W = ITraceable<T, TraceWith>> = (
w: W,
-) => U;
+) => _T;
export interface ITraceable<T, Trace = BaseTraceWith> {
readonly trace: ITrace<Trace>;
get: Supplier<T>;
- move: <U>(u: U) => ITraceable<U, Trace>;
- map: <U>(mapper: ITraceableMapper<T, U, Trace>) => ITraceable<U, Trace>;
- bimap: <U>(
+ move: <_T>(u: _T) => ITraceable<_T, Trace>;
+ map: <_T>(mapper: ITraceableMapper<T, _T, Trace>) => ITraceable<_T, Trace>;
+ bimap: <_T>(
mapper: ITraceableMapper<
T,
- ITraceableTuple<U, Array<Trace> | Trace>,
+ ITraceableTuple<_T, Array<Trace> | Trace>,
Trace
>,
- ) => ITraceable<U, Trace>;
+ ) => ITraceable<_T, Trace>;
peek: (peek: ITraceableMapper<T, void, Trace>) => ITraceable<T, Trace>;
- flatMap: <U>(
- mapper: ITraceableMapper<T, ITraceable<U, Trace>, Trace>,
- ) => ITraceable<U, Trace>;
- flatMapAsync<U>(
- mapper: ITraceableMapper<T, Promise<ITraceable<U, Trace>>, Trace>,
- ): ITraceable<Promise<U>, Trace>;
+ flatMap: <_T>(
+ mapper: ITraceableMapper<T, ITraceable<_T, Trace>, Trace>,
+ ) => ITraceable<_T, Trace>;
+ flatMapAsync<_T>(
+ mapper: ITraceableMapper<T, Promise<ITraceable<_T, Trace>>, Trace>,
+ ): ITraceable<Promise<_T>, Trace>;
}
export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> {
@@ -40,20 +40,20 @@ export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> {
public readonly trace: ITrace<TraceWith>,
) {}
- public map<U>(mapper: ITraceableMapper<T, U, TraceWith>) {
+ public map<_T>(mapper: ITraceableMapper<T, _T, TraceWith>) {
const result = mapper(this);
return new TraceableImpl(result, this.trace);
}
- public flatMap<U>(
- mapper: ITraceableMapper<T, ITraceable<U, TraceWith>, TraceWith>,
- ): ITraceable<U, TraceWith> {
+ public flatMap<_T>(
+ mapper: ITraceableMapper<T, ITraceable<_T, TraceWith>, TraceWith>,
+ ): ITraceable<_T, TraceWith> {
return mapper(this);
}
- public flatMapAsync<U>(
- mapper: ITraceableMapper<T, Promise<ITraceable<U, TraceWith>>, TraceWith>,
- ): ITraceable<Promise<U>, TraceWith> {
+ public flatMapAsync<_T>(
+ mapper: ITraceableMapper<T, Promise<ITraceable<_T, TraceWith>>, TraceWith>,
+ ): ITraceable<Promise<_T>, TraceWith> {
return new TraceableImpl(
mapper(this).then((t) => t.get()),
this.trace,
@@ -65,14 +65,14 @@ export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> {
return this;
}
- public move<Tt>(t: Tt): ITraceable<Tt, TraceWith> {
+ public move<_T>(t: _T): ITraceable<_T, TraceWith> {
return this.map(() => t);
}
- public bimap<U>(
+ public bimap<_T>(
mapper: ITraceableMapper<
T,
- ITraceableTuple<U, Array<TraceWith> | TraceWith>,
+ ITraceableTuple<_T, Array<TraceWith> | TraceWith>,
TraceWith
>,
) {
diff --git a/u/trace/logger.ts b/u/trace/logger.ts
index 5890545..4f29839 100644
--- a/u/trace/logger.ts
+++ b/u/trace/logger.ts
@@ -95,8 +95,8 @@ export class LogTrace implements ITrace<LogTraceSupplier> {
level: Math.max(logLevelOrder.indexOf(val), acc.level),
};
}
- const prefix = [acc.line, val].join(" ");
- return { ...acc, prefix };
+ const line = [acc.line, val].join(" ");
+ return { ...acc, line };
},
{ line: "", level: -1 },
);
diff --git a/u/trace/metrics.ts b/u/trace/metrics.ts
index 69322b9..822fc38 100644
--- a/u/trace/metrics.ts
+++ b/u/trace/metrics.ts
@@ -8,8 +8,8 @@ import {
} from "@emprespresso/pengueno";
export enum Unit {
- COUNT,
- MILLISECONDS,
+ COUNT = "COUNT",
+ MILLISECONDS = "MILLISECONDS",
}
export interface IMetric {
diff --git a/u/trace/trace.ts b/u/trace/trace.ts
index 03605c2..6cad5b0 100644
--- a/u/trace/trace.ts
+++ b/u/trace/trace.ts
@@ -1,6 +1,7 @@
import {
isMetricsTraceSupplier,
type ITrace,
+ type ITraceable,
type ITraceWith,
LogTrace,
type LogTraceSupplier,
@@ -12,16 +13,14 @@ import {
export class LogTraceable<T> extends TraceableImpl<T, LogTraceSupplier> {
public static LogTrace = new LogTrace();
- static from<T>(t: T) {
+ static of<T>(t: T) {
return new LogTraceable(t, LogTraceable.LogTrace);
}
}
const getEmbeddedMetricConsumer =
- (logTrace: LogTrace) => (metrics: Array<MetricValue>) =>
- logTrace
- .addTrace("<metrics>")
- .trace(JSON.stringify(metrics, null, 2) + "</metrics>");
+ (logTrace: ITrace<LogTraceSupplier>) => (metrics: Array<MetricValue>) =>
+ logTrace.trace(`<metrics>${JSON.stringify(metrics, null)}</metrics>`);
export class EmbeddedMetricsTraceable<T> extends TraceableImpl<
T,
MetricsTraceSupplier
@@ -30,11 +29,8 @@ export class EmbeddedMetricsTraceable<T> extends TraceableImpl<
getEmbeddedMetricConsumer(LogTraceable.LogTrace),
);
- static from<T>(t: T) {
- return new EmbeddedMetricsTraceable(
- t,
- EmbeddedMetricsTraceable.MetricsTrace,
- );
+ static of<T>(t: T, metricsTrace = EmbeddedMetricsTraceable.MetricsTrace) {
+ return new EmbeddedMetricsTraceable(t, metricsTrace);
}
}
@@ -72,12 +68,16 @@ export class LogMetricTraceable<T> extends TraceableImpl<
T,
MetricsTraceSupplier | LogTraceSupplier
> {
- public static LogMetricTrace = new LogMetricTrace(
- LogTraceable.LogTrace,
- EmbeddedMetricsTraceable.MetricsTrace,
- );
+ static ofLogTraceable<T>(t: ITraceable<T, LogTraceSupplier>) {
+ const metricsTrace = new MetricsTrace(getEmbeddedMetricConsumer(t.trace));
+ return new LogMetricTraceable(
+ t.get(),
+ new LogMetricTrace(t.trace, metricsTrace),
+ );
+ }
- static from<T>(t: T) {
- return new LogMetricTraceable(t, LogMetricTraceable.LogMetricTrace);
+ static of<T>(t: T) {
+ const logTrace = LogTraceable.of(t);
+ return LogMetricTraceable.ofLogTraceable(logTrace);
}
}
diff --git a/worker/executor.ts b/worker/executor.ts
index ea580eb..ea79995 100644
--- a/worker/executor.ts
+++ b/worker/executor.ts
@@ -86,7 +86,9 @@ export const executePipeline = (
.get(),
),
);
- const failures = jobResults.filter((e) => e.fold(( { isLeft }) => isLeft));
+ const failures = jobResults.filter((e) =>
+ e.fold(({ isLeft }) => isLeft),
+ );
if (failures.length > 0) {
tJobs.trace.trace(pipelinesMetric.failure);
return Either.left(new Error(failures.toString()));
diff --git a/worker/jobs/ci_pipeline.run b/worker/jobs/ci_pipeline.run
index 03d9d6d..46237f6 100644
--- a/worker/jobs/ci_pipeline.run
+++ b/worker/jobs/ci_pipeline.run
@@ -3,6 +3,7 @@
import {
type Command,
Either,
+ LogTraceable,
getRequiredEnvVars,
getStdout,
isObject,
@@ -32,8 +33,8 @@ const eitherJob = getRequiredEnvVars(["remote", "refname", "rev"])
));
const ciRunMetric = Metric.fromName("checkout_ci.run");
-const trace = `checkout_ci.${run}`;
-await LogMetricTraceable.from(eitherJob).bimap(TraceUtil.withTrace(trace))
+const _logJob = LogTraceable.of(eitherJob).bimap(TraceUtil.withTrace(`checkout_ci.${run}`));
+await LogMetricTraceable.ofLogTraceable(_logJob)
.bimap(TraceUtil.withMetricTrace(ciRunMetric))
.map((tEitherJob) =>
tEitherJob.get().flatMapAsync((ciJob) => {
diff --git a/worker/scripts/ansible_playbook b/worker/scripts/ansible_playbook
index f2cd4b9..026f892 100755
--- a/worker/scripts/ansible_playbook
+++ b/worker/scripts/ansible_playbook
@@ -5,6 +5,7 @@ import {
getRequiredEnvVars,
getStdout,
type IEither,
+ LogTraceable,
LogMetricTraceable,
Metric,
prependWith,
@@ -28,9 +29,8 @@ const eitherVault = Bitwarden.getConfigFromEnvironment()
.mapRight((config) => new Bitwarden(config));
const playbookMetric = Metric.fromName("ansiblePlaybook.playbook");
-await LogMetricTraceable.from(eitherJob)
- .bimap(TraceUtil.withTrace("ansible_playbook"))
- .bimap(TraceUtil.withMetricTrace(playbookMetric))
+const _logJob = LogTraceable.of(eitherJob).bimap(TraceUtil.withTrace("ansible_playbook"));
+await LogMetricTraceable.ofLogTraceable(_logJob).bimap(TraceUtil.withMetricTrace(playbookMetric))
.peek((tEitherJob) =>
tEitherJob.trace.trace("starting ansible playbook job! (⑅˘꒳˘)")
)
diff --git a/worker/scripts/build_docker_image b/worker/scripts/build_docker_image
index 2e19111..f2fa522 100755
--- a/worker/scripts/build_docker_image
+++ b/worker/scripts/build_docker_image
@@ -4,6 +4,7 @@ import {
getRequiredEnvVars,
getStdout,
LogLevel,
+ LogTraceable,
LogMetricTraceable,
Metric,
TraceUtil,
@@ -34,14 +35,14 @@ const eitherVault = Bitwarden.getConfigFromEnvironment()
const buildImageMetric = Metric.fromName("dockerImage.build");
const loginMetric = Metric.fromName("dockerRegistry.login");
-await LogMetricTraceable.from(eitherJob)
- .bimap(
+const _logJob = LogTraceable.of(eitherJob).bimap(
(tEitherJob) => {
const trace = "build_docker_image." +
tEitherJob.get().fold(({ isRight, value }) => isRight ? value.arguments.buildTarget : "");
return [tEitherJob.get(), trace];
},
- )
+ );
+await LogMetricTraceable.ofLogTraceable(_logJob)
.bimap(TraceUtil.withMetricTrace(buildImageMetric))
.bimap(TraceUtil.withMetricTrace(loginMetric))
.peek((tEitherJob) =>
diff --git a/worker/secret.ts b/worker/secret.ts
index f5ae93f..951c539 100644
--- a/worker/secret.ts
+++ b/worker/secret.ts
@@ -1,36 +1,36 @@
import {
- Either,
- getRequiredEnvVars,
- getStdout,
- type IEither,
- type ITraceable,
- type LogMetricTraceSupplier,
- Metric,
- TraceUtil,
+ Either,
+ getRequiredEnvVars,
+ getStdout,
+ type IEither,
+ type ITraceable,
+ type LogMetricTraceSupplier,
+ Metric,
+ TraceUtil,
} from "@emprespresso/pengueno";
// -- <ISecret> --
export interface LoginItem {
- login: {
- username: string;
- password: string;
- };
+ login: {
+ username: string;
+ password: string;
+ };
}
export interface SecureNote {
- notes: string;
+ notes: string;
}
export type SecretItem = LoginItem | SecureNote;
export interface IVault<TClient, TKey, TItemId> {
- unlock: (client: TClient) => Promise<IEither<Error, TKey>>;
- lock: (client: TClient, key: TKey) => Promise<IEither<Error, TKey>>;
+ unlock: (client: TClient) => Promise<IEither<Error, TKey>>;
+ lock: (client: TClient, key: TKey) => Promise<IEither<Error, TKey>>;
- fetchSecret: <T extends SecretItem>(
- client: TClient,
- key: TKey,
- item: TItemId,
- ) => Promise<IEither<Error, T>>;
+ fetchSecret: <T extends SecretItem>(
+ client: TClient,
+ key: TKey,
+ item: TItemId,
+ ) => Promise<IEither<Error, T>>;
}
// -- </ISecret> --
@@ -39,178 +39,156 @@ type TClient = ITraceable<unknown, LogMetricTraceSupplier>;
type TKey = string;
type TItemId = string;
export class Bitwarden implements IVault<TClient, TKey, TItemId> {
- constructor(private readonly config: BitwardenConfig) {}
+ constructor(private readonly config: BitwardenConfig) {}
- public unlock(client: TClient) {
- return client
- .move(this.config)
- .bimap(TraceUtil.withMetricTrace(Bitwarden.loginMetric))
- .flatMap((tConfig) =>
- tConfig
- .move(`bw config server ${tConfig.get().server}`)
- .map(getStdout),
- )
- .map(async (tEitherWithConfig) => {
- const eitherWithConfig = await tEitherWithConfig.get();
- tEitherWithConfig.trace.trace("logging in~ ^.^");
- return eitherWithConfig.flatMapAsync((_) =>
- tEitherWithConfig
- .move("bw login --apikey --quiet")
- .map(getStdout)
- .get(),
- );
- })
- .peek(async (tEitherWithAuthd) => {
- const eitherWithAuthd = await tEitherWithAuthd.get();
- return tEitherWithAuthd.trace.trace(
- eitherWithAuthd.fold(
- ({ isLeft }) =>
- Bitwarden.loginMetric[
- isLeft ? "failure" : "success"
- ],
- ),
- );
- })
- .map(async (tEitherWithAuthd) => {
- const eitherWithAuthd = await tEitherWithAuthd.get();
- tEitherWithAuthd.trace.trace(
- "unlocking the secret vault~ (◕ᴗ◕✿)",
- );
- return eitherWithAuthd.flatMapAsync((_) =>
- tEitherWithAuthd
- .move("bw unlock --passwordenv BW_PASSWORD --raw")
- .map(getStdout)
- .get(),
- );
- })
- .peek(async (tEitherWithSession) => {
- const eitherWithAuthd = await tEitherWithSession.get();
- return tEitherWithSession.trace.trace(
- eitherWithAuthd.fold(
- ({ isLeft }) =>
- Bitwarden.unlockVaultMetric[
- isLeft ? "failure" : "success"
- ],
- ),
- );
- })
- .get();
- }
+ public unlock(client: TClient) {
+ return client
+ .move(this.config)
+ .bimap(TraceUtil.withMetricTrace(Bitwarden.loginMetric))
+ .flatMap((tConfig) =>
+ tConfig.move(`bw config server ${tConfig.get().server}`).map(getStdout),
+ )
+ .map(async (tEitherWithConfig) => {
+ const eitherWithConfig = await tEitherWithConfig.get();
+ tEitherWithConfig.trace.trace("logging in~ ^.^");
+ return eitherWithConfig.flatMapAsync((_) =>
+ tEitherWithConfig
+ .move("bw login --apikey --quiet")
+ .map(getStdout)
+ .get(),
+ );
+ })
+ .peek(async (tEitherWithAuthd) => {
+ const eitherWithAuthd = await tEitherWithAuthd.get();
+ return tEitherWithAuthd.trace.trace(
+ eitherWithAuthd.fold(
+ ({ isLeft }) =>
+ Bitwarden.loginMetric[isLeft ? "failure" : "success"],
+ ),
+ );
+ })
+ .map(async (tEitherWithAuthd) => {
+ const eitherWithAuthd = await tEitherWithAuthd.get();
+ tEitherWithAuthd.trace.trace("unlocking the secret vault~ (◕ᴗ◕✿)");
+ return eitherWithAuthd.flatMapAsync((_) =>
+ tEitherWithAuthd
+ .move("bw unlock --passwordenv BW_PASSWORD --raw")
+ .map(getStdout)
+ .get(),
+ );
+ })
+ .peek(async (tEitherWithSession) => {
+ const eitherWithAuthd = await tEitherWithSession.get();
+ return tEitherWithSession.trace.trace(
+ eitherWithAuthd.fold(
+ ({ isLeft }) =>
+ Bitwarden.unlockVaultMetric[isLeft ? "failure" : "success"],
+ ),
+ );
+ })
+ .get();
+ }
- public fetchSecret<T extends SecretItem>(
- client: TClient,
- key: string,
- item: string,
- ): Promise<IEither<Error, T>> {
- return client
- .move(key)
- .bimap(TraceUtil.withMetricTrace(Bitwarden.fetchSecretMetric))
- .peek((tSession) =>
- tSession.trace.trace(`looking for your secret ${item} (⑅˘꒳˘)`),
- )
- .flatMap((tSession) =>
- tSession
- .move("bw list items")
- .map((listCmd) =>
- getStdout(listCmd, {
- env: { BW_SESSION: tSession.get() },
- }),
- ),
- )
- .map(
- TraceUtil.promiseify((tEitherItemsJson) =>
- tEitherItemsJson
- .get()
- .flatMap(
- (
- itemsJson,
- ): IEither<Error, Array<T & { name: string }>> =>
- Either.fromFailable(() =>
- JSON.parse(itemsJson),
- ),
- )
- .flatMap((itemsList): IEither<Error, T> => {
- const secret = itemsList.find(
- ({ name }) => name === item,
- );
- if (!secret) {
- return Either.left(
- new Error(
- `couldn't find the item ${item} (。•́︿•̀。)`,
- ),
- );
- }
- return Either.right(secret);
- }),
- ),
+ public fetchSecret<T extends SecretItem>(
+ client: TClient,
+ key: string,
+ item: string,
+ ): Promise<IEither<Error, T>> {
+ return client
+ .move(key)
+ .bimap(TraceUtil.withMetricTrace(Bitwarden.fetchSecretMetric))
+ .peek((tSession) =>
+ tSession.trace.trace(`looking for your secret ${item} (⑅˘꒳˘)`),
+ )
+ .flatMap((tSession) =>
+ tSession.move("bw list items").map((listCmd) =>
+ getStdout(listCmd, {
+ env: { BW_SESSION: tSession.get() },
+ }),
+ ),
+ )
+ .map(
+ TraceUtil.promiseify((tEitherItemsJson) =>
+ tEitherItemsJson
+ .get()
+ .flatMap(
+ (itemsJson): IEither<Error, Array<T & { name: string }>> =>
+ Either.fromFailable(() => JSON.parse(itemsJson)),
)
- .peek(async (tEitherWithSecret) => {
- const eitherWithSecret = await tEitherWithSecret.get();
- return tEitherWithSecret.trace.trace(
- eitherWithSecret.fold(
- ({ isLeft }) =>
- Bitwarden.fetchSecretMetric[
- isLeft ? "failure" : "success"
- ],
- ),
+ .flatMap((itemsList): IEither<Error, T> => {
+ const secret = itemsList.find(({ name }) => name === item);
+ if (!secret) {
+ return Either.left(
+ new Error(`couldn't find the item ${item} (。•́︿•̀。)`),
);
- })
- .get();
- }
+ }
+ return Either.right(secret);
+ }),
+ ),
+ )
+ .peek(async (tEitherWithSecret) => {
+ const eitherWithSecret = await tEitherWithSecret.get();
+ return tEitherWithSecret.trace.trace(
+ eitherWithSecret.fold(
+ ({ isLeft }) =>
+ Bitwarden.fetchSecretMetric[isLeft ? "failure" : "success"],
+ ),
+ );
+ })
+ .get();
+ }
- public lock(client: TClient, key: TKey) {
- return client
- .move(key)
- .bimap(TraceUtil.withMetricTrace(Bitwarden.lockVaultMetric))
- .peek((tSession) =>
- tSession.trace.trace(`taking care of locking the vault :3`),
- )
- .flatMap((tSession) =>
- tSession
- .move("bw lock")
- .map((lockCmd) =>
- getStdout(lockCmd, {
- env: { BW_SESSION: tSession.get() },
- }),
- ),
- )
- .peek(async (tEitherWithLocked) => {
- const eitherWithLocked = await tEitherWithLocked.get();
- return eitherWithLocked.fold(({ isLeft }) => {
- tEitherWithLocked.trace.trace(
- Bitwarden.lockVaultMetric[isLeft ? "failure" : "success"],
- );
- if (isLeft) return;
- tEitherWithLocked.trace.trace(
- "all locked up and secure now~ (。•̀ᴗ-)✧",
- );
- });
- })
- .get();
- }
+ public lock(client: TClient, key: TKey) {
+ return client
+ .move(key)
+ .bimap(TraceUtil.withMetricTrace(Bitwarden.lockVaultMetric))
+ .peek((tSession) =>
+ tSession.trace.trace(`taking care of locking the vault :3`),
+ )
+ .flatMap((tSession) =>
+ tSession.move("bw lock").map((lockCmd) =>
+ getStdout(lockCmd, {
+ env: { BW_SESSION: tSession.get() },
+ }),
+ ),
+ )
+ .peek(async (tEitherWithLocked) => {
+ const eitherWithLocked = await tEitherWithLocked.get();
+ return eitherWithLocked.fold(({ isLeft }) => {
+ tEitherWithLocked.trace.trace(
+ Bitwarden.lockVaultMetric[isLeft ? "failure" : "success"],
+ );
+ if (isLeft) return;
+ tEitherWithLocked.trace.trace(
+ "all locked up and secure now~ (。•̀ᴗ-)✧",
+ );
+ });
+ })
+ .get();
+ }
- public static getConfigFromEnvironment(): IEither<Error, BitwardenConfig> {
- return getRequiredEnvVars([
- "BW_SERVER",
- "BW_CLIENTSECRET",
- "BW_CLIENTID",
- "BW_PASSWORD",
- ]).mapRight(({ BW_SERVER, BW_CLIENTSECRET, BW_CLIENTID }) => ({
- clientId: BW_CLIENTID,
- secret: BW_CLIENTSECRET,
- server: BW_SERVER,
- }));
- }
+ public static getConfigFromEnvironment(): IEither<Error, BitwardenConfig> {
+ return getRequiredEnvVars([
+ "BW_SERVER",
+ "BW_CLIENTSECRET",
+ "BW_CLIENTID",
+ "BW_PASSWORD",
+ ]).mapRight(({ BW_SERVER, BW_CLIENTSECRET, BW_CLIENTID }) => ({
+ clientId: BW_CLIENTID,
+ secret: BW_CLIENTSECRET,
+ server: BW_SERVER,
+ }));
+ }
- private static loginMetric = Metric.fromName("Bitwarden.login");
- private static unlockVaultMetric = Metric.fromName("Bitwarden.unlockVault");
- private static fetchSecretMetric = Metric.fromName("Bitwarden.fetchSecret");
- private static lockVaultMetric = Metric.fromName("Bitwarden.lock");
+ private static loginMetric = Metric.fromName("Bitwarden.login");
+ private static unlockVaultMetric = Metric.fromName("Bitwarden.unlockVault");
+ private static fetchSecretMetric = Metric.fromName("Bitwarden.fetchSecret");
+ private static lockVaultMetric = Metric.fromName("Bitwarden.lock");
}
export interface BitwardenConfig {
- server: string;
- secret: string;
- clientId: string;
+ server: string;
+ secret: string;
+ clientId: string;
}
// -- </IVault> --