diff options
author | Elizabeth Hunt <me@liz.coffee> | 2025-07-20 16:03:44 -0700 |
---|---|---|
committer | Elizabeth Hunt <me@liz.coffee> | 2025-07-20 16:17:48 -0700 |
commit | 9e220eca4545982df83ffcaa66a9b050a3d6f24e (patch) | |
tree | a735fed0f50dec0083dac9284f45db73af1afea8 | |
parent | 2e10e9172f8528868b70886335dbbe20f932f702 (diff) | |
download | ci-9e220eca4545982df83ffcaa66a9b050a3d6f24e.tar.gz ci-9e220eca4545982df83ffcaa66a9b050a3d6f24e.zip |
Fixes silent failures
-rw-r--r-- | .ci/ci.ts | 2 | ||||
-rw-r--r-- | u/types/fn/either.ts | 2 | ||||
-rw-r--r-- | worker/executor.ts | 6 | ||||
-rwxr-xr-x | worker/scripts/ansible_playbook.ts | 7 | ||||
-rwxr-xr-x | worker/scripts/build_docker_image.ts | 73 | ||||
-rwxr-xr-x | worker/scripts/checkout_ci.ts | 10 |
6 files changed, 70 insertions, 30 deletions
@@ -18,6 +18,7 @@ const getPipeline = () => { if (!branch) return gitHookPipeline.build(); const commonBuildArgs = { + context: gitHookPipeline.getSourceDestination(), registry: REGISTRY, namespace: NAMESPACE, imageTag: branch, @@ -27,7 +28,6 @@ const getPipeline = () => { type: 'build_docker_image.js', arguments: { ...commonBuildArgs, - context: gitHookPipeline.getSourceDestination(), repository: IMG + '_base', buildTarget: IMG + '_base', dockerfile: 'Dockerfile', diff --git a/u/types/fn/either.ts b/u/types/fn/either.ts index 80f32b4..5e2dca0 100644 --- a/u/types/fn/either.ts +++ b/u/types/fn/either.ts @@ -26,7 +26,7 @@ export interface IEither<E, T> extends Tagged<IEitherTag> { readonly moveRight: <_T>(t: _T) => IEither<E, _T>; readonly fold: <_T>(leftFolder: Mapper<E, _T>, rightFolder: Mapper<T, _T>) => _T; - readonly joinRight: <O, _T>(other: IEither<E, O>, mapper: BiMapper<O, T, _T>) => IEither<E, _T>; + readonly joinRight: <O, _T>(other: IEither<E, O>, mapper: (a: O, b: T) => _T) => IEither<E, _T>; readonly joinRightAsync: <O, _T>( other: Supplier<Promise<IEither<E, O>>> | Promise<IEither<E, O>>, mapper: BiMapper<O, T, _T>, diff --git a/worker/executor.ts b/worker/executor.ts index f9fbf29..fe3a688 100644 --- a/worker/executor.ts +++ b/worker/executor.ts @@ -22,7 +22,7 @@ export const executeJob = (tJob: ITraceable<Job, LogMetricTraceSupplier>) => { .map((tJob) => validateExecutionEntries(tJob.get().arguments) .mapLeft((badEntries) => { - tJob.trace.traceScope(LogLevel.ERROR).trace(badEntries.toString()); + tJob.trace.traceScope(LogLevel.ERROR).trace(JSON.stringify(badEntries)); return new Error('invalid job arguments'); }) .flatMapAsync((args) => getStdout(tJob.move(tJob.get().type), { env: args })), @@ -44,9 +44,9 @@ export const executePipeline = ( .flatMap(TraceUtil.withMetricTrace(pipelinesMetric)) .map(async (_tPipeline): Promise<IEither<Error, void>> => { for (const [i, serialStage] of tPipeline.get().serialJobs.entries()) { - const tPipeline = _tPipeline.flatMap(TraceUtil.withTrace(`Stage = ${i}`)); + const tPipeline = _tPipeline.traceScope(() => `Stage = ${i}`); const parallelJobs = tPipeline - .peek((t) => t.trace.trace(`do your best little stage :> ${serialStage}`)) + .peek((t) => t.trace.trace(`do your best little stage :> ${JSON.stringify(serialStage)}`)) .move(serialStage.parallelJobs) .coExtend((jobs) => jobs.get().map((job) => <Job>{ ...job, arguments: { ...baseEnv, ...job.arguments } }), diff --git a/worker/scripts/ansible_playbook.ts b/worker/scripts/ansible_playbook.ts index 4ec3ffa..6eb4d47 100755 --- a/worker/scripts/ansible_playbook.ts +++ b/worker/scripts/ansible_playbook.ts @@ -88,6 +88,13 @@ await LogMetricTraceable.ofLogTraceable(_logJob) return tEitherJobAndSecrets.move(deployCmd).map(getStdout).get(); }); }) + .map(async (tEitherJob) => { + const eitherJob = await tEitherJob.get(); + return eitherJob.fold( + (e) => Promise.reject(e), + () => Promise.resolve(0), + ); + }) .get(); function saveToTempFile(text: string): Promise<IEither<Error, string>> { diff --git a/worker/scripts/build_docker_image.ts b/worker/scripts/build_docker_image.ts index 1783e7c..f29bd61 100755 --- a/worker/scripts/build_docker_image.ts +++ b/worker/scripts/build_docker_image.ts @@ -11,8 +11,9 @@ import { } from '@emprespresso/pengueno'; import type { BuildDockerImageJob, BuildDockerImageJobProps } from '@emprespresso/ci_model'; import { Bitwarden, type LoginItem } from '@emprespresso/ci_worker'; +import path from 'path'; -const eitherJob = getRequiredEnvVars([ +const job = getRequiredEnvVars([ 'registry', 'namespace', 'repository', @@ -20,36 +21,39 @@ const eitherJob = getRequiredEnvVars([ 'context', 'dockerfile', 'buildTarget', -]).mapRight( - (baseArgs) => - <BuildDockerImageJob>{ - type: 'build_docker_image.js', - arguments: baseArgs, +]) + .mapRight( + (baseArgs) => + <BuildDockerImageJob>{ + type: 'build_docker_image.js', + arguments: baseArgs, + }, + ) + .fold( + (err) => { + throw err; }, -); + (x) => x, + ); const eitherVault = Bitwarden.getConfigFromEnvironment().mapRight((config) => new Bitwarden(config)); const buildImageMetric = Metric.fromName('dockerImage.build').asResult(); const loginMetric = Metric.fromName('dockerRegistry.login').asResult(); -const _logJob = LogTraceable.of(eitherJob).flatMap((tEitherJob) => { - const trace = tEitherJob.get().fold( - () => 'NO_BUILD_TARGET', - ({ arguments: { buildTarget } }) => buildTarget, - ); - return tEitherJob.traceScope(() => `build_docker_image.${trace}`); +const _logJob = LogTraceable.of(job).flatMap((tJob) => { + const trace = tJob.get().arguments.buildTarget; + return tJob.traceScope(() => `build_docker_image.${trace}`); }); await LogMetricTraceable.ofLogTraceable(_logJob) .flatMap(TraceUtil.withMetricTrace(buildImageMetric)) .flatMap(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 })); - }), - ), + .peek((tJob) => tJob.trace.trace('starting docker image build job! (⑅˘꒳˘)')) + .map((tJob) => + eitherVault.flatMapAsync(async (vault) => { + const job = tJob.get(); + const eitherKey = await vault.unlock(tJob); + return eitherKey.mapRight((key) => ({ job, key, vault })); + }), ) .map(async (tEitherJobVault) => { tEitherJobVault.trace.trace('logging into the wegistwy uwu~'); @@ -85,9 +89,10 @@ await LogMetricTraceable.ofLogTraceable(_logJob) ) .get(), ); - return eitherBuiltImage.flatMap((buildOutput) => - eitherWithAuthdRegistryBuildJob.mapRight((job) => ({ buildOutput, job })), - ); + return eitherBuiltImage.joinRight(eitherWithAuthdRegistryBuildJob, (job, buildOutput) => ({ + job, + buildOutput, + })); }) .flatMapAsync(TraceUtil.promiseify(TraceUtil.traceResultingEither(buildImageMetric))) .peek( @@ -104,6 +109,13 @@ await LogMetricTraceable.ofLogTraceable(_logJob) .mapRight(({ job }) => tEitherWithBuiltImage.move(getPushCommand(job.arguments.imageTag))) .flatMapAsync((tPushCommand) => getStdout(tPushCommand)); }) + .map(async (tEitherJob) => { + const eitherJob = await tEitherJob.get(); + return eitherJob.fold( + (e) => Promise.reject(e), + () => Promise.resolve(0), + ); + }) .get(); function getDockerLoginCommand(username: string, registry: string): Command { @@ -111,7 +123,18 @@ function getDockerLoginCommand(username: string, registry: string): Command { } function getBuildCommand({ buildTarget, imageTag, dockerfile, context }: BuildDockerImageJobProps): Command { - return ['docker', 'build', '--target', buildTarget, '-t', imageTag, '-f', dockerfile, context]; + return [ + 'cat', + path.join(context, dockerfile), + '|', + 'docker', + 'build', + '--target', + buildTarget, + '-t', + imageTag, + '-', + ]; } function getPushCommand(tag: string): Command { diff --git a/worker/scripts/checkout_ci.ts b/worker/scripts/checkout_ci.ts index ac36d69..65cbc2e 100755 --- a/worker/scripts/checkout_ci.ts +++ b/worker/scripts/checkout_ci.ts @@ -150,6 +150,16 @@ await LogMetricTraceable.ofLogTraceable(logTraceableJob) () => afterJob, ); }) + .map( + TraceUtil.promiseify((e) => + e.get().fold( + (err) => { + throw err; + }, + (ok) => ok, + ), + ), + ) .get(); function getWorkingDirectoryForCiJob(job: CheckoutCiJob) { |