summaryrefslogtreecommitdiff
path: root/worker
diff options
context:
space:
mode:
authorElizabeth <me@liz.coffee>2025-06-02 16:52:52 -0700
committerElizabeth <me@liz.coffee>2025-06-02 16:52:52 -0700
commit98f5c21aa65bbbca01a186a754249335b4afef57 (patch)
tree0fc8e01a73f0a3be4534c11724ad2ff634b4fd2f /worker
parent373d9ec700c0097a22cf665a8e33cf48998d1dc2 (diff)
downloadci-98f5c21aa65bbbca01a186a754249335b4afef57.tar.gz
ci-98f5c21aa65bbbca01a186a754249335b4afef57.zip
fixup the Either monad a bit for type safetyp
Diffstat (limited to 'worker')
-rw-r--r--worker/executor.ts6
-rw-r--r--worker/jobs/ci_pipeline.run6
-rwxr-xr-xworker/scripts/build_docker_image16
-rw-r--r--worker/secret.ts343
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> --