@cmflow/cli 1.1.1-alpha.1 → 2.0.0-alpha.2

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.
package/.yarnrc.yml ADDED
@@ -0,0 +1,3 @@
1
+ nodeLinker: node-modules
2
+
3
+ yarnPath: .yarn/releases/yarn-4.7.0.cjs
package/README.md CHANGED
@@ -65,29 +65,50 @@ export default defineConfig({
65
65
  command: 'test_e2e'
66
66
  }
67
67
  ],
68
- '@cmflow/cli/semantif/prepare/post'
68
+ [
69
+ '@cmflow/cli/semantic/conditional', // add this task to trigger build npm task
70
+ {
71
+ // when: (context) => context.branch.type === "release" // default condition to run the task
72
+ run: [
73
+ '@cmflow/semantic/core/prepare/commit'
74
+ ]
75
+ }
76
+ ]
69
77
  ],
70
78
  publish: [
71
79
  [
72
- '@cmflow/cli/semantic/publish',
80
+ '@cmflow/cli/semantic/conditional',
81
+ {
82
+ // when: (context) => context.branch.type === "release" // default condition to run the task
83
+ run: [
84
+ '@cmflow/cli/semantic/publish/sync-repository',
85
+ '@semantic-release/github'
86
+ ] // only run if the conditional rule is true
87
+ }
88
+ ],
89
+ [
90
+ '@cmflow/cli/semantic/conditional', // run process.exit(0) if the branch is not a release branch - legacy: maybe not necessary now all task are conditional
73
91
  {
74
- runAfter: "@semantic-release/github" // only run if the conditional rule is true
92
+ when: (context) => context.branch.type !== 'release',
93
+ run: '@cmflow/cli/semantic/publish/exit.js'
75
94
  }
76
95
  ]
77
96
  ],
78
97
  success: [
98
+ '@cmflow/cli/semantic/success',
79
99
  [
80
- '@cmflow/cli/semantic/publish',
100
+ '@cmflow/cli/semantic/conditional',
81
101
  {
82
- runAfter: "@semantic-release/github" // only run if the conditional rule is true
102
+ // when: (context) => context.branch.type === "release" // default condition to run the task
103
+ run: '@semantic-release/github' // only run if the conditional rule is true
83
104
  }
84
105
  ]
85
106
  ],
86
107
  fail: [
87
108
  [
88
- '@cmflow/cli/semantic/fail',
89
109
  {
90
- runAfter: "@semantic-release/github" // only run if the conditional rule is true
110
+ // when: (context) => context.branch.type === "release" // default condition to run the task
111
+ run: '@semantic-release/github' // only run if the conditional rule is true
91
112
  }
92
113
  ]
93
114
  ],
@@ -108,6 +129,25 @@ Then edit your `package.json` add the following tasks on script property:
108
129
 
109
130
  Now, CmFlow and semantic release are correctly installed on your project.
110
131
 
132
+ ### Condition step (publish, success, fail)
133
+
134
+ CMFlow provide a `@cmflow/cli/semantic/conditional` task to run one task or many task only if a condition is true. The condition is a
135
+ function that takes the semantic context as parameter and return a boolean.
136
+
137
+ You can customize the condition to run the task by adding a `when` property to the configuration object.
138
+
139
+ ```javascript
140
+ export default defineConfig({
141
+ publish: [
142
+ '@cmflow/cli/semantic/conditional',
143
+ {
144
+ when: (context) => context.branch.type === 'release', // default condition to run the task
145
+ run: ['@semantic-release/github', '@semantic-release/github'] // only run if the conditional rule is true
146
+ }
147
+ ]
148
+ })
149
+ ```
150
+
111
151
  ### Build and E2E Test
112
152
 
113
153
  CmFlow release are able to run `build` and `test_e2e` task during the prepare step. It's useful when you want to
