npm.io
3.2.1 • Published 1 month agoCLI

@cmflow/cli

Licence
MIT
Version
3.2.1
Deps
20
Size
3.4 MB
Vulns
32
Weekly
0

@clubmed/cli aka ClubMed Flow


npm version semantic-release code style: prettier


npm i -g @cmflow/cli

CmFlow release using Semantic Release

Installation

CmFlow is compatible with semantic-release . You can use CmFlow release to deploy your projects based on CmFlow convention.

Add the cmflow to your project:

npm i --save-dev @cmflow/cli

Edit your package.json and add the following configuration:

{
  "flow": {
    "branch": {
      "develop": "master",
      "production": "master"
    }
  }
}

Then create release.config.js with this configuration:

import { defineConfig } from '@cmflow/cli'

export default defineConfig({
  verifyConditions: ['@cmflow/cli/semantic/core/verify-conditions'],
  analyzeCommits: ['@cmflow/cli/semantic/core/analyze-commits'],
  verifyRelease: ['@cmflow/cli/semantic/core/verify-release'],
  generateNotes: [
    [
      "@cmflow/cli/semantic/conditional", // add this task to trigger build npm task
      {
        // when: (context) => context.branch.type === "release" //  default condition to run the task
        run: ["@semantic-release/core/release-notes-generator"]
      }
    ]
  ],
  prepare: [
    '@cmflow/cli/semantic/core/prepare/bump-version',
    [
      '@cmflow/cli/semantic/core/prepare/run', // add this task to trigger build npm task
      {
        command: 'build'
      }
    ],
    [
      '@cmflow/cli/semantic/core/prepare/run', // add this task to trigger build npm task
      {
        command: 'test_e2e'
      }
    ],
    [
      '@cmflow/cli/semantic/core/conditional', // add this task to trigger build npm task
      {
        // when: (context) => context.branch.type === "release" //  default condition to run the task
        run:  [
          '@cmflow/cli/semantic/core/prepare/commit'
        ]
      }
    ]
  ],
  publish: [
    [
      '@cmflow/cli/semantic/core/conditional',
      {
        // when: (context) => context.branch.type === "release" //  default condition to run the task
        run: [
          '@cmflow/cli/semantic/core/sync-repository',
          '@semantic-release/github'
        ] // only run if the conditional rule is true
      }
    ],
    [
      '@cmflow/cli/semantic/core/exit', // run process.exit(0) if the branch is not a release branch - legacy: maybe not necessary now all task are conditional
      {
        when: (context) => context.nextRelease.channel === 'prerelease'
      }
    ]
  ],
  success: [
    [
      '@cmflow/cli/semantic/core/conditional',
      {
        // when: (context) => context.branch.type === "release" //  default condition to run the task
        run: '@semantic-release/github' // only run if the conditional rule is true
      }
    ]
  ],
  fail: [
    [
      "@cmflow/cli/semantic/core/conditional",
      {
        // when: (context) => context.branch.type === "release" //  default condition to run the task
        run: '@semantic-release/github' // only run if the conditional rule is true
      }
    ]
  ],
  npmPublish: false
})

Then edit your package.json add the following tasks on script property:

{
  "script": {
    "release": "cmrelease",
    "release_dry_run": "cmrelease --dry-run"
  }
}

Now, CmFlow and semantic release are correctly installed on your project.

Condition step (publish, success, fail)

CMFlow provide a @cmflow/cli/semantic/core/conditional task to run one task or many task only if a condition is true. The condition is a function that takes the semantic context as parameter and return a boolean.

You can customize the condition to run the task by adding a when property to the configuration object.

export default defineConfig({
  publish: [
    '@cmflow/cli/semantic/core/conditional',
    {
      when: (context) => context.branch.type === 'release', //  default condition to run the task
      run: ['@semantic-release/github', '@semantic-release/github'] // only run if the conditional rule is true
    }
  ]
})
Sync repository plugin (@cmflow/cli/semantic/core/sync-repository)

This plugin synchronizes your remote repository after publishing:

  • It pushes the current branch to the remote (with --set-upstream) if it is part of the candidate branches.
  • It then synchronizes the development branch with the production branch if they are different.

Options:

  • pluginOptions.branches: Allows you to explicitly define the list of branches that must be pushed to synchronize the remote. Example:
export default defineConfig({
  publish: [
    [
      '@cmflow/cli/semantic/core/conditional',
      {
        run: [
          [
            '@cmflow/cli/semantic/core/sync-repository',
            { includes: ['main', 'develop', 'release'] }
          ],
          '@semantic-release/github'
        ]
      }
    ]
  ]
})

Default behavior:

  • If pluginOptions.branches is not provided, the plugin falls back to semantic-release's branches configuration (options.branches). Values can be strings or branch objects; in the latter case, only the branch name is used.

Notes:

  • PRODUCTION_BRANCH and DEVELOP_BRANCH are defined via the CmFlow configuration (flow.branch.production and flow.branch.develop) and are used for the synchronization between production and develop.
Build and E2E Test

