diff options
author | Elizabeth <me@liz.coffee> | 2025-06-02 16:52:52 -0700 |
---|---|---|
committer | Elizabeth <me@liz.coffee> | 2025-06-02 16:52:52 -0700 |
commit | 98f5c21aa65bbbca01a186a754249335b4afef57 (patch) | |
tree | 0fc8e01a73f0a3be4534c11724ad2ff634b4fd2f /worker | |
parent | 373d9ec700c0097a22cf665a8e33cf48998d1dc2 (diff) | |
download | ci-98f5c21aa65bbbca01a186a754249335b4afef57.tar.gz ci-98f5c21aa65bbbca01a186a754249335b4afef57.zip |
fixup the Either monad a bit for type safetyp
Diffstat (limited to 'worker')
-rw-r--r-- | worker/executor.ts | 6 | ||||
-rw-r--r-- | worker/jobs/ci_pipeline.run | 6 | ||||
-rwxr-xr-x | worker/scripts/build_docker_image | 16 | ||||
-rw-r--r-- | worker/secret.ts | 343 |
4 files changed, 197 insertions, 174 deletions
diff --git a/worker/executor.ts b/worker/executor.ts index faa40a6..ea580eb 100644 --- a/worker/executor.ts +++ b/worker/executor.ts @@ -36,8 +36,8 @@ export const executeJob = (tJob: ITraceable<Job, LogMetricTraceSupplier>) => q .get() .fold( - (err, _val) => - jobTypeMetric(tJob.get().type)[err ? "failure" : "success"], + ({ isLeft }) => + jobTypeMetric(tJob.get().type)[isLeft ? "failure" : "success"], ), ), ), @@ -86,7 +86,7 @@ export const executePipeline = ( .get(), ), ); - const failures = jobResults.filter((e) => e.fold((err) => !!err)); + 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 434850c..03d9d6d 100644 --- a/worker/jobs/ci_pipeline.run +++ b/worker/jobs/ci_pipeline.run @@ -123,9 +123,9 @@ await LogMetricTraceable.from(eitherJob).bimap(TraceUtil.withTrace(trace)) ) .get() .then((e) => - e.flatMap(() => eitherJob).fold((err, val) => { - if (!val || err) throw err; - return Deno.remove(getWorkingDirectoryForCiJob(val), { recursive: true }); + e.flatMap(() => eitherJob).fold(({isLeft, isRight, value}) => { + if (isLeft || !isRight) throw value; + return Deno.remove(getWorkingDirectoryForCiJob(value), { recursive: true }); }) ); diff --git a/worker/scripts/build_docker_image b/worker/scripts/build_docker_image index dc0e961..2e19111 100755 --- a/worker/scripts/build_docker_image +++ b/worker/scripts/build_docker_image @@ -38,7 +38,7 @@ await LogMetricTraceable.from(eitherJob) .bimap( (tEitherJob) => { const trace = "build_docker_image." + - tEitherJob.get().fold((_, v) => v?.arguments.buildTarget ?? ""); + tEitherJob.get().fold(({ isRight, value }) => isRight ? value.arguments.buildTarget : ""); return [tEitherJob.get(), trace]; }, ) @@ -83,8 +83,8 @@ await LogMetricTraceable.from(eitherJob) .peek(async (tEitherWithAuthdRegistry) => { const eitherWithAuthdRegistry = await tEitherWithAuthdRegistry.get(); return tEitherWithAuthdRegistry.trace.trace( - eitherWithAuthdRegistry.fold((err, _val) => - loginMetric[err ? "failure" : "success"] + eitherWithAuthdRegistry.fold(({ isLeft}) => + loginMetric[isLeft ? "failure" : "success"] ), ); }) @@ -112,17 +112,17 @@ await LogMetricTraceable.from(eitherJob) }) .peek(async (tEitherWithBuiltImage) => { const eitherWithBuiltImage = await tEitherWithBuiltImage.get(); - eitherWithBuiltImage.fold((err, val) => { + eitherWithBuiltImage.fold(({ isLeft, value}) => { tEitherWithBuiltImage.trace.trace( - buildImageMetric[err ? "failure" : "success"], + buildImageMetric[isLeft ? "failure" : "success"], ); - if (!val || err) { + if (isLeft) { tEitherWithBuiltImage.trace.addTrace(LogLevel.ERROR).trace( - `oh nyoo we couldn't buiwd the img :(( ${err}`, + `oh nyoo we couldn't buiwd the img :(( ${value}`, ); return; } - tEitherWithBuiltImage.trace.addTrace("buildOutput").trace(val.buildOutput); + tEitherWithBuiltImage.trace.addTrace("buildOutput").trace(value.buildOutput); }); }) .map(async (tEitherWithBuiltImage) => { diff --git a/worker/secret.ts b/worker/secret.ts index e0a4c5d..f5ae93f 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,155 +39,178 @@ 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( - (err, _val) => Bitwarden.loginMetric[err ? "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( - (err, _val) => - Bitwarden.unlockVaultMetric[err ? "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)), + 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); + }), + ), ) - .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} (。•́︿•̀。)`), + .peek(async (tEitherWithSecret) => { + const eitherWithSecret = await tEitherWithSecret.get(); + return tEitherWithSecret.trace.trace( + eitherWithSecret.fold( + ({ isLeft }) => + Bitwarden.fetchSecretMetric[ + isLeft ? "failure" : "success" + ], + ), ); - } - return Either.right(secret); - }), - ), - ) - .peek(async (tEitherWithSecret) => { - const eitherWithSecret = await tEitherWithSecret.get(); - return tEitherWithSecret.trace.trace( - eitherWithSecret.fold( - (err, _val) => - Bitwarden.fetchSecretMetric[err ? "failure" : "success"], - ), - ); - }) - .get(); - } + }) + .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((err, _val) => { - tEitherWithLocked.trace.trace( - Bitwarden.lockVaultMetric[err ? "failure" : "success"], - ); - if (err) 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> -- |