@@ -135,9 +175,9 @@ import { defineConfig } from '@cmflow/cli'
135
175
  export default defineConfig({
136
176
  publish: [
137
177
  [
138
- '@cmflow/cli/semantic/publish',
178
+ '@cmflow/cli/semantic/conditional',
139
179
  {
140
- runAfter: '@semantic-release/github' // only run if the conditional rule is true
180
+ run: '@semantic-release/github'
141
181
  }
142
182
  ],
143
183
  '@cmflow/cli/semantic/docker/publish'
File without changes
package/bin/cm-config.js CHANGED
File without changes
package/bin/cm-fetch.js CHANGED
File without changes
package/bin/cm-finish.js CHANGED
File without changes
package/bin/cm-merge.js CHANGED
File without changes
package/bin/cm-publish.js CHANGED
File without changes
package/bin/cm-push.js CHANGED
File without changes
package/bin/cm-rebase.js CHANGED
File without changes
File without changes
package/bin/cm-start.js CHANGED
File without changes
package/bin/cm.js CHANGED
File without changes
package/bin/cmrelease.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmflow/cli",
3
- "version": "1.1.1-alpha.1",
3
+ "version": "2.0.0-alpha.2",
4
4
  "description": "An awesome Git Flow",
5
5
  "author": "camfou",
6
6
  "license": "MIT",
@@ -8,23 +8,22 @@
8
8
  "main": "./src/index.js",
9
9
  "module": "./src/index.js",
10
10
  "type": "module",
11
- "private": false,
12
11
  "bin": {
12
+ "checkfeatures": "./bin/checkfeatures.sh",
13
13
  "cm": "./bin/cm.js",
14
+ "cmchangelog": "bin/cm-changelog.js",
15
+ "cmconfig": "bin/cm-config.js",
16
+ "cmexpedit": "./bin/cmexpedit.sh",
14
17
  "cmfetch": "bin/cm-fetch.js",
15
- "cmrebase": "bin/cm-rebase.js",
16
18
  "cmfinish": "bin/cm-finish.js",
17
- "cmexpedit": "./bin/cmexpedit.sh",
19
+ "cmmerge": "./bin/cm-merge.js",
18
20
  "cmpublish": "bin/cm-publish.js",
19
- "cmrepublish": "bin/cm-republish.js",
20
- "cmpush": "bin/cm-push.js",
21
21
  "cmpull": "./bin/cmpull.sh",
22
- "cmstart": "bin/cm-start.js",
23
- "checkfeatures": "./bin/checkfeatures.sh",
22
+ "cmpush": "bin/cm-push.js",
23
+ "cmrebase": "bin/cm-rebase.js",
24
24
  "cmrelease": "./bin/cmrelease.js",
25
- "cmmerge": "./bin/cm-merge.js",
26
- "cmchangelog": "bin/cm-changelog.js",
27
- "cmconfig": "bin/cm-config.js"
25
+ "cmrepublish": "bin/cm-republish.js",
26
+ "cmstart": "bin/cm-start.js"
28
27
  },
29
28
  "exports": {
30
29
  ".": "./index.js",
@@ -33,6 +32,8 @@
33
32
  "./semantic/docker/*": "./src/semantic-release/docker/*.js"
34
33
  },
35
34
  "dependencies": {
35
+ "@semantic-release/release-notes-generator": ">=14.0.3",
36
+ "any-observable": "0.5.1",
36
37
  "axios": "1.8.2",
37
38
  "chalk": "^4.1.0",
38
39
  "commander": "5.1.0",
@@ -47,14 +48,15 @@
47
48
  "listr": "0.14.3",
48
49
  "lodash": "4.17.21",
49
50
  "rxjs": "7.8.1",
50
- "semantic-release": "23.1.1",
51
- "semver": "7.3.7",
51
+ "semantic-release": ">=24.2.3",
52
+ "semver": "7.7.1",
52
53
  "split": "1.0.1"
53
54
  },
54
55
  "devDependencies": {
56
+ "@semantic-release/github": "11.0.1",
55
57
  "@stylistic/eslint-plugin": "^4.2.0",
56
- "@typescript-eslint/parser": "8.26.1",
57
58
  "@typescript-eslint/eslint-plugin": "8.26.1",
59
+ "@typescript-eslint/parser": "8.26.1",
58
60
  "eslint": "9.21.0",
59
61
  "eslint-config-prettier": "10.0.2",
60
62
  "eslint-formatter-junit": "^8.40.0",
@@ -62,14 +64,13 @@
62
64
  "eslint-plugin-simple-import-sort": "12.1.1",
63
65
  "eslint-plugin-vitest": "0.5.4",
64
66
  "husky": "4.3.6",
65
- "prettier": "3.5.1",
66
67
  "lint-staged": "10.5.3",
67
- "vitest": "^3.0.8",
68
- "typescript": "5.8.2"
68
+ "prettier": "3.5.1",
69
+ "typescript": "5.8.2",
70
+ "vitest": "^3.0.8"
69
71
  },
70
72
  "peerDependencies": {
71
73
  "@semantic-release/commit-analyzer": "^11.1.0",
72
- "@semantic-release/github": "^10.1.1",
73
74
  "@semantic-release/release-notes-generator": "^12.1.0"
74
75
  },
75
76
  "peerDependenciesMeta": {
@@ -107,5 +108,6 @@
107
108
  "develop": "master",
108
109
  "production": "master"
109
110
  }
110
- }
111
+ },
112
+ "packageManager": "yarn@4.7.0"
111
113
  }
