diff --git a/.pnp.cjs b/.pnp.cjs index 93a8e6f3ef..7f355456bd 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -3819,7 +3819,7 @@ const RAW_RUNTIME_STATE = ["clean-stack", "npm:3.0.1"],\ ["cli-progress", "npm:3.12.0"],\ ["debug", "virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4"],\ - ["ejs", "npm:3.1.8"],\ + ["ejs", "npm:3.1.10"],\ ["get-package-type", "npm:0.1.0"],\ ["globby", "npm:11.1.0"],\ ["hyperlinker", "npm:1.0.0"],\ @@ -3853,7 +3853,7 @@ const RAW_RUNTIME_STATE = ["clean-stack", "npm:3.0.1"],\ ["cli-progress", "npm:3.12.0"],\ ["debug", "virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4"],\ - ["ejs", "npm:3.1.8"],\ + ["ejs", "npm:3.1.10"],\ ["get-package-type", "npm:0.1.0"],\ ["globby", "npm:11.1.0"],\ ["hyperlinker", "npm:1.0.0"],\ @@ -3874,6 +3874,41 @@ const RAW_RUNTIME_STATE = ["wrap-ansi", "npm:7.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:3.26.5", {\ + "packageLocation": "./.yarn/cache/@oclif-core-npm-3.26.5-02719845fd-4e2aa1a945.zip/node_modules/@oclif/core/",\ + "packageDependencies": [\ + ["@oclif/core", "npm:3.26.5"],\ + ["@types/cli-progress", "npm:3.11.5"],\ + ["ansi-escapes", "npm:4.3.2"],\ + ["ansi-styles", "npm:4.3.0"],\ + ["cardinal", "npm:2.1.1"],\ + ["chalk", "npm:4.1.2"],\ + ["clean-stack", "npm:3.0.1"],\ + ["cli-progress", "npm:3.12.0"],\ + ["color", "npm:4.2.3"],\ + ["debug", "virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4"],\ + ["ejs", "npm:3.1.10"],\ + ["get-package-type", "npm:0.1.0"],\ + ["globby", "npm:11.1.0"],\ + ["hyperlinker", "npm:1.0.0"],\ + ["indent-string", "npm:4.0.0"],\ + ["is-wsl", "npm:2.2.0"],\ + ["js-yaml", "npm:3.14.1"],\ + ["minimatch", "npm:9.0.4"],\ + ["natural-orderby", "npm:2.0.3"],\ + ["object-treeify", "npm:1.1.33"],\ + ["password-prompt", "npm:1.1.3"],\ + ["slice-ansi", "npm:4.0.0"],\ + ["string-width", "npm:4.2.3"],\ + ["strip-ansi", "npm:6.0.1"],\ + ["supports-color", "npm:8.1.1"],\ + ["supports-hyperlinks", "npm:2.3.0"],\ + ["widest-line", "npm:3.1.0"],\ + ["wordwrap", "npm:1.0.0"],\ + ["wrap-ansi", "npm:7.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@oclif/plugin-help", [\ @@ -7635,6 +7670,15 @@ const RAW_RUNTIME_STATE = ["color-string", "npm:1.6.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.2.3", {\ + "packageLocation": "./.yarn/cache/color-npm-4.2.3-4a23227581-b23f5e500a.zip/node_modules/color/",\ + "packageDependencies": [\ + ["color", "npm:4.2.3"],\ + ["color-convert", "npm:2.0.1"],\ + ["color-string", "npm:1.9.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["color-convert", [\ @@ -7680,6 +7724,15 @@ const RAW_RUNTIME_STATE = ["simple-swizzle", "npm:0.2.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.9.1", {\ + "packageLocation": "./.yarn/cache/color-string-npm-1.9.1-dc020e56be-72aa0b81ee.zip/node_modules/color-string/",\ + "packageDependencies": [\ + ["color-string", "npm:1.9.1"],\ + ["color-name", "npm:1.1.4"],\ + ["simple-swizzle", "npm:0.2.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["color-support", [\ @@ -8410,7 +8463,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/masternode-reward-shares-contract", "workspace:packages/masternode-reward-shares-contract"],\ ["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\ ["@dashevo/withdrawals-contract", "workspace:packages/withdrawals-contract"],\ - ["@oclif/core", "npm:3.10.8"],\ + ["@oclif/core", "npm:3.26.5"],\ ["@oclif/plugin-help", "npm:6.0.5"],\ ["ajv", "npm:8.12.0"],\ ["ajv-formats", "virtual:e822c5b02ef2b3c5fb9c8d88d5e0ca208365bff76f80510f4ccf9b1de44e2078264bcb00d3cdd5e193c256e9ab81e27c34fcfb1ad3a0e8c1dc8fa0066c78c468#npm:2.1.1"],\ @@ -9075,10 +9128,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["ejs", [\ - ["npm:3.1.8", {\ - "packageLocation": "./.yarn/cache/ejs-npm-3.1.8-30583753fc-879f84c8ee.zip/node_modules/ejs/",\ + ["npm:3.1.10", {\ + "packageLocation": "./.yarn/cache/ejs-npm-3.1.10-4e8cf4bdc1-a9cb7d7cd1.zip/node_modules/ejs/",\ "packageDependencies": [\ - ["ejs", "npm:3.1.8"],\ + ["ejs", "npm:3.1.10"],\ ["jake", "npm:10.8.5"]\ ],\ "linkType": "HARD"\ @@ -13517,7 +13570,7 @@ const RAW_RUNTIME_STATE = ["binaryextensions", "npm:4.18.0"],\ ["commondir", "npm:1.0.1"],\ ["deep-extend", "npm:0.6.0"],\ - ["ejs", "npm:3.1.8"],\ + ["ejs", "npm:3.1.10"],\ ["globby", "npm:11.1.0"],\ ["isbinaryfile", "npm:5.0.0"],\ ["mem-fs", "npm:2.2.1"],\ @@ -13540,7 +13593,7 @@ const RAW_RUNTIME_STATE = ["binaryextensions", "npm:4.18.0"],\ ["commondir", "npm:1.0.1"],\ ["deep-extend", "npm:0.6.0"],\ - ["ejs", "npm:3.1.8"],\ + ["ejs", "npm:3.1.10"],\ ["globby", "npm:11.1.0"],\ ["isbinaryfile", "npm:5.0.0"],\ ["mem-fs", null],\ @@ -13813,6 +13866,14 @@ const RAW_RUNTIME_STATE = ["brace-expansion", "npm:2.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:9.0.4", {\ + "packageLocation": "./.yarn/cache/minimatch-npm-9.0.4-7be5a33efc-4cdc18d112.zip/node_modules/minimatch/",\ + "packageDependencies": [\ + ["minimatch", "npm:9.0.4"],\ + ["brace-expansion", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["minimist", [\ @@ -15366,6 +15427,15 @@ const RAW_RUNTIME_STATE = ["cross-spawn", "npm:6.0.5"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.1.3", {\ + "packageLocation": "./.yarn/cache/password-prompt-npm-1.1.3-0190666768-1cf7001e66.zip/node_modules/password-prompt/",\ + "packageDependencies": [\ + ["password-prompt", "npm:1.1.3"],\ + ["ansi-escapes", "npm:4.3.2"],\ + ["cross-spawn", "npm:7.0.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["path-browserify", [\ diff --git a/.yarn/cache/ejs-npm-3.1.8-30583753fc-879f84c8ee.zip b/.yarn/cache/ejs-npm-3.1.8-30583753fc-879f84c8ee.zip deleted file mode 100644 index 368ffb9272..0000000000 Binary files a/.yarn/cache/ejs-npm-3.1.8-30583753fc-879f84c8ee.zip and /dev/null differ diff --git a/package.json b/package.json index b31de1b640..0a15524e42 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,6 @@ "resolutions": { "elliptic": "^6.5.4", "bn.js": "4.12.0", - "ejs": "^3.1.7", "fast-json-patch": "^3.1.1", "node-tar": "^6.2.1", "oclif@3.4.2": "patch:oclif@npm:3.4.2#.yarn/patches/oclif-npm-3.4.2-a655d32eed.patch", diff --git a/packages/dashmate/src/commands/update.js b/packages/dashmate/src/commands/update.js index 8ba5b774d2..dce6b2c679 100644 --- a/packages/dashmate/src/commands/update.js +++ b/packages/dashmate/src/commands/update.js @@ -35,6 +35,12 @@ export default class UpdateCommand extends ConfigBaseCommand { ) { const updateInfo = await updateNode(config); + const colors = { + updated: chalk.yellow, + 'up to date': chalk.green, + error: chalk.red, + }; + // Draw table or show json printArrayOfObjects(updateInfo .reduce( @@ -43,7 +49,7 @@ export default class UpdateCommand extends ConfigBaseCommand { }) => ([ ...acc, format === OUTPUT_FORMATS.PLAIN - ? { Service: title, Image: image, Updated: updated ? chalk.yellow('updated') : chalk.green('up to date') } + ? { Service: title, Image: image, Updated: colors[updated](updated) } : { name, title, updated, image, }, diff --git a/packages/dashmate/src/update/updateNodeFactory.js b/packages/dashmate/src/update/updateNodeFactory.js index 79996a2511..9ce4fb126a 100644 --- a/packages/dashmate/src/update/updateNodeFactory.js +++ b/packages/dashmate/src/update/updateNodeFactory.js @@ -19,10 +19,17 @@ export default function updateNodeFactory(getServiceList, docker) { return Promise.all( lodash.uniqBy(services, 'image') - .map(async ({ name, image, title }) => new Promise((resolve, reject) => { + .map(async ({ name, image, title }) => new Promise((resolve) => { docker.pull(image, (err, stream) => { if (err) { - reject(err); + if (process.env.DEBUG) { + // eslint-disable-next-line no-console + console.error(`Failed to update ${name} service, image ${image}, error: ${err}`); + } + + resolve({ + name, title, image, updated: 'error', + }); } else { let updated = null; @@ -33,15 +40,35 @@ export default function updateNodeFactory(getServiceList, docker) { .trim() .split('\r\n') .map((str) => JSON.parse(str)) - .filter((obj) => obj.status.startsWith('Status: ')); + .filter((obj) => obj?.status?.startsWith('Status: ')); + + if (status) { + if (status.status.includes('Image is up to date for')) { + updated = 'up to date'; + } else if (status.status.includes('Downloaded newer image for')) { + updated = 'updated'; + } + } else { + if (process.env.DEBUG) { + // eslint-disable-next-line no-console + console.error('Failed to read docker json data, status not found'); + } - if (status?.status.includes('Image is up to date for')) { - updated = false; - } else if (status?.status.includes('Downloaded newer image for')) { - updated = true; + resolve({ + name, title, image, updated: 'error', + }); } }); - stream.on('error', reject); + stream.on('error', () => { + if (process.env.DEBUG) { + // eslint-disable-next-line no-console + console.error(`Failed to update ${name} service, image ${image}, error: ${err}`); + } + + resolve({ + name, title, image, updated: 'error', + }); + }); stream.on('end', () => resolve({ name, title, image, updated, })); diff --git a/packages/dashmate/test/unit/commands/update.spec.js b/packages/dashmate/test/unit/commands/update.spec.js index ecf95ad7a3..12536a2293 100644 --- a/packages/dashmate/test/unit/commands/update.spec.js +++ b/packages/dashmate/test/unit/commands/update.spec.js @@ -42,4 +42,44 @@ describe('Update command', () => { expect(mockGetServicesList).to.have.been.calledOnceWithExactly(config); expect(mockDocker.pull).to.have.been.calledOnceWith(mockServicesList[0].image); }); + + it('should update other services if one of them fails', async function it() { + const command = new UpdateCommand(); + mockDockerResponse = { status: 'Status: Image is up to date for' }; + mockServicesList = [{ name: 'fake', image: 'fake', title: 'FAKE' }, + { name: 'fake_docker_pull_error', image: 'fake_err_image', title: 'FAKE_ERROR' }]; + + // test docker.pull returns error + mockDocker = { + pull: this.sinon.stub() + .callsFake((image, cb) => (image === mockServicesList[1].image ? cb(new Error(), null) + : cb(false, mockDockerStream))), + }; + + let updateNode = updateNodeFactory(mockGetServicesList, mockDocker); + + await command.runWithDependencies({}, { format: 'json' }, mockDocker, config, updateNode); + + expect(mockGetServicesList).to.have.been.calledOnceWithExactly(config); + expect(mockDocker.pull.firstCall.firstArg).to.equal(mockServicesList[0].image); + expect(mockDocker.pull.secondCall.firstArg).to.equal(mockServicesList[1].image); + + // test docker.pull stream returns error + mockDocker = { pull: this.sinon.stub().callsFake((image, cb) => cb(false, mockDockerStream)) }; + mockDockerStream = { + on: this.sinon.stub().callsFake((channel, cb) => (channel === 'error' ? cb(new Error()) : null)), + }; + + // reset + mockGetServicesList = this.sinon.stub().callsFake(() => mockServicesList); + mockDocker = { pull: this.sinon.stub().callsFake((image, cb) => cb(false, mockDockerStream)) }; + + updateNode = updateNodeFactory(mockGetServicesList, mockDocker); + + await command.runWithDependencies({}, { format: 'json' }, mockDocker, config, updateNode); + + expect(mockGetServicesList).to.have.been.calledOnceWithExactly(config); + expect(mockDocker.pull.firstCall.firstArg).to.equal(mockServicesList[0].image); + expect(mockDocker.pull.secondCall.firstArg).to.equal(mockServicesList[1].image); + }); }); diff --git a/yarn.lock b/yarn.lock index 0c9f1d5de1..218479264c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2591,7 +2591,7 @@ __metadata: languageName: node linkType: hard -"@oclif/core@npm:^3.0.4, @oclif/core@npm:^3.10.8, @oclif/core@npm:^3.3.1, @oclif/core@npm:^3.9.1": +"@oclif/core@npm:^3.0.4, @oclif/core@npm:^3.3.1, @oclif/core@npm:^3.9.1": version: 3.10.8 resolution: "@oclif/core@npm:3.10.8" dependencies: @@ -2625,6 +2625,42 @@ __metadata: languageName: node linkType: hard +"@oclif/core@npm:^3.10.8": + version: 3.26.5 + resolution: "@oclif/core@npm:3.26.5" + dependencies: + "@types/cli-progress": "npm:^3.11.5" + ansi-escapes: "npm:^4.3.2" + ansi-styles: "npm:^4.3.0" + cardinal: "npm:^2.1.1" + chalk: "npm:^4.1.2" + clean-stack: "npm:^3.0.1" + cli-progress: "npm:^3.12.0" + color: "npm:^4.2.3" + debug: "npm:^4.3.4" + ejs: "npm:^3.1.10" + get-package-type: "npm:^0.1.0" + globby: "npm:^11.1.0" + hyperlinker: "npm:^1.0.0" + indent-string: "npm:^4.0.0" + is-wsl: "npm:^2.2.0" + js-yaml: "npm:^3.14.1" + minimatch: "npm:^9.0.4" + natural-orderby: "npm:^2.0.3" + object-treeify: "npm:^1.1.33" + password-prompt: "npm:^1.1.3" + slice-ansi: "npm:^4.0.0" + string-width: "npm:^4.2.3" + strip-ansi: "npm:^6.0.1" + supports-color: "npm:^8.1.1" + supports-hyperlinks: "npm:^2.2.0" + widest-line: "npm:^3.1.0" + wordwrap: "npm:^1.0.0" + wrap-ansi: "npm:^7.0.0" + checksum: 4e2aa1a9453d15e6bbb1b321b4b0e556ab36b02bd65d80632722e497e25baf661547993bf410a41e4a129518e66771a8608b18c9a16601be2be516eb5397f5e6 + languageName: node + linkType: hard + "@oclif/plugin-help@npm:^5.2.14": version: 5.2.20 resolution: "@oclif/plugin-help@npm:5.2.20" @@ -3152,7 +3188,7 @@ __metadata: languageName: node linkType: hard -"@types/cli-progress@npm:^3.11.0": +"@types/cli-progress@npm:^3.11.0, @types/cli-progress@npm:^3.11.5": version: 3.11.5 resolution: "@types/cli-progress@npm:3.11.5" dependencies: @@ -5597,6 +5633,16 @@ __metadata: languageName: node linkType: hard +"color-string@npm:^1.9.0": + version: 1.9.1 + resolution: "color-string@npm:1.9.1" + dependencies: + color-name: "npm:^1.0.0" + simple-swizzle: "npm:^0.2.2" + checksum: 72aa0b81ee71b3f4fb1ac9cd839cdbd7a011a7d318ef58e6cb13b3708dca75c7e45029697260488709f1b1c7ac4e35489a87e528156c1e365917d1c4ccb9b9cd + languageName: node + linkType: hard + "color-support@npm:^1.1.2": version: 1.1.3 resolution: "color-support@npm:1.1.3" @@ -5616,6 +5662,16 @@ __metadata: languageName: node linkType: hard +"color@npm:^4.2.3": + version: 4.2.3 + resolution: "color@npm:4.2.3" + dependencies: + color-convert: "npm:^2.0.1" + color-string: "npm:^1.9.0" + checksum: b23f5e500a79ea22428db43d1a70642d983405c0dd1f95ef59dbdb9ba66afbb4773b334fa0b75bb10b0552fd7534c6b28d4db0a8b528f91975976e70973c0152 + languageName: node + linkType: hard + "colorette@npm:^2.0.14, colorette@npm:^2.0.19, colorette@npm:^2.0.7": version: 2.0.20 resolution: "colorette@npm:2.0.20" @@ -6775,14 +6831,14 @@ __metadata: languageName: node linkType: hard -"ejs@npm:^3.1.7": - version: 3.1.8 - resolution: "ejs@npm:3.1.8" +"ejs@npm:^3.1.10, ejs@npm:^3.1.8, ejs@npm:^3.1.9": + version: 3.1.10 + resolution: "ejs@npm:3.1.10" dependencies: jake: "npm:^10.8.5" bin: ejs: bin/cli.js - checksum: 879f84c8ee56d06dea7b47a8b493e1b398dba578ec7a701660cf77c8a6d565b932c5896639d1dc4a3be29204eccdb70ee4e1bdf634647c2490227f727d5d6a3d + checksum: a9cb7d7cd13b7b1cd0be5c4788e44dd10d92f7285d2f65b942f33e127230c054f99a42db4d99f766d8dbc6c57e94799593ee66a14efd7c8dd70c4812bf6aa384 languageName: node linkType: hard @@ -10756,6 +10812,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.4": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 4cdc18d112b164084513e890d6323370db14c22249d536ad1854539577a895e690a27513dc346392f61a4a50afbbd8abc88f3f25558bfbbbb862cd56508b20f5 + languageName: node + linkType: hard + "minimist-options@npm:4.1.0": version: 4.1.0 resolution: "minimist-options@npm:4.1.0" @@ -12190,6 +12255,16 @@ __metadata: languageName: node linkType: hard +"password-prompt@npm:^1.1.3": + version: 1.1.3 + resolution: "password-prompt@npm:1.1.3" + dependencies: + ansi-escapes: "npm:^4.3.2" + cross-spawn: "npm:^7.0.3" + checksum: 1cf7001e66868b2ed7a03e036bc2f1dd45eb6dc8fee7e3e2056370057c484be25e7468fee00a1378e1ee8eca77ba79f48bee5ce15dcb464413987ace63c68b35 + languageName: node + linkType: hard + "path-browserify@npm:^1.0.1": version: 1.0.1 resolution: "path-browserify@npm:1.0.1"