summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-06-15 21:13:00 -0700
committerElizabeth Hunt <me@liz.coffee>2025-06-15 21:13:00 -0700
commit037c85fdd373322a84afd8acd9c652deeab37520 (patch)
tree9d830ca8b2f79e3e2ec2e5218873e0028d7fede6
parent1e38d81ceec451f25d3a11fbd82e5c225848d172 (diff)
downloadci-037c85fdd373322a84afd8acd9c652deeab37520.tar.gz
ci-037c85fdd373322a84afd8acd9c652deeab37520.zip
Use .ts extensions for deno parser
-rw-r--r--.ci/ci.ts8
-rw-r--r--model/job.ts8
-rwxr-xr-xworker/jobs/ci_pipeline.run170
-rwxr-xr-xworker/scripts/ansible_playbook.ts (renamed from worker/scripts/ansible_playbook)0
-rwxr-xr-xworker/scripts/build_docker_image.ts (renamed from worker/scripts/build_docker_image)2
-rwxr-xr-xworker/scripts/checkout_ci.ts182
6 files changed, 193 insertions, 177 deletions
diff --git a/.ci/ci.ts b/.ci/ci.ts
index 18fdb60..89bad35 100644
--- a/.ci/ci.ts
+++ b/.ci/ci.ts
@@ -24,7 +24,7 @@ const getPipeline = () => {
};
const baseCiPackageBuild: BuildDockerImageJob = {
- type: "build_docker_image",
+ type: "build_docker_image.ts",
arguments: {
...commonBuildArgs,
context: gitHookPipeline.getSourceDestination(),
@@ -38,7 +38,7 @@ const getPipeline = () => {
});
const subPackages = ["worker", "hooks"].map((_package) => ({
- type: "build_docker_image",
+ type: "build_docker_image.ts",
arguments: {
...commonBuildArgs,
repository: `${IMG}_${_package}`,
@@ -56,7 +56,7 @@ const getPipeline = () => {
}
const fetchAnsibleCode: FetchCodeJob = {
- type: "fetch_code",
+ type: "fetch_code.ts",
arguments: {
remoteUrl: `${REMOTE}/infra`,
checkout: "main",
@@ -64,7 +64,7 @@ const getPipeline = () => {
},
};
const thenDeploy: AnsiblePlaybookJob = {
- type: "ansible_playbook",
+ type: "ansible_playbook.ts",
arguments: {
path: "infra",
playbooks: "playbooks/ci.yml",
diff --git a/model/job.ts b/model/job.ts
index 52386eb..187ed56 100644
--- a/model/job.ts
+++ b/model/job.ts
@@ -22,7 +22,7 @@ export interface FetchCodeJobProps extends JobArgT {
}
export interface FetchCodeJob {
- readonly type: "fetch_code";
+ readonly type: "fetch_code.ts";
readonly arguments: FetchCodeJobProps;
}
@@ -38,7 +38,7 @@ export interface BuildDockerImageJobProps extends JobArgT {
}
export interface BuildDockerImageJob extends Job {
- readonly type: "build_docker_image";
+ readonly type: "build_docker_image.ts";
readonly arguments: BuildDockerImageJobProps;
}
@@ -48,7 +48,7 @@ export interface AnsiblePlaybookJobProps extends JobArgT {
}
export interface AnsiblePlaybookJob extends Job {
- readonly type: "ansible_playbook";
+ readonly type: "ansible_playbook.ts";
readonly arguments: AnsiblePlaybookJobProps;
}
@@ -62,6 +62,6 @@ export interface CheckoutCiJobProps extends JobArgT {
}
export interface CheckoutCiJob extends Job {
- readonly type: "checkout_ci";
+ readonly type: "checkout_ci.ts";
readonly arguments: CheckoutCiJobProps;
}
diff --git a/worker/jobs/ci_pipeline.run b/worker/jobs/ci_pipeline.run
index 66b02ed..c2f1880 100755
--- a/worker/jobs/ci_pipeline.run
+++ b/worker/jobs/ci_pipeline.run
@@ -1,169 +1,3 @@
-#!/usr/bin/env -S deno run --allow-all
+#!/bin/sh
-import {
- type Command,
- Either,
- LogTraceable,
- getRequiredEnvVars,
- getStdout,
- isObject,
- LogMetricTraceable,
- Metric,
- prependWith,
- TraceUtil,
-} from "@emprespresso/pengueno";
-import {
- type CheckoutCiJob,
- type FetchCodeJob,
- PipelineImpl,
-} from "@emprespresso/ci_model";
-import { executeJob, executePipeline } from "@emprespresso/ci_worker";
-
-const run = Date.now().toString();
-const eitherJob = getRequiredEnvVars(["remote", "refname", "rev"])
- .mapRight((baseArgs) => (
- <CheckoutCiJob> {
- type: "checkout_ci",
- arguments: {
- ...baseArgs,
- run,
- returnPath: Deno.cwd(),
- },
- }
- ));
-
-const ciRunMetric = Metric.fromName("checkout_ci.run");
-const _logJob = LogTraceable.of(eitherJob).bimap(TraceUtil.withTrace(`checkout_ci.${run}`));
-await LogMetricTraceable.ofLogTraceable(_logJob)
- .bimap(TraceUtil.withMetricTrace(ciRunMetric))
- .map((tEitherJob) =>
- tEitherJob.get().flatMapAsync((ciJob) => {
- const wd = getWorkingDirectoryForCiJob(ciJob);
- const fetchPackageJob = <FetchCodeJob> {
- type: "fetch_code",
- arguments: {
- remoteUrl: ciJob.arguments.remote,
- checkout: ciJob.arguments.rev,
- path: getSrcDirectoryForCiJob(ciJob),
- },
- };
- return Either.fromFailableAsync<Error, CheckoutCiJob>(
- () => Deno.mkdir(wd).then(() => Deno.chdir(wd))
- .then(() => tEitherJob.move(fetchPackageJob).map(executeJob).get())
- .then(() => ciJob),
- );
- })
- )
- .map((tEitherCiJob) =>
- tEitherCiJob.get().then((eitherCiJob) =>
- eitherCiJob.flatMapAsync<{ cmd: Command; job: CheckoutCiJob }>((ciJob) =>
- Either.fromFailableAsync<Error, string>(
- () => Deno.readTextFile(
- `${getSrcDirectoryForCiJob(ciJob)}/${CI_WORKFLOW_FILE}`,
- ),
- ).then((eitherWorkflowJson) =>
- eitherWorkflowJson.flatMap(
- (json) => Either.fromFailable<Error, unknown>(JSON.parse(json)),
- ).flatMap((eitherWorkflowParse) => {
- if (isCiWorkflow(eitherWorkflowParse)) {
- return Either.right({
- cmd: getPipelineGenerationCommand(
- ciJob,
- eitherWorkflowParse.workflow,
- ),
- job: ciJob,
- });
- }
- return Either.left(
- new Error(
- "couldn't find any valid ci configuration (。•́︿•̀。), that's okay~",
- ),
- );
- })
- )
- )
- )
- )
- .map(async (tEitherPipelineGenerationCommand) => {
- const eitherJobCommand = await tEitherPipelineGenerationCommand.get();
- const eitherPipeline = await eitherJobCommand
- .flatMapAsync((jobCommand) =>
- tEitherPipelineGenerationCommand.move(jobCommand.cmd)
- .map(getStdout)
- .get()
- );
- return eitherPipeline
- .flatMap(PipelineImpl.from)
- .flatMap((pipeline) =>
- eitherJobCommand.mapRight(({ job }) => ({ job, pipeline }))
- );
- })
- .peek(
- TraceUtil.promiseify((tEitherPipeline) =>
- tEitherPipeline.get()
- .mapRight((val) => val.pipeline.serialize())
- .mapRight((pipeline) =>
- `built the pipeline~ (◕ᴗ◕✿) let's make something amazing! ${pipeline}`
- )
- .mapRight((msg) => tEitherPipeline.trace.trace(msg))
- ),
- )
- .map(
- async (tEitherPipeline) => {
- const eitherPipeline = await tEitherPipeline.get();
- return eitherPipeline.flatMapAsync(({ pipeline, job }) =>
- tEitherPipeline.move(pipeline)
- .map((p) =>
- executePipeline(p, {
- HOME: getWorkingDirectoryForCiJob(job),
- })
- )
- .get()
- );
- },
- )
- .get()
- .then((e) =>
- e.flatMap(() => eitherJob).fold(({isLeft, isRight, value}) => {
- if (isLeft || !isRight) throw value;
- return Deno.remove(getWorkingDirectoryForCiJob(value), { recursive: true });
- })
- );
-
-const getWorkingDirectoryForCiJob = (job: CheckoutCiJob) =>
- `${job.arguments.returnPath}/${job.arguments.run}`;
-
-const getSrcDirectoryForCiJob = (job: CheckoutCiJob) =>
- `${job.arguments.returnPath}/${job.arguments.run}/src`;
-
-const _runFlags = ("--rm --network none --cap-drop ALL" +
- "--security-opt no-new-privileges").split(" ");
-const _image = "oci.liz.coffee/img/ci-worker:release";
-const getPipelineGenerationCommand = (
- job: CheckoutCiJob,
- pipelineGeneratorPath: string,
- image = _image,
- runFlags = _runFlags,
-) => [
- "docker",
- "run",
- ...runFlags,
- ...prependWith(
- Object.entries(job.arguments).map(([key, val]) => `"${key}"="${val}"`),
- "-e",
- ),
- "-v",
- `${
- getSrcDirectoryForCiJob(job)
- }/${pipelineGeneratorPath}:/pipeline_generator`,
- image,
- "/pipeline_generator",
-];
-
-export interface CiWorkflow {
- workflow: string;
-}
-export const isCiWorkflow = (t: unknown): t is CiWorkflow =>
- isObject(t) && "workflow" in t && typeof t.workflow === "string" &&
- !t.workflow.includes("..");
-const CI_WORKFLOW_FILE = ".ci/ci.json";
+checkout_ci.ts
diff --git a/worker/scripts/ansible_playbook b/worker/scripts/ansible_playbook.ts
index fe2810b..fe2810b 100755
--- a/worker/scripts/ansible_playbook
+++ b/worker/scripts/ansible_playbook.ts
diff --git a/worker/scripts/build_docker_image b/worker/scripts/build_docker_image.ts
index f2fa522..49abe41 100755
--- a/worker/scripts/build_docker_image
+++ b/worker/scripts/build_docker_image.ts
@@ -26,7 +26,7 @@ const eitherJob = getRequiredEnvVars([
])
.mapRight((baseArgs) => (
<BuildDockerImageJob> {
- type: "build_docker_image",
+ type: "build_docker_image.ts",
arguments: baseArgs,
}
));
diff --git a/worker/scripts/checkout_ci.ts b/worker/scripts/checkout_ci.ts
new file mode 100755
index 0000000..efe74fb
--- /dev/null
+++ b/worker/scripts/checkout_ci.ts
@@ -0,0 +1,182 @@
+#!/usr/bin/env -S deno run --allow-all
+
+import {
+ type Command,
+ Either,
+ LogTraceable,
+ getRequiredEnvVars,
+ getStdout,
+ isObject,
+ LogMetricTraceable,
+ Metric,
+ prependWith,
+ TraceUtil,
+} from "@emprespresso/pengueno";
+import {
+ type CheckoutCiJob,
+ type FetchCodeJob,
+ PipelineImpl,
+} from "@emprespresso/ci_model";
+import { executeJob, executePipeline } from "@emprespresso/ci_worker";
+
+const run = Date.now().toString();
+const eitherJob = getRequiredEnvVars(["remote", "refname", "rev"]).mapRight(
+ (baseArgs) =>
+ <CheckoutCiJob>{
+ type: "checkout_ci.ts",
+ arguments: {
+ ...baseArgs,
+ run,
+ returnPath: Deno.cwd(),
+ },
+ },
+);
+
+const ciRunMetric = Metric.fromName("checkout_ci.run");
+const _logJob = LogTraceable.of(eitherJob).bimap(
+ TraceUtil.withTrace(`checkout_ci.${run}`),
+);
+await LogMetricTraceable.ofLogTraceable(_logJob)
+ .bimap(TraceUtil.withMetricTrace(ciRunMetric))
+ .map((tEitherJob) =>
+ tEitherJob.get().flatMapAsync((ciJob) => {
+ const wd = getWorkingDirectoryForCiJob(ciJob);
+ const fetchPackageJob = <FetchCodeJob>{
+ type: "fetch_code.ts",
+ arguments: {
+ remoteUrl: ciJob.arguments.remote,
+ checkout: ciJob.arguments.rev,
+ path: getSrcDirectoryForCiJob(ciJob),
+ },
+ };
+ return Either.fromFailableAsync<Error, CheckoutCiJob>(() =>
+ Deno.mkdir(wd)
+ .then(() => Deno.chdir(wd))
+ .then(() => tEitherJob.move(fetchPackageJob).map(executeJob).get())
+ .then(() => ciJob),
+ );
+ }),
+ )
+ .map((tEitherCiJob) =>
+ tEitherCiJob.get().then((eitherCiJob) =>
+ eitherCiJob.flatMapAsync<{ cmd: Command; job: CheckoutCiJob }>((ciJob) =>
+ Either.fromFailableAsync<Error, string>(() =>
+ Deno.readTextFile(
+ `${getSrcDirectoryForCiJob(ciJob)}/${CI_WORKFLOW_FILE}`,
+ ),
+ ).then((eitherWorkflowJson) =>
+ eitherWorkflowJson
+ .flatMap((json) =>
+ Either.fromFailable<Error, unknown>(JSON.parse(json)),
+ )
+ .flatMap((eitherWorkflowParse) => {
+ if (isCiWorkflow(eitherWorkflowParse)) {
+ return Either.right({
+ cmd: getPipelineGenerationCommand(
+ ciJob,
+ eitherWorkflowParse.workflow,
+ ),
+ job: ciJob,
+ });
+ }
+ return Either.left(
+ new Error(
+ "couldn't find any valid ci configuration (。•́︿•̀。), that's okay~",
+ ),
+ );
+ }),
+ ),
+ ),
+ ),
+ )
+ .map(async (tEitherPipelineGenerationCommand) => {
+ const eitherJobCommand = await tEitherPipelineGenerationCommand.get();
+ const eitherPipeline = await eitherJobCommand.flatMapAsync((jobCommand) =>
+ tEitherPipelineGenerationCommand
+ .move(jobCommand.cmd)
+ .map(getStdout)
+ .get(),
+ );
+ return eitherPipeline
+ .flatMap(PipelineImpl.from)
+ .flatMap((pipeline) =>
+ eitherJobCommand.mapRight(({ job }) => ({ job, pipeline })),
+ );
+ })
+ .peek(
+ TraceUtil.promiseify((tEitherPipeline) =>
+ tEitherPipeline
+ .get()
+ .mapRight((val) => val.pipeline.serialize())
+ .mapRight(
+ (pipeline) =>
+ `built the pipeline~ (◕ᴗ◕✿) let's make something amazing! ${pipeline}`,
+ )
+ .mapRight((msg) => tEitherPipeline.trace.trace(msg)),
+ ),
+ )
+ .map(async (tEitherPipeline) => {
+ const eitherPipeline = await tEitherPipeline.get();
+ return eitherPipeline.flatMapAsync(({ pipeline, job }) =>
+ tEitherPipeline
+ .move(pipeline)
+ .map((p) =>
+ executePipeline(p, {
+ HOME: getWorkingDirectoryForCiJob(job),
+ }),
+ )
+ .get(),
+ );
+ })
+ .get()
+ .then((e) =>
+ e
+ .flatMap(() => eitherJob)
+ .fold(({ isLeft, isRight, value }) => {
+ if (isLeft || !isRight) throw value;
+ return Deno.remove(getWorkingDirectoryForCiJob(value), {
+ recursive: true,
+ });
+ }),
+ );
+
+const getWorkingDirectoryForCiJob = (job: CheckoutCiJob) =>
+ `${job.arguments.returnPath}/${job.arguments.run}`;
+
+const getSrcDirectoryForCiJob = (job: CheckoutCiJob) =>
+ `${job.arguments.returnPath}/${job.arguments.run}/src`;
+
+const _runFlags = (
+ "--rm --network none --cap-drop ALL" + "--security-opt no-new-privileges"
+).split(" ");
+const _image = "oci.liz.coffee/img/ci-worker:release";
+const getPipelineGenerationCommand = (
+ job: CheckoutCiJob,
+ pipelineGeneratorPath: string,
+ image = _image,
+ runFlags = _runFlags,
+) => [
+ "docker",
+ "run",
+ ...runFlags,
+ ...prependWith(
+ Object.entries(job.arguments).map(([key, val]) => `"${key}"="${val}"`),
+ "-e",
+ ),
+ "-v",
+ `${getSrcDirectoryForCiJob(
+ job,
+ )}/${pipelineGeneratorPath}:/pipeline_generator`,
+ image,
+ "/pipeline_generator",
+];
+
+export interface CiWorkflow {
+ workflow: string;
+}
+export const isCiWorkflow = (t: unknown): t is CiWorkflow =>
+ isObject(t) &&
+ "workflow" in t &&
+ typeof t.workflow === "string" &&
+ !t.workflow.includes("..");
+const CI_WORKFLOW_FILE = ".ci/ci.json";