@catladder/pipeline 3.48.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/build/index.d.ts +2 -2
  2. package/dist/build/node/buildJob.d.ts +3 -3
  3. package/dist/build/node/buildJob.js +185 -26
  4. package/dist/build/node/cache.d.ts +3 -3
  5. package/dist/build/node/cache.js +199 -36
  6. package/dist/build/node/index.d.ts +3 -3
  7. package/dist/build/node/index.js +151 -3
  8. package/dist/build/node/meteor.d.ts +1 -1
  9. package/dist/build/node/meteor.js +162 -27
  10. package/dist/build/node/testJob.d.ts +1 -1
  11. package/dist/build/node/testJob.js +174 -49
  12. package/dist/build/node/yarn.d.ts +2 -2
  13. package/dist/build/node/yarn.js +168 -21
  14. package/dist/constants.js +1 -1
  15. package/dist/context/createComponentContext.js +10 -12
  16. package/dist/context/createWorkspaceContext.js +29 -34
  17. package/dist/deploy/custom/deployJob.d.ts +1 -1
  18. package/dist/deploy/custom/deployJob.js +147 -23
  19. package/dist/deploy/index.d.ts +1 -1
  20. package/dist/pipeline/createAllJobs.js +30 -14
  21. package/dist/pipeline/createJobsForComponent.d.ts +1 -1
  22. package/dist/pipeline/createJobsForComponent.js +128 -4
  23. package/dist/pipeline/createJobsForWorkspace.d.ts +1 -1
  24. package/dist/pipeline/createJobsForWorkspace.js +127 -2
  25. package/dist/pipeline/yarn/yarnUtils.js +61 -1
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/dist/types/context.d.ts +3 -3
  28. package/examples/__snapshots__/automatic-releases.test.ts.snap +9 -13
  29. package/examples/__snapshots__/cloud-run-execute-script-on-deploy.test.ts.snap +9 -13
  30. package/examples/__snapshots__/cloud-run-health-check-defaults.test.ts.snap +9 -13
  31. package/examples/__snapshots__/cloud-run-health-check-only-startup.test.ts.snap +9 -13
  32. package/examples/__snapshots__/cloud-run-health-check.test.ts.snap +9 -13
  33. package/examples/__snapshots__/cloud-run-http2.test.ts.snap +9 -13
  34. package/examples/__snapshots__/cloud-run-memory-limit.test.ts.snap +9 -13
  35. package/examples/__snapshots__/cloud-run-meteor-with-worker.test.ts.snap +9 -13
  36. package/examples/__snapshots__/cloud-run-nextjs.test.ts.snap +9 -13
  37. package/examples/__snapshots__/cloud-run-no-cpu-throttling.test.ts.snap +9 -13
  38. package/examples/__snapshots__/cloud-run-no-service.test.ts.snap +9 -13
  39. package/examples/__snapshots__/cloud-run-non-public.test.ts.snap +9 -13
  40. package/examples/__snapshots__/cloud-run-post-stop-job.test.ts.snap +9 -13
  41. package/examples/__snapshots__/cloud-run-service-custom-vpc-connector.test.ts.snap +9 -13
  42. package/examples/__snapshots__/cloud-run-service-custom-vpc.test.ts.snap +9 -13
  43. package/examples/__snapshots__/cloud-run-service-gen2.test.ts.snap +9 -13
  44. package/examples/__snapshots__/cloud-run-service-increase-timout.test.ts.snap +9 -13
  45. package/examples/__snapshots__/cloud-run-service-with-volumes.test.ts.snap +9 -13
  46. package/examples/__snapshots__/cloud-run-session-affinity.test.ts.snap +9 -13
  47. package/examples/__snapshots__/cloud-run-with-agents.test.ts.snap +9 -13
  48. package/examples/__snapshots__/cloud-run-with-gpu.test.ts.snap +9 -13
  49. package/examples/__snapshots__/cloud-run-with-ngnix.test.ts.snap +9 -13
  50. package/examples/__snapshots__/cloud-run-with-sql-legacy-jobs.test.ts.snap +9 -13
  51. package/examples/__snapshots__/cloud-run-with-sql-multiple-dbs.test.ts.snap +18 -30
  52. package/examples/__snapshots__/cloud-run-with-sql-reuse-db.test.ts.snap +14 -22
  53. package/examples/__snapshots__/cloud-run-with-sql.test.ts.snap +9 -13
  54. package/examples/__snapshots__/cloud-run-with-worker.test.ts.snap +9 -13
  55. package/examples/__snapshots__/cloud-run-worker-pool.test.ts.snap +9 -13
  56. package/examples/__snapshots__/custom-deploy.test.ts.snap +9 -13
  57. package/examples/__snapshots__/custom-docker-file.test.ts.snap +9 -13
  58. package/examples/__snapshots__/custom-envs.test.ts.snap +14 -22
  59. package/examples/__snapshots__/custom-verify-job.test.ts.snap +9 -13
  60. package/examples/__snapshots__/git-submodule.test.ts.snap +9 -13
  61. package/examples/__snapshots__/kubernetes-application-customization.test.ts.snap +9 -13
  62. package/examples/__snapshots__/kubernetes-with-cloud-sql.test.ts.snap +9 -13
  63. package/examples/__snapshots__/kubernetes-with-jobs.test.ts.snap +14 -22
  64. package/examples/__snapshots__/kubernetes-with-mongodb.test.ts.snap +9 -13
  65. package/examples/__snapshots__/local-dot-env.test.ts.snap +9 -13
  66. package/examples/__snapshots__/meteor-kubernetes.test.ts.snap +9 -13
  67. package/examples/__snapshots__/modify-generated-files.test.ts.snap +9 -13
  68. package/examples/__snapshots__/modify-generated-yaml.test.ts.snap +9 -13
  69. package/examples/__snapshots__/multiline-var.test.ts.snap +18 -30
  70. package/examples/__snapshots__/native-app.test.ts.snap +14 -22
  71. package/examples/__snapshots__/node-build-with-custom-image.test.ts.snap +9 -13
  72. package/examples/__snapshots__/node-build-with-docker-additions.test.ts.snap +9 -13
  73. package/examples/__snapshots__/override-secrets.test.ts.snap +9 -13
  74. package/examples/__snapshots__/referencing-other-vars.test.ts.snap +18 -30
  75. package/examples/__snapshots__/wait-for-other-deploy.test.ts.snap +14 -22
  76. package/examples/__snapshots__/workspace-api-www-turbo-cache.test.ts.snap +9 -13
  77. package/examples/__snapshots__/workspace-api-www.test.ts.snap +9 -13
  78. package/package.json +1 -1
  79. package/src/build/index.ts +6 -2
  80. package/src/build/node/buildJob.ts +26 -17
  81. package/src/build/node/cache.ts +18 -15
  82. package/src/build/node/index.ts +17 -9
  83. package/src/build/node/meteor.ts +16 -11
  84. package/src/build/node/testJob.ts +10 -6
  85. package/src/build/node/yarn.ts +10 -8
  86. package/src/context/createComponentContext.ts +6 -3
  87. package/src/context/createWorkspaceContext.ts +1 -1
  88. package/src/deploy/cloudRun/createJobs/getCloudRunDeployScripts.ts +3 -1
  89. package/src/deploy/custom/deployJob.ts +3 -3
  90. package/src/deploy/index.ts +1 -1
  91. package/src/pipeline/createAllJobs.ts +9 -7
  92. package/src/pipeline/createJobsForComponent.ts +6 -6
  93. package/src/pipeline/createJobsForWorkspace.ts +3 -3
  94. package/src/pipeline/yarn/yarnUtils.ts +34 -0
  95. package/src/types/context.ts +3 -3