CmFlow release is able to run build and test_e2e task during the prepare step. It's useful when you want to deploy a docker image on docker hub with the right revision number in the package.json. The only requirement, is to have a build and test_e2e tasks in you npm scripts.

Example:

{
  "scripts": {
    "build": "docker-compose build",
    "test_e2e": "docker-compose up -d && sleep 10 && npm run test_cucumber && docker-compose stop"
  }
}

Then:

export default defineConfig({
  prepare: [
    [
      '@cmflow/cli/semantic/core/run',
      {
        command: 'build'
      }
    ],
    [
      '@cmflow/cli/semantic/core/run',
      {
        command: 'test_e2e'
      }
    ]
  ]
})
Generate release.info file

CmFlow release generate a release.info file in the root of your project. This file contains the branch name.

import { defineConfig } from '@cmflow/cli'

export default defineConfig({
  prepare: [
    '@cmflow/cli/semantic/prepare/bump-version',
    [
      '@cmflow/cli/semantic/prepare/release-info',
      {
        path: './resources/release.info'
      }
    ]
  ]
})
Deploy on Docker Hub

Add the following configuration to your release.config.js:

import { defineConfig } from '@cmflow/cli'

export default defineConfig({
  publish: [
    '@cmflow/cli/semantic/docker/publish'
  ]
});
Publish & Clean docker tags
import { defineConfig } from '@cmflow/cli'

export default defineConfig({
  success: [
    '@cmflow/cli/semantic/docker/success'
  ]
})
Configure CI

CmFlow release can be used with Travis CI, Circle CI and GitLab. You have to create these environments variables to allow git release note deployment, commit push and docker image deployment.

Variable Description
PROJECT_NAME The project to publish artifact on docker
SCM_TOKEN A SCM Token (GH_TOKEN or GITLAB_TOKEN)
GH_TOKEN (deprecated) A GitHub token personal access token.
GIT_USER_EMAIL User mail to sign the commit produced by CmFlow release
GIT_USER_NAME User name to sign the commit produced by CmFlow release
DOCKER_HUB_ID The docker hub id
DOCKER_HUB_PWD The docker password account

Jira Releases Command

The jira-releases command lists and (optionally) updates Jira versions related to an application version, then generates a share-ready delivery note.

Goal
  • For a given Jira project and component, retrieve all versions whose number is less than or equal to a target tag/version.
  • Display the issues associated with those versions and produce a delivery note.
  • Optionally mark the versions as "released" (with today's date) and move the corresponding issues to the "Livré en production" state.
  • Optionally trigger a CMS (Directus) workflow if configuration is provided.
Prerequisites
  • Access to the Jira API via environment variables:
  • Optional (to trigger a Directus workflow):
    • DIRECTUS_URL
    • DIRECTUS_FLOW_ID
    • DIRECTUS_ACCESS_TOKEN

If all three Directus variables are present, CmFlow considers CAN_TRIGGER_WORKFLOW=true and will attempt to run the workflow after updating releases.

Usage
cm jira-releases --project-id <PROJECT_KEY> --component <COMPONENT> --tag <VERSION> [--update] [--verbose]

Aliases and options (from bin/cm-jira-releases.js):

  • -c, --component <component>: Jira component filter (e.g., API).
  • -c, --project-id <projectId>: Jira project key (e.g., CMAB).
  • -t, --tag <tag>: target version to analyze (e.g., 0.3241.3, v0.3241.3, or version-0.3241.3). v and version- prefixes are automatically ignored.
  • -u, --update: updates Jira (marks the version(s) as released with today's date and moves the issues).
  • -v, --verbose: verbose logs.

Note: Jira versions are expected to follow <COMPONENT>-<version> or similar. For example, if --component API and a Jira version is named API-0.3241.3, the 0.3241.3 part will be compared to --tag using semver.

Detailed behavior
  1. Fetch all Jira versions for the project (projectId).
  2. Keep those whose version (after stripping component-, version-, and v prefixes) is semver <= the provided --tag.
  3. Print the delivery note to stdout (example below).
  4. If --update is provided:
    • Mark the relevant version(s) as released=true with releaseDate=YYYY-MM-DD (today's date).
  5. If the Directus config is complete, trigger the workflow by passing the list of version values for the processed releases.

Important: moving issue isn't supported from the cmflow. You have to create a jira automation script to move the issue on your board.

Example

From this repo, a sample script is provided in package.json:

yarn jira_releases

which runs, with .env loaded:

node --env-file=.env bin/cm.js jira-releases \
  --project-id CMAB \
  --component API \
  --tag 0.3241.3 \
  --verbose

Raw CLI example:

cm jira-releases --project-id CMAB --component API --tag v0.3241.3 --update
Best practices
  • Use a valid semver --tag (the v/version- prefixes are accepted).
  • Ensure your Jira versions follow a consistent schema that includes the component (<COMPONENT>-<version>) to allow matching.
  • First run without --update to preview the note and verify selected versions and issues.
  • Provide HTTPS_PROXY if your environment requires it to reach Jira/Directus.