@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.
Files changed (85) hide show
  1. package/README.md +106 -0
  2. package/bin/checkfeatures.sh +5 -0
  3. package/bin/cm-changelog.js +17 -0
  4. package/bin/cm-clean.js +10 -0
  5. package/bin/cm-config.js +14 -0
  6. package/bin/cm-deploy.js +11 -0
  7. package/bin/cm-fetch.js +11 -0
  8. package/bin/cm-finish.js +13 -0
  9. package/bin/cm-publish-pages.js +11 -0
  10. package/bin/cm-publish.js +14 -0
  11. package/bin/cm-push.js +14 -0
  12. package/bin/cm-rebase.js +14 -0
  13. package/bin/cm-republish.js +11 -0
  14. package/bin/cm-start.js +20 -0
  15. package/bin/cm.js +20 -0
  16. package/bin/cmexpedit.sh +9 -0
  17. package/bin/cmpull.sh +7 -0
  18. package/bin/cmrelease.js +3 -0
  19. package/package.json +88 -0
  20. package/release.config.js +19 -0
  21. package/semantic.js +1 -0
  22. package/src/commands/changelog.js +47 -0
  23. package/src/commands/clean.js +30 -0
  24. package/src/commands/config.js +23 -0
  25. package/src/commands/deploy.js +39 -0
  26. package/src/commands/fetch.js +21 -0
  27. package/src/commands/finish.js +44 -0
  28. package/src/commands/index.js +10 -0
  29. package/src/commands/prompts/branches.js +38 -0
  30. package/src/commands/publish-pages.js +29 -0
  31. package/src/commands/push.js +26 -0
  32. package/src/commands/rebase.js +38 -0
  33. package/src/commands/release.js +36 -0
  34. package/src/commands/republish.js +24 -0
  35. package/src/commands/start.js +82 -0
  36. package/src/commands/tasks/push-branch.js +16 -0
  37. package/src/commands/tasks/rebase-all-branches.js +34 -0
  38. package/src/commands/tasks/refresh-repository.js +33 -0
  39. package/src/commands/tasks/run-test.js +23 -0
  40. package/src/commands/tasks/update-branch.js +40 -0
  41. package/src/commands/tasks/update-dependencies.js +37 -0
  42. package/src/commands/utils/check-install.js +31 -0
  43. package/src/common/cli/cli.js +107 -0
  44. package/src/common/cli/docker.js +63 -0
  45. package/src/common/cli/docker.test.js +128 -0
  46. package/src/common/cli/git.js +130 -0
  47. package/src/common/cli/git.test.js +205 -0
  48. package/src/common/cli/heroku.js +21 -0
  49. package/src/common/cli/heroku.test.js +56 -0
  50. package/src/common/cli/lerna.js +25 -0
  51. package/src/common/cli/lerna.test.js +48 -0
  52. package/src/common/cli/npm.js +33 -0
  53. package/src/common/cli/npm.test.js +47 -0
  54. package/src/common/cli/yarn.js +33 -0
  55. package/src/common/cli/yarn.test.js +48 -0
  56. package/src/common/configure-git-workspace.js +27 -0
  57. package/src/common/get-config.js +135 -0
  58. package/src/common/get-package-json.js +7 -0
  59. package/src/common/get-release-config.js +7 -0
  60. package/src/common/index.js +10 -0
  61. package/src/common/run-command.js +61 -0
  62. package/src/common/run-command.test.js +63 -0
  63. package/src/index.js +1 -0
  64. package/src/main.js +10 -0
  65. package/src/semantic-release/actions/analyze-commits.js +9 -0
  66. package/src/semantic-release/actions/fail.js +16 -0
  67. package/src/semantic-release/actions/generate-notes.js +11 -0
  68. package/src/semantic-release/actions/index.js +8 -0
  69. package/src/semantic-release/actions/prepare.js +101 -0
  70. package/src/semantic-release/actions/publish.js +17 -0
  71. package/src/semantic-release/actions/success.js +30 -0
  72. package/src/semantic-release/actions/verify-conditions.js +30 -0
  73. package/src/semantic-release/actions/verify-release.js +7 -0
  74. package/src/semantic-release/get-semantic-config.js +115 -0
  75. package/src/semantic-release/utils/calculate-snapshot-version.js +9 -0
  76. package/src/semantic-release/utils/calculate-snapshot-version.test.js +57 -0
  77. package/src/semantic-release/utils/display-package-info.js +11 -0
  78. package/src/semantic-release/utils/display-release-info.js +12 -0
  79. package/src/semantic-release/utils/docker-clean-tags.js +45 -0
  80. package/src/semantic-release/utils/docker-clean-tags.test.js +54 -0
  81. package/src/semantic-release/utils/docker-publish.js +36 -0
  82. package/src/semantic-release/utils/docker-publish.test.js +43 -0
  83. package/src/semantic-release/utils/ghpages-publish.js +16 -0
  84. package/src/semantic-release/utils/log-section.js +5 -0
  85. 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()