diff options
Diffstat (limited to 'worker/scripts/build_docker_image.ts')
-rwxr-xr-x | worker/scripts/build_docker_image.ts | 259 |
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]; |