@catladder/pipeline 1.11.0 → 1.12.0

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.
@@ -1,8 +1,25 @@
1
1
  import { Context } from "../../types";
2
2
 
3
+ export const getYarnInstallCommand = (
4
+ context: Context,
5
+ options?: {
6
+ prodOnly?: boolean;
7
+ noScripts?: boolean;
8
+ }
9
+ ) =>
10
+ context.packageManagerInfo?.isClassic
11
+ ? `yarn install --frozen-lockfile ${
12
+ options?.prodOnly ? "--production" : ""
13
+ } ${options?.noScripts ? "--ignore-scripts" : ""}`
14
+ : options?.prodOnly
15
+ ? `${
16
+ options?.noScripts ? "YARN_ENABLE_SCRIPTS=false " : ""
17
+ }yarn plugin import workspace-tools && yarn workspaces focus --production` // needs yarn plugin import workspace-tools
18
+ : `${
19
+ options?.noScripts ? "YARN_ENABLE_SCRIPTS=false " : ""
20
+ }yarn install --immutable`;
21
+
3
22
  export const getYarnInstall = (context: Context) => [
4
23
  "if [ -f ./.nvmrc ]; then source /root/.nvm/nvm.sh && nvm install <<< .nvmrc; fi",
5
- context.yarnInfo?.isClassic
6
- ? "yarn install --frozen-lockfile"
7
- : "yarn install --immutable",
24
+ getYarnInstallCommand(context),
8
25
  ];
@@ -46,6 +46,12 @@ export type BuildConfigBase = {
46
46
  | {
47
47
  command?: string | string[];
48
48
  };
49
+
50
+ /**
51
+ * additional paths for artifacts,
52
+ * by default "dist" and ".next" are allways included
53
+ */
54
+ artifactsPaths?: [];
49
55
  };
50
56
 
51
57
  export type BuildConfigNodeBase = BuildConfigBase;
@@ -1,11 +1,15 @@
1
- import { merge, mergeWith } from "lodash";
2
1
  import slugify from "slugify";
3
2
  import { BUILD_TYPES } from "../build";
4
3
  import { BuildConfig } from "../build/types";
5
4
  import { DEPLOY_TYPES, getKubernetesNamespace } from "../deploy";
6
5
  import { DeployConfig } from "../deploy/types";
7
6
  import { Config, isKnowEnvType, DevLocalEnvConfig } from "../types/config";
8
- import { CommitInfo, Context, Environment, YarnInfo } from "../types/context";
7
+ import {
8
+ CommitInfo,
9
+ Context,
10
+ Environment,
11
+ PackageManagerInfo,
12
+ } from "../types/context";
9
13
  import { mergeWithMergingArrays } from "../utils";
10
14
 
11
15
  const sanitizeForEnVar = (s: string) => s.replace(/-/g, "_");