@@ -20,33 +20,12 @@ export default defineConfig({
20
20
  }
21
21
  ],
22
22
  verifyConditions: ["./src/semantic/core/verify-conditions.js"],
23
- analyzeCommits: ["./src/semantic/core/analyze-commits.js"],
23
+ analyzeCommits: ["@semantic-release/commit-analyzer"],
24
24
  verifyRelease: ["./src/semantic/core/verify-release.js"],
25
25
  generateNotes: ["./src/semantic/core/generate-notes.js"],
26
- prepare: ["./src/semantic/core/prepare/bump-version.js", "./src/semantic/core/prepare/post.js"],
27
- publish: [
28
- [
29
- "./src/semantic/core/publish.js",
30
- {
31
- runAfter: "@semantic-release/github"
32
- }
33
- ]
34
- ],
35
- success: [
36
- [
37
- "./src/semantic/core/success.js",
38
- {
39
- runAfter: "@semantic-release/github"
40
- }
41
- ]
42
- ],
43
- fail: [
44
- [
45
- "./src/semantic/core/fail.js",
46
- {
47
- runAfter: "@semantic-release/github"
48
- }
49
- ]
50
- ],
26
+ prepare: ["./src/semantic/core/prepare/bump-version.js", "./src/semantic/core/prepare/commit.js"],
27
+ publish: ["./src/semantic/core/publish/sync-repository.js", "@semantic-release/github"],
28
+ success: ["@semantic-release/github"],
29
+ fail: ["@semantic-release/github"],
51
30
  npmPublish: false
52
31
  });
