summaryrefslogtreecommitdiff
path: root/worker/scripts/build_docker_image.ts
diff options
context:
space:
mode:
Diffstat (limited to 'worker/scripts/build_docker_image.ts')
-rwxr-xr-xworker/scripts/build_docker_image.ts259
1 files changed, 114 insertions, 145 deletions
diff --git a/worker/scripts/build_docker_image.ts b/worker/scripts/build_docker_image.ts
index 49abe41..228dfcc 100755
--- a/worker/scripts/build_docker_image.ts
+++ b/worker/scripts/build_docker_image.ts
@@ -1,162 +1,131 @@
-#!/usr/bin/env -S deno run --allow-env --allow-net --allow-run
+#!/usr/bin/env node
import {
- getRequiredEnvVars,
- getStdout,
- LogLevel,
- LogTraceable,
- LogMetricTraceable,
- Metric,
- TraceUtil,
-} from "@emprespresso/pengueno";
-import type {
- BuildDockerImageJob,
- BuildDockerImageJobProps,
-} from "@emprespresso/ci_model";
-import { Bitwarden, type LoginItem } from "@emprespresso/ci_worker";
+ getRequiredEnvVars,
+ getStdout,
+ LogLevel,
+ LogTraceable,
+ LogMetricTraceable,
+ Metric,
+ TraceUtil,
+} from '@emprespresso/pengueno';
+import type { BuildDockerImageJob, BuildDockerImageJobProps } from '@emprespresso/ci_model';
+import { Bitwarden, type LoginItem } from '@emprespresso/ci_worker';
const eitherJob = getRequiredEnvVars([
- "registry",
- "namespace",
- "repository",
- "imageTag",
- "context",
- "dockerfile",
- "buildTarget",
-])
- .mapRight((baseArgs) => (
- <BuildDockerImageJob> {
- type: "build_docker_image.ts",
- arguments: baseArgs,
- }
- ));
-const eitherVault = Bitwarden.getConfigFromEnvironment()
- .mapRight((config) => new Bitwarden(config));
+ 'registry',
+ 'namespace',
+ 'repository',
+ 'imageTag',
+ 'context',
+ 'dockerfile',
+ 'buildTarget',
+]).mapRight(
+ (baseArgs) =>
+ <BuildDockerImageJob>{
+ type: 'build_docker_image.ts',
+ arguments: baseArgs,
+ },
+);
+const eitherVault = Bitwarden.getConfigFromEnvironment().mapRight((config) => new Bitwarden(config));
-const buildImageMetric = Metric.fromName("dockerImage.build");
-const loginMetric = Metric.fromName("dockerRegistry.login");
-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];
- },
- );
+const buildImageMetric = Metric.fromName('dockerImage.build');
+const loginMetric = Metric.fromName('dockerRegistry.login');
+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) =>
- tEitherJob.trace.trace("starting docker image build job! (⑅˘꒳˘)")
- )
- .map((tEitherJob) =>
- tEitherJob.get()
- .flatMapAsync((job) =>
- eitherVault.flatMapAsync(async (vault) => {
- const eitherKey = await vault.unlock(tEitherJob);
- return eitherKey.mapRight((key) => ({ job, key, vault }));
- })
- )
- )
- .map(async (tEitherJobVault) => {
- tEitherJobVault.trace.trace("logging into the wegistwy uwu~");
- const eitherJobVault = await tEitherJobVault.get();
- const eitherDockerRegistryLoginItem = await eitherJobVault.flatMapAsync((
- { job, key, vault },
- ) =>
- vault.fetchSecret<LoginItem>(tEitherJobVault, key, job.arguments.registry)
- .finally(() => vault.lock(tEitherJobVault, key))
- );
- return eitherDockerRegistryLoginItem.flatMapAsync(({ login }) =>
- eitherJobVault.flatMapAsync(async ({ job }) => {
- const loginCommand = getDockerLoginCommand(
- login.username,
- job.arguments.registry,
+ .bimap(TraceUtil.withMetricTrace(buildImageMetric))
+ .bimap(TraceUtil.withMetricTrace(loginMetric))
+ .peek((tEitherJob) => tEitherJob.trace.trace('starting docker image build job! (⑅˘꒳˘)'))
+ .map((tEitherJob) =>
+ tEitherJob.get().flatMapAsync((job) =>
+ eitherVault.flatMapAsync(async (vault) => {
+ const eitherKey = await vault.unlock(tEitherJob);
+ return eitherKey.mapRight((key) => ({ job, key, vault }));
+ }),
+ ),
+ )
+ .map(async (tEitherJobVault) => {
+ tEitherJobVault.trace.trace('logging into the wegistwy uwu~');
+ const eitherJobVault = await tEitherJobVault.get();
+ const eitherDockerRegistryLoginItem = await eitherJobVault.flatMapAsync(({ job, key, vault }) =>
+ vault
+ .fetchSecret<LoginItem>(tEitherJobVault, key, job.arguments.registry)
+ .finally(() => vault.lock(tEitherJobVault, key)),
);
- const eitherLoggedIn = await tEitherJobVault.move(loginCommand).map((
- tLoginCmd,
- ) =>
- getStdout(tLoginCmd, { env: { REGISTRY_PASSWORD: login.password } })
- ).get();
- return eitherLoggedIn.moveRight(job);
- })
- );
- })
- .peek(async (tEitherWithAuthdRegistry) => {
- const eitherWithAuthdRegistry = await tEitherWithAuthdRegistry.get();
- return tEitherWithAuthdRegistry.trace.trace(
- eitherWithAuthdRegistry.fold(({ isLeft}) =>
- loginMetric[isLeft ? "failure" : "success"]
- ),
- );
- })
- .map(async (tEitherWithAuthdRegistryBuildJob) => {
- const eitherWithAuthdRegistryBuildJob =
- await tEitherWithAuthdRegistryBuildJob.get();
- tEitherWithAuthdRegistryBuildJob.trace.trace(
- "finally building the image~ (◕ᴗ◕✿)",
- );
- const eitherBuiltImage = await eitherWithAuthdRegistryBuildJob.flatMapAsync(
- (job) =>
- tEitherWithAuthdRegistryBuildJob
- .move(getBuildCommand(job.arguments))
- .map((tBuildCmd) =>
- getStdout(tBuildCmd, {
- env: {},
- clearEnv: true,
- })
- )
- .get(),
- );
- return eitherBuiltImage.flatMap((buildOutput) =>
- eitherWithAuthdRegistryBuildJob.mapRight((job) => ({ buildOutput, job }))
- );
- })
- .peek(async (tEitherWithBuiltImage) => {
- const eitherWithBuiltImage = await tEitherWithBuiltImage.get();
- eitherWithBuiltImage.fold(({ isLeft, value}) => {
- tEitherWithBuiltImage.trace.trace(
- buildImageMetric[isLeft ? "failure" : "success"],
- );
- if (isLeft) {
- tEitherWithBuiltImage.trace.addTrace(LogLevel.ERROR).trace(
- `oh nyoo we couldn't buiwd the img :(( ${value}`,
+ return eitherDockerRegistryLoginItem.flatMapAsync(({ login }) =>
+ eitherJobVault.flatMapAsync(async ({ job }) => {
+ const loginCommand = getDockerLoginCommand(login.username, job.arguments.registry);
+ const eitherLoggedIn = await tEitherJobVault
+ .move(loginCommand)
+ .map((tLoginCmd) => getStdout(tLoginCmd, { env: { REGISTRY_PASSWORD: login.password } }))
+ .get();
+ return eitherLoggedIn.moveRight(job);
+ }),
);
- return;
- }
- tEitherWithBuiltImage.trace.addTrace("buildOutput").trace(value.buildOutput);
- });
- })
- .map(async (tEitherWithBuiltImage) => {
- const eitherWithBuiltImage = await tEitherWithBuiltImage.get();
- return eitherWithBuiltImage
- .mapRight(({ job }) =>
- tEitherWithBuiltImage.move(getPushCommand(job.arguments.imageTag))
- )
- .flatMapAsync((tPushCommand) => getStdout(tPushCommand));
- })
- .get();
+ })
+ .peek(async (tEitherWithAuthdRegistry) => {
+ const eitherWithAuthdRegistry = await tEitherWithAuthdRegistry.get();
+ return tEitherWithAuthdRegistry.trace.trace(
+ eitherWithAuthdRegistry.fold(({ isLeft }) => loginMetric[isLeft ? 'failure' : 'success']),
+ );
+ })
+ .map(async (tEitherWithAuthdRegistryBuildJob) => {
+ const eitherWithAuthdRegistryBuildJob = await tEitherWithAuthdRegistryBuildJob.get();
+ tEitherWithAuthdRegistryBuildJob.trace.trace('finally building the image~ (◕ᴗ◕✿)');
+ const eitherBuiltImage = await eitherWithAuthdRegistryBuildJob.flatMapAsync((job) =>
+ tEitherWithAuthdRegistryBuildJob
+ .move(getBuildCommand(job.arguments))
+ .map((tBuildCmd) =>
+ getStdout(tBuildCmd, {
+ env: {},
+ clearEnv: true,
+ }),
+ )
+ .get(),
+ );
+ return eitherBuiltImage.flatMap((buildOutput) =>
+ eitherWithAuthdRegistryBuildJob.mapRight((job) => ({ buildOutput, job })),
+ );
+ })
+ .peek(async (tEitherWithBuiltImage) => {
+ const eitherWithBuiltImage = await tEitherWithBuiltImage.get();
+ eitherWithBuiltImage.fold(({ isLeft, value }) => {
+ tEitherWithBuiltImage.trace.trace(buildImageMetric[isLeft ? 'failure' : 'success']);
+ if (isLeft) {
+ tEitherWithBuiltImage.trace
+ .addTrace(LogLevel.ERROR)
+ .trace(`oh nyoo we couldn't buiwd the img :(( ${value}`);
+ return;
+ }
+ tEitherWithBuiltImage.trace.addTrace('buildOutput').trace(value.buildOutput);
+ });
+ })
+ .map(async (tEitherWithBuiltImage) => {
+ const eitherWithBuiltImage = await tEitherWithBuiltImage.get();
+ return eitherWithBuiltImage
+ .mapRight(({ job }) => tEitherWithBuiltImage.move(getPushCommand(job.arguments.imageTag)))
+ .flatMapAsync((tPushCommand) => getStdout(tPushCommand));
+ })
+ .get();
const getDockerLoginCommand = (username: string, registry: string) =>
- `docker login --username ${username} --password $REGISTRY_PASSWORD ${registry}`
- .split(" ");
+ `docker login --username ${username} --password $REGISTRY_PASSWORD ${registry}`.split(' ');
-const getBuildCommand = (
- {
+const getBuildCommand = ({ buildTarget, imageTag, dockerfile, context }: BuildDockerImageJobProps) => [
+ 'docker',
+ 'build',
+ '--target',
buildTarget,
+ '-t',
imageTag,
+ '-f',
dockerfile,
context,
- }: BuildDockerImageJobProps,
-) => [
- "docker",
- "build",
- "--target",
- buildTarget,
- "-t",
- imageTag,
- "-f",
- dockerfile,
- context,
];
-const getPushCommand = (tag: string) => ["docker", "push", tag];
+const getPushCommand = (tag: string) => ['docker', 'push', tag];