@@ -12,9 +12,9 @@ import { NODE_RUNNER_BUILD_VARIABLES } from "./constants";
12
12
  import { ensureNodeVersion, getYarnInstall } from "./yarn";
13
13
  import { createJobCacheFromCacheConfigs } from "../cache/createJobCache";
14
14
 
15
- export const createNodeTestJobs = (
15
+ export const createNodeTestJobs = async (
16
16
  context: ComponentContext | WorkspaceContext,
17
- ): CatladderJob[] => {
17
+ ): Promise<CatladderJob[]> => {
18
18
  // don't run tests after release
19
19
  // TODO: this will be replaced by using rules
20
20
  if (context.trigger === "taggedRelease") {
@@ -43,7 +43,11 @@ export const createNodeTestJobs = (
43
43
  needs: [],
44
44
  };
45
45
  const buildConfig = context.build.config;
46
- const yarnInstall = getYarnInstall(context);
46
+ const [yarnInstall, packageManagerInfo, nodeCache] = await Promise.all([
47
+ getYarnInstall(context),
48
+ context.packageManagerInfo,
49
+ getNodeCache(context),
50
+ ]);
47
51
  const auditJob: CatladderJob | null =
48
52
  buildConfig.audit !== false
49
53
  ? {
@@ -58,7 +62,7 @@ export const createNodeTestJobs = (
58
62
  script: [
59
63
  `cd ${context.build.dir}`,
60
64
  ...(ensureArrayOrNull(buildConfig.audit?.command) ?? [
61
- context.packageManagerInfo.isClassic
65
+ packageManagerInfo.isClassic
62
66
  ? "yarn audit --level critical"
63
67
  : "yarn npm audit --environment production --severity critical", // yarn 2
64
68
  ]),
@@ -81,7 +85,7 @@ export const createNodeTestJobs = (
81
85
  ...(buildConfig.lint?.runnerVariables ?? {}),
82
86
  },
83
87
  image: buildConfig.lint?.jobImage ?? defaultImage,
84
- cache: createJobCacheFromCacheConfigs(context, getNodeCache(context)),
88
+ cache: createJobCacheFromCacheConfigs(context, nodeCache),
85
89
  script: [
86
90
  ...ensureNodeVersion(context),
87
91
  `cd ${context.build.dir}`,
@@ -108,7 +112,7 @@ export const createNodeTestJobs = (
108
112
  },
109
113
  image:
110
114
  buildConfig.test?.jobImage ?? getRunnerImage("jobs-testing-chrome"),
111
- cache: createJobCacheFromCacheConfigs(context, getNodeCache(context)),
115
+ cache: createJobCacheFromCacheConfigs(context, nodeCache),
112
116
  script: [
113
117
  ...ensureNodeVersion(context),
114
118
  `cd ${context.build.dir}`,
@@ -10,8 +10,9 @@ const YARN_BERRY_PROD_INSTALL = `yarn workspaces focus --production`;
10
10
  // FIXME: check why and when rebuild is needed
11
11
  const YARN_BERRY_PROD_REBUILD = `yarn rebuild`;
12
12
 
13
- const getYarnInstallCommand = (context: Context) => {
14
- if (context.packageManagerInfo.isClassic) {
13
+ const getYarnInstallCommand = async (context: Context) => {
14
+ const packageManagerInfo = await context.packageManagerInfo;
15
+ if (packageManagerInfo.isClassic) {
15
16
  return YARN_INSTALL_CLASSIC;
16
17
  }
17
18
  // inline builds make debugging easier as it prints it out in the logs, instead of writing it in temp files
@@ -27,7 +28,7 @@ export const ensureNodeVersion = (context: Context) =>
27
28
  "if command -v nvm &> /dev/null && [ -f ./.nvmrc ]; then nvm install; fi",
28
29
  ]);
29
30
 
30
- export const getYarnInstall = (
31
+ export const getYarnInstall = async (
31
32
  context: Context,
32
33
  options?: {
33
34
  noCustomPostInstall: boolean;
@@ -44,7 +45,7 @@ export const getYarnInstall = (
44
45
  ...collapseableSection(
45
46
  "yarninstall",
46
47
  "Yarn install",
47
- )([getYarnInstallCommand(context)]),
48
+ )([await getYarnInstallCommand(context)]),
48
49
  ...(postInstall && !options?.noCustomPostInstall
49
50
  ? collapseableSection(
50
51
  "postinstall",
@@ -56,15 +57,16 @@ export const getYarnInstall = (
56
57
 
57
58
  const DOCKER_COPY_FILES = `COPY --chown=node:node $APP_DIR .`;
58
59
 
59
- export const getDockerAppCopyAndBuildScript = (
60
+ export const getDockerAppCopyAndBuildScript = async (
60
61
  context: ComponentContextWithBuild,
61
62
  ) => {
62
- if (context.packageManagerInfo.isClassic) {
63
+ const packageManagerInfo = await context.packageManagerInfo;
64
+ if (packageManagerInfo.isClassic) {
63
65
  return new BashExpression(
64
66
  `
65
67
  RUN ${YARN_INSTALL_CLASSIC} --production --ignore-scripts
66
68
  ${DOCKER_COPY_FILES}
67
- RUN ${YARN_INSTALL_CLASSIC} --production
69
+ RUN ${YARN_INSTALL_CLASSIC} --production
68
70
  `.trim(),
69
71
  );
70
72
  }
@@ -86,7 +88,7 @@ RUN ${YARN_INSTALL_CLASSIC} --production
86
88
  // yarn >= 4 ships with build in plugins, see https://github.com/yarnpkg/berry/pull/4253
87
89
  // trying to import those fail on this version
88
90
  const doesNotShipWithBuiltInPlugins = ["2", "3"].some((v) =>
89
- context.packageManagerInfo.version.startsWith(v),
91
+ packageManagerInfo.version.startsWith(v),
90
92
  );
91
93
  const maybeAddWorkspaceToolsCommand = doesNotShipWithBuiltInPlugins
92
94
  ? "RUN yarn plugin import workspace-tools"
@@ -33,7 +33,7 @@ export const createComponentContext = async (
33
33
  );
34
34
  }
35
35
 
36
- const packageManagerInfo = await getPackageManagerInfoForComponent(
36
+ const packageManagerInfoPromise = getPackageManagerInfoForComponent(
37
37
  ctx.config,
38
38
  ctx.componentName,
39
39
  );
@@ -75,7 +75,10 @@ export const createComponentContext = async (
75
75
  componentConfigWithoutDefaults,
76
76
  );
77
77
 
78
- const environment = await getEnvironment(ctx);
78
+ const [environment, packageManagerInfo] = await Promise.all([
79
+ getEnvironment(ctx),
80
+ packageManagerInfoPromise,
81
+ ]);
79
82
  const { deploy, build, customJobs, dir } = componentConfig;
80
83
  const getComponentDirs: BuildContext["getComponentDirs"] = (mode) => [
81
84
  dir,
@@ -133,7 +136,7 @@ export const createComponentContext = async (
133
136
  : null,
134
137
 
135
138
  environment,
136
- packageManagerInfo: packageManagerInfo,
139
+ packageManagerInfo: packageManagerInfoPromise,
137
140
  pipelineType: ctx.pipelineType,
138
141
  trigger: ctx.trigger,
139
142
  };
@@ -43,7 +43,7 @@ export async function createWorkspaceContext({
43
43
  env,
44
44
  components,
45
45
  fullConfig: config,
46
- packageManagerInfo: await getPackageManagerInfoBase(),
46
+ packageManagerInfo: getPackageManagerInfoBase(),
47
47
  build: {
48
48
  type: "workspace",
49
49
  dir: workspaceConfig.dir ?? ".",
@@ -66,7 +66,9 @@ export function getCloudRunDeployScripts(context: ComponentContext) {
66
66
  ),
67
67
  ),
68
68
  ...Object.entries(deployConfig.workerPools ?? {})
69
- .filter(([_, workerPool]) => workerPool !== false && workerPool !== null)
69
+ .filter(
70
+ ([_, workerPool]) => workerPool !== false && workerPool !== null,
71
+ )
70
72
  .map(([name, workerPool]) =>
71
73
  getWorkerPoolDeployScript(
72
74
  context,
@@ -7,9 +7,9 @@ import { createDeployementJobs } from "../base";
7
7
 
8
8
  import { isOfDeployType } from "../types";
9
9
 
10
- export const createCustomDeployJobs = (
10
+ export const createCustomDeployJobs = async (
11
11
  context: ComponentContext,
12
- ): CatladderJob[] => {
12
+ ): Promise<CatladderJob[]> => {
13
13
  const deployConfig = context.deploy?.config;
14
14
 
15
15
  if (!isOfDeployType(deployConfig, "custom")) {
@@ -17,7 +17,7 @@ export const createCustomDeployJobs = (
17
17
  throw new Error("deploy config is not custom");
18
18
  }
19
19
  // FIXME: custom deploy currently assumes yarn-based project
20
- const yarnInstall = getYarnInstall(context, {
20
+ const yarnInstall = await getYarnInstall(context, {
21
21
  noCustomPostInstall: true,
22
22
  });
23
23
 
@@ -19,7 +19,7 @@ export * from "./types";
19
19
  export * from "./utils";
20
20
 
21
21
  export type DeployTypeDefinition<D extends DeployConfig> = {
22
- jobs: (context: ComponentContext) => CatladderJob[];
22
+ jobs: (context: ComponentContext) => CatladderJob[] | Promise<CatladderJob[]>;
23
23
  defaults: (envContext: EnvironmentContext<BuildConfig, D>) => PartialDeep<D>;
24
24
  additionalSecretKeys: (
25
25
  envContext: EnvironmentContext<BuildConfig, D>,
@@ -65,19 +65,21 @@ export const createAllJobs = async ({
65
65
 
66
66
  return {
67
67
  context: workspaceContext,
68
- jobs: createJobsForWorkspace(workspaceContext),
68
+ jobs: await createJobsForWorkspace(workspaceContext),
69
69
  };
70
70
  }),
71
71
  );
72
72
  }),
73
73
  ).then((f) => f.flat()),
74
74
 
75
- components: allComponentsContext.map((context) => {
76
- return {
77
- context,
78
- jobs: createJobsForComponentContext(context),
79
- };
80
- }),
75
+ components: await Promise.all(
76
+ allComponentsContext.map(async (context) => {
77
+ return {
78
+ context,
79
+ jobs: await createJobsForComponentContext(context),
80
+ };
81
+ }),
82
+ ),
81
83
  agents: await Promise.all(
82
84
  Object.keys(config.agents ?? {}).map(async (agentName) => {
83
85
  const context = await createAgentContext({ agentName, config });
@@ -24,19 +24,19 @@ const getCustomJobs = (context: ComponentContext) => {
24
24
  const rawJobs = context.customJobs;
25
25
  return injectDefaultVarsInCustomJobs(context, rawJobs);
26
26
  };
27
- export const createJobsForComponentContext = (
27
+ export const createJobsForComponentContext = async (
28
28
  context: ComponentContext,
29
- ): CatladderJob[] => {
30
- const buildJobs =
29
+ ): Promise<CatladderJob[]> => {
30
+ const [buildJobs, deployJobs] = await Promise.all([
31
31
  context.build.type !== "disabled"
32
32
  ? BUILD_TYPES[context.build.buildType].jobs(
33
33
  context as ComponentContextWithBuild,
34
34
  )
35
- : [];
36
- const deployJobs =
35
+ : [],
37
36
  context.componentConfig.deploy !== false
38
37
  ? DEPLOY_TYPES[context.componentConfig.deploy.type].jobs(context)
39
- : [];
38
+ : [],
39
+ ]);
40
40
 
41
41
  const customJobs = getCustomJobs(context);
42
42
 
@@ -2,11 +2,11 @@ import { WORKSPACE_BUILD_TYPES } from "../build";
2
2
  import type { WorkspaceContext } from "../types/context";
3
3
  import type { CatladderJob } from "../types/jobs";
4
4
 
5
- export const createJobsForWorkspace = (
5
+ export const createJobsForWorkspace = async (
6
6
  context: WorkspaceContext,
7
- ): CatladderJob[] => {
7
+ ): Promise<CatladderJob[]> => {
8
8
  const buildJobs =
9
- WORKSPACE_BUILD_TYPES[context.build.buildType].jobs(context);
9
+ await WORKSPACE_BUILD_TYPES[context.build.buildType].jobs(context);
10
10
 
11
11
  return buildJobs;
12
12
  };
@@ -1,4 +1,6 @@
1
1
  import { exec } from "child-process-promise";
2
+ import { readFile } from "fs/promises";
3
+ import { join } from "path";
2
4
  import memoizee from "memoizee";
3
5
  import type { YarnWorkspace } from "../../types";
4
6
  import { jsonParseOrThrow } from "../../utils/jsonParse";
@@ -10,9 +12,41 @@ const execOrFail = async (cmd: string, onFail: string): Promise<string> => {
10
12
  return onFail ?? null;
11
13
  }
12
14
  };
15
+
16
+ const readPackageManagerVersion = async (
17
+ dir: string,
18
+ ): Promise<string | null> => {
19
+ try {
20
+ const pkg = JSON.parse(await readFile(join(dir, "package.json"), "utf-8"));
21
+ const match = /^yarn@(.+)$/.exec(pkg.packageManager);
22
+ return match?.[1] ?? null;
23
+ } catch {
24
+ return null;
25
+ }
26
+ };
27
+
28
+ const getGitRoot = async (): Promise<string | null> => {
29
+ try {
30
+ return (await exec("git rev-parse --show-toplevel")).stdout.trim();
31
+ } catch {
32
+ return null;
33
+ }
34
+ };
35
+
13
36
  // export for mocking
14
37
  export const getYarnVersion = memoizee(
15
38
  async () => {
39
+ // Fast path: read from package.json packageManager field
40
+ const fromCwd = await readPackageManagerVersion(process.cwd());
41
+ if (fromCwd) return fromCwd;
42
+
43
+ const gitRoot = await getGitRoot();
44
+ if (gitRoot && gitRoot !== process.cwd()) {
45
+ const fromGitRoot = await readPackageManagerVersion(gitRoot);
46
+ if (fromGitRoot) return fromGitRoot;
47
+ }
48
+
49
+ // Fallback: invoke yarn CLI
16
50
  return await execOrFail("yarn --version", "");
17
51
  },
18
52
  { promise: true },
@@ -90,7 +90,7 @@ export type PackageManagerInfoBase = YarnPackageManagerInfoBase;
90
90
  export type ContextBeforeConfig = {
91
91
  componentName: string;
92
92
  fullConfig: Config;
93
- packageManagerInfo?: PackageManagerInfoComponent;
93
+ packageManagerInfo?: Promise<PackageManagerInfoComponent>;
94
94
  };
95
95
 
96
96
  export type BuildContextBase = {
@@ -175,7 +175,7 @@ export type ComponentContext<
175
175
  trigger?: PipelineTrigger;
176
176
  pipelineType?: PipelineType;
177
177
 
178
- packageManagerInfo: PackageManagerInfoComponent;
178
+ packageManagerInfo: Promise<PackageManagerInfoComponent>;
179
179
 
180
180
  customJobs?: CatladderJob[];
181
181
  };
@@ -208,7 +208,7 @@ export type WorkspaceContext = {
208
208
  name: string;
209
209
  fullConfig: Config;
210
210
  workspaceConfig: WorkspaceBuildConfig;
211
- packageManagerInfo: PackageManagerInfoBase;
211
+ packageManagerInfo: Promise<PackageManagerInfoBase>;
212
212
  components: Array<ComponentContext>;
213
213
  build: BuildContextWorkspace;
214
214
  trigger: PipelineTrigger;