From 7db9ce56c26d25ca43631daaf5d32c3140e15f6a Mon Sep 17 00:00:00 2001 From: Erez Rokah Date: Thu, 24 Sep 2020 12:22:57 +0200 Subject: [PATCH] fix(command-deploy): handle deploy error when there are no files to deploy (#1274) --- package-lock.json | 6 +++--- package.json | 2 +- src/commands/deploy.js | 7 ++++++- src/lib/api.js | 13 ++++++++++--- src/utils/edge-handlers.js | 8 ++------ tests/command.deploy.test.js | 15 +++++++++++++++ 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index d715bb18437..b028290dcf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11624,9 +11624,9 @@ "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==" }, "netlify": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/netlify/-/netlify-4.5.1.tgz", - "integrity": "sha512-Ke6lXulj8Jd4qzAmHv5VHvqAWoV+EkQUKiBDvpZuUAGA12UDRP4vl7gvJkxmwZ5Z/trIOgiOC9n8y/NHlvFbXA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/netlify/-/netlify-4.5.2.tgz", + "integrity": "sha512-o6g67js91RBY2ZPGvgKC6jyEYxhLyofBMiiaKh4ALcRUnSXOnZEGZH1FZYZIB85omjO6PUaTdGIB9g+VkWRUaA==", "requires": { "@netlify/open-api": "^0.16.0", "@netlify/zip-it-and-ship-it": "^1.3.12", diff --git a/package.json b/package.json index 657b93d5285..955c6ac304b 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "make-dir": "^3.0.0", "minimist": "^1.2.5", "multiparty": "^4.2.1", - "netlify": "^4.3.10", + "netlify": "^4.5.2", "netlify-redirect-parser": "^2.5.0", "netlify-redirector": "^0.2.0", "node-fetch": "^2.6.0", diff --git a/src/commands/deploy.js b/src/commands/deploy.js index d518fb301a0..0468d316cbf 100644 --- a/src/commands/deploy.js +++ b/src/commands/deploy.js @@ -16,6 +16,7 @@ const { getBuildOptions, runBuild } = require('../lib/build') const LinkCommand = require('./link') const { NETLIFYDEV, NETLIFYDEVLOG, NETLIFYDEVERR } = require('../utils/logo') const { statAsync } = require('../lib/fs') +const { cancelDeploy } = require('../lib/api') const { deployEdgeHandlers } = require('../utils/edge-handlers') const DEFAULT_DEPLOY_TIMEOUT = 1.2e6 @@ -174,6 +175,7 @@ const runDeploy = async ({ exit, }) => { let results + let deployId try { if (deployToProduction) { if (isObject(siteData.published_deploy) && siteData.published_deploy.locked) { @@ -198,7 +200,7 @@ const runDeploy = async ({ const draft = !deployToProduction && !alias const title = flags.message results = await api.createSiteDeploy({ siteId, title, body: { draft, branch: alias } }) - const deployId = results.id + deployId = results.id const silent = flags.json || flags.silent await deployEdgeHandlers({ @@ -220,6 +222,9 @@ const runDeploy = async ({ filter: getDeployFilesFilter({ site, deployFolder }), }) } catch (e) { + if (deployId) { + await cancelDeploy({ api, deployId, warn }) + } switch (true) { case e.name === 'JSONHTTPError': { warn(`JSONHTTPError: ${e.json.message} ${e.status}`) diff --git a/src/lib/api.js b/src/lib/api.js index c799c1650f2..0072c024148 100644 --- a/src/lib/api.js +++ b/src/lib/api.js @@ -1,5 +1,3 @@ -// This file should be used to wrap API methods that are not part of our open API spec yet -// Once they become part of the spec, js-client should be used const fetch = require('node-fetch') const getHeaders = ({ token }) => { @@ -47,6 +45,7 @@ const apiPost = async ({ api, path, data }) => { } const uploadEdgeHandlers = async ({ api, deployId, bundleBuffer, manifest }) => { + // TODO: use open-api spec via api when it is exposed const response = await apiPost({ api, path: `deploys/${deployId}/edge_handlers`, data: manifest }) const { error, exists, upload_url: uploadUrl } = await response.json() if (error) { @@ -75,4 +74,12 @@ const uploadEdgeHandlers = async ({ api, deployId, bundleBuffer, manifest }) => return true } -module.exports = { uploadEdgeHandlers } +const cancelDeploy = async ({ api, deployId, warn }) => { + try { + await api.cancelSiteDeploy({ deploy_id: deployId }) + } catch (e) { + warn(`Failed canceling deploy with id ${deployId}: ${e.message}`) + } +} + +module.exports = { uploadEdgeHandlers, cancelDeploy } diff --git a/src/utils/edge-handlers.js b/src/utils/edge-handlers.js index 5ca753d1902..b3fa4d7d5a7 100644 --- a/src/utils/edge-handlers.js +++ b/src/utils/edge-handlers.js @@ -1,6 +1,6 @@ const path = require('path') const { statAsync, readFileAsyncCatchError } = require('../lib/fs') -const { uploadEdgeHandlers } = require('../lib/api') +const { uploadEdgeHandlers, cancelDeploy } = require('../lib/api') const { startSpinner, stopSpinner } = require('../lib/spinner') const MANIFEST_FILENAME = 'manifest.json' @@ -74,11 +74,7 @@ const deployEdgeHandlers = async ({ site, deployId, api, silent, error, warn }) } catch (e) { const text = `Failed deploying Edge Handlers: ${e.message}` stopSpinner({ spinner, text, error: true }) - try { - await api.cancelSiteDeploy({ deploy_id: deployId }) - } catch (e) { - warn(`Failed canceling deploy with id ${deployId}: ${e.message}`) - } + await cancelDeploy({ api, deployId, warn }) // no need to report the error again error('') } diff --git a/tests/command.deploy.test.js b/tests/command.deploy.test.js index 3f0b95c25c9..986680b1b55 100644 --- a/tests/command.deploy.test.js +++ b/tests/command.deploy.test.js @@ -291,6 +291,21 @@ if (process.env.IS_FORK !== 'true') { }) }) + test('should exit with error when deploying an empty directory', async t => { + await withSiteBuilder('site-with-an-empty-directory', async builder => { + await builder.buildAsync() + + try { + await callCli(['deploy', '--dir', '.'], { + cwd: builder.directory, + env: { NETLIFY_SITE_ID: t.context.siteId }, + }) + } catch (e) { + t.is(e.stderr.includes('Error: No files or functions to deploy'), true) + } + }) + }) + test.after('cleanup', async t => { const { siteId } = t.context console.log(`deleting test site "${siteName}". ${siteId}`)