@cmflow/cli 0.65.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.
- package/README.md +106 -0
- package/bin/checkfeatures.sh +5 -0
- package/bin/cm-changelog.js +17 -0
- package/bin/cm-clean.js +10 -0
- package/bin/cm-config.js +14 -0
- package/bin/cm-deploy.js +11 -0
- package/bin/cm-fetch.js +11 -0
- package/bin/cm-finish.js +13 -0
- package/bin/cm-publish-pages.js +11 -0
- package/bin/cm-publish.js +14 -0
- package/bin/cm-push.js +14 -0
- package/bin/cm-rebase.js +14 -0
- package/bin/cm-republish.js +11 -0
- package/bin/cm-start.js +20 -0
- package/bin/cm.js +20 -0
- package/bin/cmexpedit.sh +9 -0
- package/bin/cmpull.sh +7 -0
- package/bin/cmrelease.js +3 -0
- package/package.json +88 -0
- package/release.config.js +19 -0
- package/semantic.js +1 -0
- package/src/commands/changelog.js +47 -0
- package/src/commands/clean.js +30 -0
- package/src/commands/config.js +23 -0
- package/src/commands/deploy.js +39 -0
- package/src/commands/fetch.js +21 -0
- package/src/commands/finish.js +44 -0
- package/src/commands/index.js +10 -0
- package/src/commands/prompts/branches.js +38 -0
- package/src/commands/publish-pages.js +29 -0
- package/src/commands/push.js +26 -0
- package/src/commands/rebase.js +38 -0
- package/src/commands/release.js +36 -0
- package/src/commands/republish.js +24 -0
- package/src/commands/start.js +82 -0
- package/src/commands/tasks/push-branch.js +16 -0
- package/src/commands/tasks/rebase-all-branches.js +34 -0
- package/src/commands/tasks/refresh-repository.js +33 -0
- package/src/commands/tasks/run-test.js +23 -0
- package/src/commands/tasks/update-branch.js +40 -0
- package/src/commands/tasks/update-dependencies.js +37 -0
- package/src/commands/utils/check-install.js +31 -0
- package/src/common/cli/cli.js +107 -0
- package/src/common/cli/docker.js +63 -0
- package/src/common/cli/docker.test.js +128 -0
- package/src/common/cli/git.js +130 -0
- package/src/common/cli/git.test.js +205 -0
- package/src/common/cli/heroku.js +21 -0
- package/src/common/cli/heroku.test.js +56 -0
- package/src/common/cli/lerna.js +25 -0
- package/src/common/cli/lerna.test.js +48 -0
- package/src/common/cli/npm.js +33 -0
- package/src/common/cli/npm.test.js +47 -0
- package/src/common/cli/yarn.js +33 -0
- package/src/common/cli/yarn.test.js +48 -0
- package/src/common/configure-git-workspace.js +27 -0
- package/src/common/get-config.js +135 -0
- package/src/common/get-package-json.js +7 -0
- package/src/common/get-release-config.js +7 -0
- package/src/common/index.js +10 -0
- package/src/common/run-command.js +61 -0
- package/src/common/run-command.test.js +63 -0
- package/src/index.js +1 -0
- package/src/main.js +10 -0
- package/src/semantic-release/actions/analyze-commits.js +9 -0
- package/src/semantic-release/actions/fail.js +16 -0
- package/src/semantic-release/actions/generate-notes.js +11 -0
- package/src/semantic-release/actions/index.js +8 -0
- package/src/semantic-release/actions/prepare.js +101 -0
- package/src/semantic-release/actions/publish.js +17 -0
- package/src/semantic-release/actions/success.js +30 -0
- package/src/semantic-release/actions/verify-conditions.js +30 -0
- package/src/semantic-release/actions/verify-release.js +7 -0
- package/src/semantic-release/get-semantic-config.js +115 -0
- package/src/semantic-release/utils/calculate-snapshot-version.js +9 -0
- package/src/semantic-release/utils/calculate-snapshot-version.test.js +57 -0
- package/src/semantic-release/utils/display-package-info.js +11 -0
- package/src/semantic-release/utils/display-release-info.js +12 -0
- package/src/semantic-release/utils/docker-clean-tags.js +45 -0
- package/src/semantic-release/utils/docker-clean-tags.test.js +54 -0
- package/src/semantic-release/utils/docker-publish.js +36 -0
- package/src/semantic-release/utils/docker-publish.test.js +43 -0
- package/src/semantic-release/utils/ghpages-publish.js +16 -0
- package/src/semantic-release/utils/log-section.js +5 -0
- package/src/workflow/index.js +37 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import inquirer from 'inquirer'
|
|
2
|
+
import { git } from '../../common'
|
|
3
|
+
|
|
4
|
+
function toRemote (branch, origin) {
|
|
5
|
+
branch = branch.replace(`${origin}/`)
|
|
6
|
+
return `${origin}/${branch}`
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function branches ({ fromBranch, origin, PRODUCTION_BRANCH, DEVELOP_BRANCH, message = 'Start your branch from:' }) {
|
|
10
|
+
const currentBranch = git.getBranchName()
|
|
11
|
+
const originDevelop = `${origin}/${DEVELOP_BRANCH}`
|
|
12
|
+
const originProduction = `${origin}/${PRODUCTION_BRANCH}`
|
|
13
|
+
|
|
14
|
+
let startFromBranches = [
|
|
15
|
+
originProduction
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
if (startFromBranches.indexOf(toRemote(currentBranch, origin)) === -1 && git.branchExists(currentBranch, origin)) {
|
|
19
|
+
startFromBranches = startFromBranches.concat(toRemote(currentBranch, origin))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const remoteBranches = git.branchesInfos('-r')
|
|
23
|
+
.map(info => info.branch)
|
|
24
|
+
.filter(name => !startFromBranches.includes(name) && ![originDevelop, originProduction].includes(name))
|
|
25
|
+
|
|
26
|
+
if (remoteBranches.length) {
|
|
27
|
+
startFromBranches = startFromBranches.concat(new inquirer.Separator(), remoteBranches)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
type: 'list',
|
|
32
|
+
name: 'fromBranch',
|
|
33
|
+
message,
|
|
34
|
+
default: startFromBranches.indexOf(fromBranch || originProduction),
|
|
35
|
+
choices: startFromBranches,
|
|
36
|
+
when: !fromBranch || currentBranch !== DEVELOP_BRANCH
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import figures from 'figures'
|
|
3
|
+
import { ghPagesPublish } from '../semantic-release/utils/ghpages-publish'
|
|
4
|
+
|
|
5
|
+
export class PublishPages {
|
|
6
|
+
mapContext (commander, context) {
|
|
7
|
+
return {
|
|
8
|
+
...context
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
prompt (context) {
|
|
13
|
+
return []
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTasks (context) {
|
|
17
|
+
return [
|
|
18
|
+
{
|
|
19
|
+
title: 'Publish github pages',
|
|
20
|
+
task: () => ghPagesPublish(context)
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
success (context) {
|
|
26
|
+
// eslint-disable-next-line no-console
|
|
27
|
+
console.log(chalk.green(figures.tick), 'Github pages deployed')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import figures from 'figures'
|
|
3
|
+
import { Rebase } from './rebase'
|
|
4
|
+
import { pushBranch } from './tasks/push-branch'
|
|
5
|
+
|
|
6
|
+
export class Push extends Rebase {
|
|
7
|
+
mapContext (commander, context) {
|
|
8
|
+
return {
|
|
9
|
+
...super.mapContext(commander, context),
|
|
10
|
+
force: !!commander.force,
|
|
11
|
+
checkStatus: true
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getTasks (context) {
|
|
16
|
+
return [
|
|
17
|
+
...super.getTasks(context),
|
|
18
|
+
pushBranch(context)
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
success (context) {
|
|
23
|
+
// eslint-disable-next-line no-console
|
|
24
|
+
console.log(chalk.green(figures.tick), 'Branch', chalk.green(context.featureBranch), 'rebased and pushed.')
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import figures from 'figures'
|
|
3
|
+
import { Fetch } from './fetch'
|
|
4
|
+
import { git } from '../common/cli/git'
|
|
5
|
+
import { updateBranch } from './tasks/update-branch'
|
|
6
|
+
import { updateDependencies } from './tasks/update-dependencies'
|
|
7
|
+
import { runTest } from './tasks/run-test'
|
|
8
|
+
|
|
9
|
+
export class Rebase extends Fetch {
|
|
10
|
+
mapContext (commander, context) {
|
|
11
|
+
return {
|
|
12
|
+
...context,
|
|
13
|
+
useYarn: context.HAS_YARN,
|
|
14
|
+
origin: context.ORIGIN,
|
|
15
|
+
featureBranch: git.getBranchName(),
|
|
16
|
+
fromBranch: context.PRODUCTION_BRANCH,
|
|
17
|
+
checkStatus: commander.force === undefined ? true : !!commander.force,
|
|
18
|
+
rebase: true,
|
|
19
|
+
skipTest: !commander.cucumber && !commander.unitTest,
|
|
20
|
+
skipUnit: !commander.unitTest,
|
|
21
|
+
skipE2E: context.HAS_E2E ? !commander.cucumber : true
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getTasks (context) {
|
|
26
|
+
return [
|
|
27
|
+
...super.getTasks(context),
|
|
28
|
+
updateBranch(context),
|
|
29
|
+
updateDependencies(context),
|
|
30
|
+
...runTest(context)
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
success (context) {
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.log(chalk.green(figures.tick), `Branch ${chalk.green(context.featureBranch)} rebased from ${chalk.green(context.fromBranch)} HEAD`)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const getConfig = require('semantic-release/lib/get-config')
|
|
2
|
+
const getNextVersion = require('semantic-release/lib/get-next-version')
|
|
3
|
+
const { calculateSnapshotVersion } = require('../semantic-release/utils/calculate-snapshot-version')
|
|
4
|
+
|
|
5
|
+
require.cache[require.resolve('semantic-release/lib/get-config')].exports = async (context, cliOptions) => {
|
|
6
|
+
context.config = require('../common/get-config').getConfig()
|
|
7
|
+
|
|
8
|
+
return getConfig(context, cliOptions)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
require.cache[require.resolve('semantic-release/lib/get-next-version')].exports = (context) => {
|
|
12
|
+
if (context.branch.type === 'prerelease') {
|
|
13
|
+
return calculateSnapshotVersion(context)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return getNextVersion(context)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
delete process.env.CIRCLE_PR_NUMBER
|
|
20
|
+
delete process.env.CIRCLE_PULL_REQUEST
|
|
21
|
+
delete process.env.CI_PULL_REQUEST
|
|
22
|
+
|
|
23
|
+
export function release (options = {}) {
|
|
24
|
+
require('semantic-release')({
|
|
25
|
+
dryRun: process.argv.includes('--dry-run'),
|
|
26
|
+
ci: false,
|
|
27
|
+
noCi: true,
|
|
28
|
+
...options
|
|
29
|
+
})
|
|
30
|
+
.then((exitCode) => {
|
|
31
|
+
process.exitCode = exitCode
|
|
32
|
+
})
|
|
33
|
+
.catch(() => {
|
|
34
|
+
process.exitCode = 1
|
|
35
|
+
})
|
|
36
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import figures from 'figures'
|
|
3
|
+
import { Fetch } from './fetch'
|
|
4
|
+
import { rebaseAllBranches } from './tasks/rebase-all-branches'
|
|
5
|
+
|
|
6
|
+
export class Republish extends Fetch {
|
|
7
|
+
mapContext (commander, context) {
|
|
8
|
+
return {
|
|
9
|
+
...super.mapContext(commander, context)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getTasks (context) {
|
|
14
|
+
return [
|
|
15
|
+
...super.getTasks(context),
|
|
16
|
+
rebaseAllBranches(context)
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
success (context) {
|
|
21
|
+
// eslint-disable-next-line no-console
|
|
22
|
+
console.log(chalk.green(figures.tick), 'All branches rebased and pushed.')
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import figures from 'figures'
|
|
3
|
+
import { git } from '../common/cli/git'
|
|
4
|
+
import { branches } from './prompts/branches'
|
|
5
|
+
import { Fetch } from './fetch'
|
|
6
|
+
|
|
7
|
+
import { updateDependencies } from './tasks/update-dependencies'
|
|
8
|
+
import { WORKFLOW_CONFIGURATION } from '../workflow'
|
|
9
|
+
|
|
10
|
+
function sanitize (name) {
|
|
11
|
+
return name.replace(/[/\\_|. ]/gi, '-').split('-').filter(Boolean).join('-')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Start extends Fetch {
|
|
15
|
+
mapContext (options, context) {
|
|
16
|
+
options.branchName = options.branchName || ''
|
|
17
|
+
const type = WORKFLOW_CONFIGURATION
|
|
18
|
+
.map(({ type }) => type)
|
|
19
|
+
.find((t) => options.branchName.startsWith(`${t}-`))
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
...context,
|
|
23
|
+
useYarn: context.HAS_YARN,
|
|
24
|
+
origin: context.ORIGIN,
|
|
25
|
+
branchName: options.branchName,
|
|
26
|
+
type
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
prompt (context) {
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
type: 'list',
|
|
34
|
+
name: 'type',
|
|
35
|
+
message: 'Choose the type of your branch:',
|
|
36
|
+
choices: ['fix', 'feat', 'chore', 'docs', 'tech'],
|
|
37
|
+
default: context.type,
|
|
38
|
+
when: !context.type
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: 'input',
|
|
42
|
+
name: 'branchName',
|
|
43
|
+
message: 'What is the branch name ?',
|
|
44
|
+
validate (branch) {
|
|
45
|
+
if (!branch.length) {
|
|
46
|
+
return 'Branch name is required'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (git.branchExists(branch, context.origin)) {
|
|
50
|
+
return `${branch} already exists`
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return true
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
when: !context.branchName
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
branches(context)
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getTasks (context) {
|
|
64
|
+
context.branchName = sanitize(context.branchName)
|
|
65
|
+
context.featureBranch = context.branchName.includes(context.type + '-') ? context.branchName : `${context.type}-${context.branchName}`
|
|
66
|
+
context.fromBranch = context.fromBranch || context.PRODUCTION_BRANCH
|
|
67
|
+
|
|
68
|
+
return [
|
|
69
|
+
...super.getTasks(context),
|
|
70
|
+
{
|
|
71
|
+
title: `Create branch from ${chalk.green(context.fromBranch)}`,
|
|
72
|
+
task: () => git.checkout('--no-track', '-b', context.featureBranch, context.fromBranch).toObservable()
|
|
73
|
+
},
|
|
74
|
+
updateDependencies(context)
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
success (context) {
|
|
79
|
+
// eslint-disable-next-line no-console
|
|
80
|
+
console.log(chalk.green(figures.tick), `New branch ${chalk.green(context.featureBranch)} created from ${chalk.green(context.fromBranch)} HEAD`)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { git } from '../../common/cli/git'
|
|
2
|
+
|
|
3
|
+
export function pushBranch ({ origin = 'origin', featureBranch, upstream = true, noVerify = true }) {
|
|
4
|
+
return ({
|
|
5
|
+
title: `Push ${featureBranch}`,
|
|
6
|
+
task: () => {
|
|
7
|
+
return git.push(...[
|
|
8
|
+
upstream ? '-u' : '',
|
|
9
|
+
'-f',
|
|
10
|
+
origin,
|
|
11
|
+
featureBranch,
|
|
12
|
+
noVerify ? '--no-verify' : ''
|
|
13
|
+
].filter(Boolean)).toObservable()
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { git } from '../../common/cli/git'
|
|
2
|
+
|
|
3
|
+
export function rebaseAllBranches (context) {
|
|
4
|
+
const { origin = 'origin', upstream = true, noVerify = true } = context
|
|
5
|
+
return ({
|
|
6
|
+
title: 'Rebase all branches',
|
|
7
|
+
task: async () => {
|
|
8
|
+
const remoteBranches = git.branches('-r')
|
|
9
|
+
.filter(b => !new RegExp(`${context.PRODUCTION_BRANCH}|${context.DEVELOP_BRANCH}`).test(b))
|
|
10
|
+
for (const remoteBranch of remoteBranches) {
|
|
11
|
+
const branch = remoteBranch.split('/')[1]
|
|
12
|
+
try {
|
|
13
|
+
await git.branch('-D', branch)
|
|
14
|
+
} catch (e) {}
|
|
15
|
+
try {
|
|
16
|
+
await git.checkout('--track', remoteBranch)
|
|
17
|
+
await git.rebase(`${origin}/${context.PRODUCTION_BRANCH}`)
|
|
18
|
+
await git.push(...[
|
|
19
|
+
upstream ? '-u' : '',
|
|
20
|
+
'-f',
|
|
21
|
+
origin,
|
|
22
|
+
branch,
|
|
23
|
+
noVerify ? '--no-verify' : ''
|
|
24
|
+
].filter(Boolean))
|
|
25
|
+
} catch (e) {
|
|
26
|
+
try {
|
|
27
|
+
await git.rebase('--abort')
|
|
28
|
+
await git.reset('--hard')
|
|
29
|
+
} catch (e) {}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { EMPTY } from 'rxjs'
|
|
2
|
+
import { catchError } from 'rxjs/operators'
|
|
3
|
+
import Listr from 'listr'
|
|
4
|
+
import { git } from '../../common'
|
|
5
|
+
|
|
6
|
+
function pipe (observable, output) {
|
|
7
|
+
observable.pipe(catchError((err) => {
|
|
8
|
+
output.push(err)
|
|
9
|
+
return EMPTY
|
|
10
|
+
}))
|
|
11
|
+
|
|
12
|
+
observable.subscribe(result => {
|
|
13
|
+
output.push(result)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
return observable
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function refreshRepository (context) {
|
|
20
|
+
const {
|
|
21
|
+
output = []
|
|
22
|
+
} = context
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
title: 'Refresh local repository',
|
|
26
|
+
task: () => new Listr([
|
|
27
|
+
{
|
|
28
|
+
title: 'Git fetch',
|
|
29
|
+
task: () => pipe(git.fetch('--prune').toObservable(), output)
|
|
30
|
+
}
|
|
31
|
+
])
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { git, npm, yarn } from '../../common'
|
|
2
|
+
|
|
3
|
+
export const runTest = ({ useYarn, skipTest, skipUnit, skipE2E }) => {
|
|
4
|
+
const manager = useYarn ? yarn : npm
|
|
5
|
+
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
title: 'Unit test',
|
|
9
|
+
skip: () => skipTest || skipUnit,
|
|
10
|
+
task: () => manager.run('test')
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
title: 'E2E test',
|
|
14
|
+
skip: () => skipTest || skipE2E,
|
|
15
|
+
task: () => manager.run('test_e2e')
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
title: 'Reset changes',
|
|
19
|
+
skip: () => skipTest,
|
|
20
|
+
task: () => git.reset('--hard') // reset files updated unit test
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import Listr from 'listr'
|
|
3
|
+
import { git } from '../../common/cli/git'
|
|
4
|
+
|
|
5
|
+
async function checkBranchRemoteStatus ({ featureBranch, origin, force }) {
|
|
6
|
+
const isBranchExists = git.branchExists(featureBranch, origin)
|
|
7
|
+
|
|
8
|
+
if (isBranchExists && !force) {
|
|
9
|
+
const result = git.checkBranchRemoteStatus(featureBranch)
|
|
10
|
+
|
|
11
|
+
if (result) {
|
|
12
|
+
throw new Error('Remote branch changed, check diff before continue')
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const updateBranch = ({ origin, featureBranch, fromBranch, force, checkStatus = true, rebase = true }) => {
|
|
18
|
+
return ({
|
|
19
|
+
title: 'Rebase branch',
|
|
20
|
+
task: () => new Listr(
|
|
21
|
+
[
|
|
22
|
+
{
|
|
23
|
+
title: 'Check status',
|
|
24
|
+
enabled: () => checkStatus,
|
|
25
|
+
task: () => checkBranchRemoteStatus({
|
|
26
|
+
force,
|
|
27
|
+
featureBranch,
|
|
28
|
+
origin
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
title: `Rebase from ${origin}/${chalk.green(fromBranch)}`,
|
|
33
|
+
enabled: () => rebase,
|
|
34
|
+
task: () => git.rebase(`${origin}/${fromBranch}`).toObservable()
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
{ concurrent: false }
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { npm, yarn } from '../../common'
|
|
2
|
+
import { refreshMetadata, shouldReinstall } from '../utils/check-install'
|
|
3
|
+
import Listr from 'listr'
|
|
4
|
+
import { catchError } from 'rxjs/operators'
|
|
5
|
+
|
|
6
|
+
export const updateDependencies = ({ useYarn }) => {
|
|
7
|
+
const manager = useYarn ? yarn : npm
|
|
8
|
+
const reinstall = shouldReinstall()
|
|
9
|
+
|
|
10
|
+
return ({
|
|
11
|
+
title: 'Install',
|
|
12
|
+
enabled: () => reinstall,
|
|
13
|
+
task: () => new Listr(
|
|
14
|
+
[
|
|
15
|
+
{
|
|
16
|
+
title: `Restore dependencies using ${useYarn ? 'Yarn' : 'Npm'}`,
|
|
17
|
+
task: () => manager.restore()
|
|
18
|
+
.toObservable()
|
|
19
|
+
.pipe(catchError(error => {
|
|
20
|
+
if (useYarn) {
|
|
21
|
+
if (error.stderr.startsWith('error Your lockfile needs to be updated')) {
|
|
22
|
+
throw new Error('yarn.lock file is outdated. Run yarn, commit the updated lockfile and try again.')
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
throw error
|
|
27
|
+
}))
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: 'Refresh metadata',
|
|
31
|
+
task: () => refreshMetadata()
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
{ concurrency: false }
|
|
35
|
+
)
|
|
36
|
+
})
|
|
37
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import isEqual from 'lodash/isEqual'
|
|
2
|
+
import { getPackageJson } from '../../common/get-package-json'
|
|
3
|
+
import { git } from '../../common'
|
|
4
|
+
|
|
5
|
+
function getDeps () {
|
|
6
|
+
const pkg = getPackageJson()
|
|
7
|
+
return {
|
|
8
|
+
dependencies: pkg.dependencies,
|
|
9
|
+
devDependencies: pkg.devDependencies
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getHash () {
|
|
14
|
+
return Buffer.from(JSON.stringify(getDeps())).toString('base64')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getDepsFromHash () {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(Buffer.from(git.config('--local', 'npm.hash'), 'base64').toString('utf8'))
|
|
20
|
+
} catch (er) {
|
|
21
|
+
return ''
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function shouldReinstall () {
|
|
26
|
+
return !isEqual(getDeps(), getDepsFromHash())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function refreshMetadata () {
|
|
30
|
+
git.config('--local', 'npm.hash', `${getHash()}`)
|
|
31
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import 'any-observable/register/rxjs-all' // eslint-disable-line import/no-unassigned-import
|
|
2
|
+
import execa from 'execa'
|
|
3
|
+
import streamToObservable from '@samverschueren/stream-to-observable'
|
|
4
|
+
import { filter, merge } from 'rxjs/operators'
|
|
5
|
+
import split from 'split'
|
|
6
|
+
import { spawnSync } from 'child_process'
|
|
7
|
+
|
|
8
|
+
export class Cli {
|
|
9
|
+
constructor (cmd) {
|
|
10
|
+
this.cmd = cmd
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
sync (...args) {
|
|
14
|
+
return Cli.run(this.cmd, args).sync()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
run (...args) {
|
|
18
|
+
return Cli.run(this.cmd, args)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get (...args) {
|
|
22
|
+
return Cli.run(this.cmd, args).get()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static run (cmd, args = [], options = {}) {
|
|
26
|
+
const run = (opt = {}) => {
|
|
27
|
+
return execa(cmd, args, {
|
|
28
|
+
cwd: process.cwd(),
|
|
29
|
+
...opt,
|
|
30
|
+
...options
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let isPromise = true
|
|
35
|
+
|
|
36
|
+
const promise = new Promise((resolve, reject) => {
|
|
37
|
+
setTimeout(async () => {
|
|
38
|
+
if (isPromise) {
|
|
39
|
+
try {
|
|
40
|
+
const result = await run({
|
|
41
|
+
stdio: 'inherit'
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
resolve(result)
|
|
45
|
+
} catch (err) {
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
47
|
+
reject(err)
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
resolve()
|
|
51
|
+
}
|
|
52
|
+
}, 10)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
promise.toObservable = (opt) => {
|
|
56
|
+
isPromise = false
|
|
57
|
+
const cp = run(opt)
|
|
58
|
+
const stdout = streamToObservable(cp.stdout.pipe(split()), { await: cp })
|
|
59
|
+
const stderr = streamToObservable(cp.stderr.pipe(split()), { await: cp })
|
|
60
|
+
|
|
61
|
+
return stdout.pipe(merge(stderr)).pipe(filter(Boolean))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
promise.toStream = (opt) => {
|
|
65
|
+
isPromise = false
|
|
66
|
+
|
|
67
|
+
return run(opt)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
promise.cwd = (cwd) => {
|
|
71
|
+
options.cwd = cwd
|
|
72
|
+
return promise
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
promise.sync = (opt) => {
|
|
76
|
+
isPromise = false
|
|
77
|
+
|
|
78
|
+
return execa.sync(cmd, args, {
|
|
79
|
+
cwd: process.cwd(),
|
|
80
|
+
stdio: 'inherit',
|
|
81
|
+
...options,
|
|
82
|
+
...opt
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
promise.getRaw = (opt) => {
|
|
87
|
+
isPromise = false
|
|
88
|
+
return Cli.getRaw(cmd, args, {
|
|
89
|
+
cwd: process.cwd(),
|
|
90
|
+
...options,
|
|
91
|
+
...opt
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
promise.get = promise.getRaw
|
|
96
|
+
|
|
97
|
+
return promise
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static getRaw (cmd, args, options) {
|
|
101
|
+
return spawnSync(cmd, args, options)
|
|
102
|
+
.output.filter(o => !!o)
|
|
103
|
+
.map(o => o.toString())
|
|
104
|
+
.join('\n')
|
|
105
|
+
.trim()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import { Cli } from './cli'
|
|
3
|
+
|
|
4
|
+
class DockerCli extends Cli {
|
|
5
|
+
constructor () {
|
|
6
|
+
super('docker')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
tag (...args) {
|
|
10
|
+
return this.get('tag', ...args)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
login (...args) {
|
|
14
|
+
return this.sync('login', ...args)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
push (...args) {
|
|
18
|
+
return this.run('push', ...args)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async getToken (username, password) {
|
|
22
|
+
const { data: { token } } = await axios({
|
|
23
|
+
method: 'POST',
|
|
24
|
+
url: 'https://hub.docker.com/v2/users/login/',
|
|
25
|
+
headers: {
|
|
26
|
+
Accept: 'application/json',
|
|
27
|
+
'Content-Type': 'application/json'
|
|
28
|
+
},
|
|
29
|
+
data: {
|
|
30
|
+
username,
|
|
31
|
+
password
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return token
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async getTags ({ token, repository }) {
|
|
39
|
+
const { data } = await axios({
|
|
40
|
+
method: 'GET',
|
|
41
|
+
url: `https://hub.docker.com/v2/repositories/${repository}/tags/?page=1&page_size=500`,
|
|
42
|
+
headers: {
|
|
43
|
+
Accept: 'application/json',
|
|
44
|
+
Authorization: `JWT ${token}`
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return data.results
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async deleteTag (tag, { token, repository }) {
|
|
52
|
+
await axios({
|
|
53
|
+
method: 'DELETE',
|
|
54
|
+
url: `https://hub.docker.com/v2/repositories/${repository}/tags/${tag}/`,
|
|
55
|
+
headers: {
|
|
56
|
+
Accept: 'application/json',
|
|
57
|
+
Authorization: `JWT ${token}`
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const docker = new DockerCli()
|