@@ -164,7 +168,7 @@ export const createContext = (
164
168
  componentName: string,
165
169
  env: string,
166
170
  commitInfo?: CommitInfo,
167
- yarnInfo?: YarnInfo
171
+ packageManagerInfo?: PackageManagerInfo
168
172
  ): Context => {
169
173
  if (!/^[a-z0-9-]+$/.test(componentName)) {
170
174
  throw new Error(
@@ -208,6 +212,6 @@ export const createContext = (
208
212
  componentName,
209
213
  environment: getEnvironment(config, componentName, env, commitInfo),
210
214
  commitInfo,
211
- yarnInfo,
215
+ packageManagerInfo,
212
216
  };
213
217
  };
@@ -7,7 +7,7 @@ import { Config, PipelineTrigger } from "../types/config";
7
7
  import { Context, CommitInfo } from "../types/context";
8
8
  import { GitlabJob, GitlabJobDef, GitlabJobs } from "../types/gitlab-types";
9
9
  import { notNil } from "../utils";
10
- import { getYarnInfo } from "./yarnInfo";
10
+ import { getPackageManagerInfo } from "./packageManager";
11
11
 
12
12
  const createRawJobs = (context: Context): GitlabJobs => {
13
13
  if (context.componentConfig.deploy === false) {
@@ -134,7 +134,7 @@ export const createJobs = async (
134
134
  trigger,
135
135
  };
136
136
 
137
- const yarnInfo = await getYarnInfo(config, componentName);
137
+ const packageManagerInfo = await getPackageManagerInfo(config, componentName);
138
138
 
139
139
  return envs.reduce((acc, env) => {
140
140
  const context = createContext(
@@ -142,7 +142,7 @@ export const createJobs = async (
142
142
  componentName,
143
143
  env,
144
144
  commitInfo,
145
- yarnInfo
145
+ packageManagerInfo
146
146
  );
147
147
  const jobs = addStageNeeds(createRawJobs(context));
148
148
 
@@ -0,0 +1,99 @@
1
+ import { exec } from "child-process-promise";
2
+ import { Config, PackageManagerInfo } from "../types";
3
+ import { pathEqual } from "path-equal";
4
+ import memoizee from "memoizee";
5
+ import { join } from "path";
6
+ import { existsSync } from "fs";
7
+
8
+ const execOrFail = async (cmd: string, onFail: string): Promise<string> => {
9
+ try {
10
+ return await exec(cmd).then((r) => r.stdout);
11
+ } catch (e) {
12
+ return onFail ?? null;
13
+ }
14
+ };
15
+
16
+ const getYarnVersion = memoizee(
17
+ async () => {
18
+ return await execOrFail("yarn --version", "");
19
+ },
20
+ { promise: true }
21
+ );
22
+
23
+ const getWorkspaces = memoizee(
24
+ async (isClassic: boolean): Promise<PackageManagerInfo["workspaces"]> => {
25
+ return isClassic
26
+ ? Object.values(
27
+ JSON.parse(
28
+ JSON.parse(await execOrFail("yarn workspaces --json info", "{}"))
29
+ ?.data ?? "{}"
30
+ )
31
+ )
32
+ : JSON.parse(
33
+ `[${(await execOrFail("yarn workspaces list --json --verbose", ""))
34
+ .trim()
35
+ .split("\n")
36
+ .join(",")}]`
37
+ );
38
+ },
39
+ { promise: true }
40
+ );
41
+ export const getPackageManagerInfo = async (
42
+ config: Config,
43
+ componentName: string
44
+ ): Promise<PackageManagerInfo> => {
45
+ // currently only supports yarn
46
+ const version = await getYarnVersion();
47
+ if (!version) throw new Error("could not get yarn version");
48
+ const isClassic = version.startsWith("1");
49
+
50
+ const component = config.components[componentName];
51
+ const workspaces = await getWorkspaces(isClassic);
52
+ const currentWorkspace = workspaces.find((w) =>
53
+ pathEqual(component.dir, w.location)
54
+ );
55
+ const componentIsInWorkspace = Boolean(currentWorkspace);
56
+ const workspaceRoot = "."; // currently we assume the root folder, later on we might support nested workspaces
57
+ const packageJson = join(component.dir, "package.json");
58
+ const workspacePackageJson = componentIsInWorkspace
59
+ ? join(workspaceRoot, "package.json")
60
+ : null;
61
+
62
+ const lockFile = componentIsInWorkspace
63
+ ? join(workspaceRoot, "yarn.lock")
64
+ : join(component.dir, "yarn.lock");
65
+ const configFiles = [".yarnrc", ".yarnrc.yml", ".npmrc", ".yarn"]; // ".yarn" is yarn 2 folder
66
+ const rcFiles = (
67
+ componentIsInWorkspace
68
+ ? configFiles
69
+ : configFiles.map((f) => join(component.dir, f))
70
+ ).filter((f) => existsSync(f));
71
+
72
+ // get all folders that this workspace depend on
73
+ // we will later copy them into the docker build
74
+ const workspaceDependencies = currentWorkspace
75
+ ? ([
76
+ ...currentWorkspace.workspaceDependencies,
77
+ ...currentWorkspace.mismatchedWorkspaceDependencies,
78
+ ]
79
+ .map((name) => workspaces.find((w) => w.name === name)?.location)
80
+ .filter(Boolean) as string[])
81
+ : [];
82
+
83
+ const pathsToCopyInDocker = [
84
+ packageJson,
85
+ ...(workspacePackageJson ? [workspacePackageJson] : []),
86
+ lockFile,
87
+ ...rcFiles,
88
+ ...workspaceDependencies,
89
+ ];
90
+ return {
91
+ type: "yarn",
92
+ workspaces,
93
+ version,
94
+ isClassic,
95
+ currentWorkspace,
96
+ componentIsInWorkspace,
97
+ pathsToCopyInDocker,
98
+ };
99
+ };
@@ -22,21 +22,28 @@ export type CommitInfo = {
22
22
  trigger: PipelineTrigger;
23
23
  };
24
24
 
25
- export type YarnInfo = {
25
+ type Workspace = {
26
+ name: string;
27
+ location: string;
28
+ workspaceDependencies: string[];
29
+ mismatchedWorkspaceDependencies: string[];
30
+ };
31
+ export type YarnPackageManagerInfo = {
32
+ type: "yarn";
26
33
  version: string;
27
- workspaces: { location: string }[];
34
+ workspaces: Workspace[];
35
+ currentWorkspace?: Workspace;
28
36
  isClassic: boolean;
29
37
  componentIsInWorkspace: boolean;
30
- /**
31
- * files relevant for the package manager
32
- */
33
- files: string[];
38
+ pathsToCopyInDocker: string[];
34
39
  };
40
+
41
+ export type PackageManagerInfo = YarnPackageManagerInfo;
35
42
  export type Context = {
36
43
  componentName: string;
37
44
  componentConfig: ComponentConfig;
38
45
  fullConfig: Config;
39
46
  environment: Environment;
40
47
  commitInfo?: CommitInfo;
41
- yarnInfo?: YarnInfo;
48
+ packageManagerInfo?: PackageManagerInfo;
42
49
  };
@@ -1,2 +0,0 @@
1
- import { Config, YarnInfo } from "../types";
2
- export declare const getYarnInfo: (config: Config, componentName: string) => Promise<YarnInfo>;
@@ -1,73 +0,0 @@
1
- import { exec } from "child-process-promise";
2
- import { Config, YarnInfo } from "../types";
3
- import { pathEqual } from "path-equal";
4
- import memoizee from "memoizee";
5
- import { join } from "path";
6
- import { existsSync } from "fs";
7
-
8
- const execOrFail = async (cmd: string, onFail: string): Promise<string> => {
9
- try {
10
- return await exec(cmd).then((r) => r.stdout);
11
- } catch (e) {
12
- return onFail ?? null;
13
- }
14
- };
15
-
16
- const getYarnVersion = memoizee(
17
- async () => {
18
- return await execOrFail("yarn --version", "");
19
- },
20
- { promise: true }
21
- );
22
-
23
- const getWorkspaces = memoizee(
24
- async (isClassic: boolean): Promise<YarnInfo["workspaces"]> => {
25
- return isClassic
26
- ? Object.values(
27
- JSON.parse(
28
- JSON.parse(await execOrFail("yarn workspaces --json info", "{}"))
29
- ?.data ?? "{}"
30
- )
31
- )
32
- : JSON.parse(
33
- `[${(await execOrFail("yarn workspaces list --json", ""))
34
- .trim()
35
- .split("\n")
36
- .join(",")}]`
37
- );
38
- },
39
- { promise: true }
40
- );
41
- export const getYarnInfo = async (
42
- config: Config,
43
- componentName: string
44
- ): Promise<YarnInfo> => {
45
- const version = await getYarnVersion();
46
- if (!version) throw new Error("could not get yarn version");
47
- const isClassic = version.startsWith("1");
48
-
49
- const component = config.components[componentName];
50
- const workspaces = await getWorkspaces(isClassic);
51
- const componentIsInWorkspace = workspaces.some((w) =>
52
- pathEqual(component.dir, w.location)
53
- );
54
- const packageJson = join(component.dir, "package.json");
55
- const lockFile = componentIsInWorkspace
56
- ? "yarn.lock"
57
- : join(component.dir, "yarn.lock");
58
- const RC_FILES = [".yarnrc", ".npmrc"];
59
- const possibleRcFiles = componentIsInWorkspace
60
- ? RC_FILES
61
- : RC_FILES.map((f) => join(component.dir, f));
62
- const files = [packageJson, lockFile, ...possibleRcFiles].filter((f) =>
63
- existsSync(f)
64
- );
65
-
66
- return {
67
- workspaces,
68
- version,
69
- isClassic,
70
- componentIsInWorkspace,
71
- files,
72
- };
73
- };