@@ -0,0 +1,25 @@
1
+ import { getConfig } from "../../common/index.js";
2
+ export function success(pluginConfig, context) {
3
+ return runAll(pluginConfig, context, context.branch?.type === "release");
4
+ }
5
+
6
+ export function publish(pluginConfig, context) {
7
+ return runAll(pluginConfig, context, context.branch?.type === "release");
8
+ }
9
+
10
+ export function fail(pluginConfig, context) {
11
+ return runAll(pluginConfig, context, context.branch?.type === "release");
12
+ }
13
+
14
+ async function runAll(pluginConfig, context, defaultCondition) {
15
+ context.config = getConfig();
16
+
17
+ const condition = pluginConfig.when !== undefined ? pluginConfig.if(context) : defaultCondition;
18
+
19
+ if (condition && pluginConfig.run) {
20
+ const tasks = [].concat(pluginConfig.run);
21
+ for (const task of tasks) {
22
+ await task(pluginConfig, context);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,29 @@
1
+ import { configureGitWorkspace, getConfig, git } from "../../../common/index.js";
2
+
3
+ export async function prepare(pluginConfig, context) {
4
+ context.config = getConfig();
5
+
6
+ const {
7
+ logger,
8
+ config: { CI_NAME, BUILD_NUMBER }
9
+ } = context;
10
+
11
+ logger.info("Prepare release");
12
+
13
+ configureGitWorkspace(context);
14
+
15
+ logger.info("Adding files to commit");
16
+ git.add("-A").sync();
17
+
18
+ logger.info("Get commit stage status");
19
+ git.status();
20
+
21
+ const revisionMessage = `${CI_NAME} build: ${context.branch.name} ${BUILD_NUMBER} ${context.nextRelease.gitTag} [ci skip]`;
22
+
23
+ logger.info("Commit changes with revision message: ");
24
+ logger.info(revisionMessage);
25
+
26
+ git.commit("-m", revisionMessage).sync();
27
+
28
+ logger.success("Change committed");
29
+ }
@@ -0,0 +1,7 @@
1
+ import { getConfig } from "../../../common/index.js";
2
+
3
+ export async function prepare(pluginConfig, context) {
4
+ context.config = getConfig();
5
+ // avoid next semantic-release steps when is a prerelease or release branch with SKIP_GITHUB_PUBLISH
6
+ process.exit(0);
7
+ }
@@ -0,0 +1,42 @@
1
+ import { getConfig, git } from "../../../common/index.js";
2
+
3
+ export async function publish(pluginConfig, context) {
4
+ context.config = getConfig();
5
+
6
+ const {
7
+ logger,
8
+ config: { PRODUCTION_BRANCH, ORIGIN, DEVELOP_BRANCH }
9
+ } = context;
10
+
11
+ logger.info("Prepare release");
12
+
13
+ async function asyncCatchError(fn) {
14
+ try {
15
+ return await fn();
16
+ } catch (er) {
17
+ context.logger.error(String(er), er.stack);
18
+ }
19
+ }
20
+
21
+ await asyncCatchError(() => git.fetch());
22
+
23
+ if ([PRODUCTION_BRANCH, "alpha", "beta", "rc"].includes(context.branch.name)) {
24
+ logger.info(`Push ${PRODUCTION_BRANCH}`);
25
+
26
+ await asyncCatchError(() => {
27
+ logger.info(`git push --quiet --set-upstream ${ORIGIN} ${context.branch.name}`);
28
+
29
+ return git.push("--quiet", "--set-upstream", ORIGIN, context.branch.name);
30
+ });
31
+ }
32
+
33
+ if (PRODUCTION_BRANCH !== DEVELOP_BRANCH) {
34
+ logger.info(`Sync ${DEVELOP_BRANCH} with ${PRODUCTION_BRANCH}`);
35
+ logger.info(`git push -f ${ORIGIN} ${PRODUCTION_BRANCH}:refs/heads/${DEVELOP_BRANCH}`);
36
+
37
+ await asyncCatchError(async () => {
38
+ await git.push("-f", ORIGIN, `${PRODUCTION_BRANCH}:refs/heads/${DEVELOP_BRANCH}`);
39
+ logger.success(`${ORIGIN}/${DEVELOP_BRANCH} branch correctly updated`);
40
+ });
41
+ }
42
+ }
@@ -2,4 +2,14 @@ import omit from "lodash/omit.js";
2
2
 
3
3
  import { WORKFLOW_CONFIGURATION } from "../../workflow/index.js";
4
4
 
5
- export const releaseRules = WORKFLOW_CONFIGURATION.map((props) => omit(props, ["label"]));
5
+ export const releaseRules = [
6
+ {
7
+ breaking: true,
8
+ release: "major"
9
+ },
10
+ {
11
+ revert: true,
12
+ release: "patch"
13
+ },
14
+ ...WORKFLOW_CONFIGURATION.map((props) => omit(props, ["label"]))
15
+ ];
@@ -1,29 +0,0 @@
1
- import { git } from "../../common/index.js";
2
-
3
- /**
4
- * Remove the tag from the git repository if the release is not a prerelease.
5
- *
6
- * Add runAfter property with the semantic-release plugin name to run after the fail task.
7
- *
8
- * @param pluginConfig {{runAfter: string}}
9
- * @param context
10
- * @return {Promise<void>}
11
- */
12
- export async function fail(pluginConfig, context) {
13
- if (context.branch && context.branch.type !== "prerelease") {
14
- const {
15
- tagFormat,
16
- config: { ORIGIN }
17
- } = context;
18
-
19
- try {
20
- await git.push("--delete", ORIGIN, tagFormat.replace("${version}", context.nextRelease.version));
21
- } catch {}
22
-
23
- if (pluginConfig.runAfter) {
24
- const { fail } = await import(pluginConfig.runAfter);
25
-
26
- await fail(pluginConfig, context);
27
- }
28
- }
29
- }
@@ -1,38 +0,0 @@
1
- import { configureGitWorkspace, getConfig, git } from "../../../common/index.js";
2
-
3
- export async function prepare(pluginConfig, context) {
4
- context.config = getConfig();
5
- const { branch } = context;
6
-
7
- if (branch.type === "release") {
8
- context.config = getConfig();
9
-
10
- const {
11
- logger,
12
- config: { CI_NAME, BUILD_NUMBER }
13
- } = context;
14
-
15
- logger.info("Prepare release");
16
-
17
- configureGitWorkspace(context);
18
-
19
- logger.info("Adding files to commit");
20
- git.add("-A").sync();
21
-
22
- logger.info("Get commit stage status");
23
- git.status();
24
-
25
- const revisionMessage = `${CI_NAME} build: ${context.branch.name} ${BUILD_NUMBER} ${context.nextRelease.gitTag} [ci skip]`;
26
-
27
- logger.info("Commit changes with revision message: ");
28
- logger.info(revisionMessage);
29
-
30
- git.commit("-m", revisionMessage).sync();
31
-
32
- logger.success("Change committed");
33
- return;
34
- }
35
-
36
- // avoid next semantic-release steps when is a prerelease or release branch with SKIP_GITHUB_PUBLISH
37
- process.exit(0);
38
- }
@@ -1,9 +0,0 @@
1
- export async function publish(pluginConfig, context) {
2
- const { branch } = context;
3
-
4
- if (branch.type === "release" && pluginConfig.runAfter) {
5
- const { publish } = await import(pluginConfig.runAfter);
6
-
7
- await publish(pluginConfig, context);
8
- }
9
- }
@@ -1,37 +0,0 @@
1
- import { getConfig } from "../../common/get-config.js";
2
- import { git } from "../../common/index.js";
3
-
4
- /**
5
- * Add runAfter property with the semantic-release plugin name to run after the success task
6
- * depending on the branch type.
7
- *
8
- * @param pluginConfig {{runAfter: string}}
9
- * @param context
10
- * @return {Promise<void>}
11
- */
12
- export async function success(pluginConfig, context) {
13
- context.config = getConfig();
14
- const {
15
- branch,
16
- logger,
17
- config: { PRODUCTION_BRANCH, ORIGIN, DEVELOP_BRANCH }
18
- } = context;
19
-
20
- if (branch.type !== "prerelease") {
21
- await git.push("--quiet", "--set-upstream", ORIGIN, PRODUCTION_BRANCH);
22
-
23
- if (PRODUCTION_BRANCH !== DEVELOP_BRANCH) {
24
- logger.start(`Reset HEAD of ${ORIGIN}/${DEVELOP_BRANCH} branch to HEAD of ${ORIGIN}/${PRODUCTION_BRANCH} `);
25
-
26
- await git.push("-f", ORIGIN, `refs/remotes/${ORIGIN}/${PRODUCTION_BRANCH}:refs/heads/${DEVELOP_BRANCH}`);
27
-
28
- logger.success(`${ORIGIN}/${DEVELOP_BRANCH} branch correctly updated`);
29
- }
30
-
31
- if (pluginConfig.runAfter) {
32
- const { success } = await import(pluginConfig.runAfter);
33
-
34
- await success(pluginConfig, context);
35
- }
36
- }
37
- }