Skip to content

Commit

Permalink
fix(command-deploy): sync redirects after build (#2920)
Browse files Browse the repository at this point in the history
* fix(command-deploy): sync redirects after build

* fix: pass config instead of newConfig

* test(command-deploy): add config mutator plugin test

* refactor: use netlify config to sync configuration

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
erezrokah and kodiakhq[bot] authored Aug 3, 2021
1 parent e6f20f9 commit 021bbfa
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 10 deletions.
22 changes: 18 additions & 4 deletions src/commands/deploy.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const path = require('path')
const process = require('process')

const { updateConfig, restoreConfig } = require('@netlify/config')
const { flags: flagsLib } = require('@oclif/command')
const chalk = require('chalk')
const { get } = require('dot-prop')
Expand Down Expand Up @@ -307,19 +308,19 @@ const runDeploy = async ({

const handleBuild = async ({ context, flags }) => {
if (!flags.build) {
return
return {}
}
const [token] = await getToken()
const options = await getBuildOptions({
context,
token,
flags,
})
const { exitCode, newConfig } = await runBuild(options)
const { exitCode, newConfig, configMutations } = await runBuild(options)
if (exitCode !== 0) {
context.exit(exitCode)
}
return newConfig
return { newConfig, configMutations }
}

const printResults = ({ flags, results, deployToProduction, exit }) => {
Expand Down Expand Up @@ -429,7 +430,7 @@ class DeployCommand extends Command {
return triggerDeploy({ api, siteId, siteData, error })
}

const newConfig = await handleBuild({ context: this, flags })
const { newConfig, configMutations = [] } = await handleBuild({ context: this, flags })
const config = newConfig || this.netlify.config

const deployFolder = await getDeployFolder({ flags, config, site, siteData })
Expand All @@ -450,6 +451,15 @@ class DeployCommand extends Command {
error,
})
const functionsConfig = normalizeFunctionsConfig({ functionsConfig: config.functions, projectRoot: site.root })

const redirectsPath = `${deployFolder}/_redirects`
await updateConfig(configMutations, {
buildDir: deployFolder,
configPath,
redirectsPath,
context: this.netlify.cachedConfig.context,
branch: this.netlify.cachedConfig.branch,
})
const results = await runDeploy({
flags,
deployToProduction,
Expand All @@ -468,6 +478,10 @@ class DeployCommand extends Command {
exit,
})

if (configMutations.length !== 0) {
await restoreConfig({ buildDir: deployFolder, configPath, redirectsPath })
}

printResults({ flags, results, deployToProduction, exit })

if (flags.open) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ const getBuildOptions = ({
})

const runBuild = async (options) => {
const { severityCode: exitCode, netlifyConfig: newConfig } = await build(options)
return { exitCode, newConfig }
const { severityCode: exitCode, netlifyConfig: newConfig, configMutations } = await build(options)
return { exitCode, newConfig, configMutations }
}

module.exports = { getBuildOptions, runBuild }
82 changes: 78 additions & 4 deletions tests/command.deploy.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable require-await */
const process = require('process')

const test = require('ava')
Expand Down Expand Up @@ -399,7 +400,6 @@ if (process.env.NETLIFY_TEST_DISABLE_LIVE !== 'true') {
})

test.serial('should deploy functions from internal functions directory', async (t) => {
/* eslint-disable require-await */
await withSiteBuilder('site-with-internal-functions', async (builder) => {
await builder
.withNetlifyToml({
Expand Down Expand Up @@ -451,14 +451,12 @@ if (process.env.NETLIFY_TEST_DISABLE_LIVE !== 'true') {
t.is(await got(`${deployUrl}/.netlify/functions/func-1`).text(), 'User 1')
t.is(await got(`${deployUrl}/.netlify/functions/func-2`).text(), 'User 2')
t.is(await got(`${deployUrl}/.netlify/functions/func-3`).text(), 'Internal 3')
/* eslint-enable require-await */
})
})

test.serial(
'should deploy functions from internal functions directory when setting `base` to a sub-directory',
async (t) => {
/* eslint-disable require-await */
await withSiteBuilder('site-with-internal-functions-sub-directory', async (builder) => {
await builder
.withNetlifyToml({
Expand Down Expand Up @@ -487,14 +485,90 @@ if (process.env.NETLIFY_TEST_DISABLE_LIVE !== 'true') {
)

t.is(await got(`${deployUrl}/.netlify/functions/func-1`).text(), 'Internal')
/* eslint-enable require-await */
})
},
)

test.serial('should handle redirects mutated by plugins', async (t) => {
await withSiteBuilder('site-with-public-folder', async (builder) => {
const content = '<h1>⊂◉‿◉つ</h1>'
await builder
.withContentFile({
path: 'public/index.html',
content,
})
.withNetlifyToml({
config: {
build: { publish: 'public' },
functions: { directory: 'functions' },
redirects: [{ from: '/*', to: '/index.html', status: 200 }],
plugins: [{ package: './plugins/mutator' }],
},
})
.withFunction({
path: 'hello.js',
handler: async () => ({
statusCode: 200,
body: 'hello',
}),
})
.withRedirectsFile({
pathPrefix: 'public',
redirects: [{ from: `/api/*`, to: `/.netlify/functions/:splat`, status: '200' }],
})
.withBuildPlugin({
name: 'mutator',
plugin: {
onPostBuild: ({ netlifyConfig }) => {
netlifyConfig.redirects = [
{
from: '/other-api/*',
to: '/.netlify/functions/:splat',
status: 200,
},
...netlifyConfig.redirects,
]
},
},
})
.buildAsync()

const deploy = await callCli(
['deploy', '--json', '--build'],
{
cwd: builder.directory,
env: { NETLIFY_SITE_ID: t.context.siteId },
},
true,
)

const fullDeploy = await callCli(
['api', 'getDeploy', '--data', JSON.stringify({ deploy_id: deploy.deploy_id })],
{
cwd: builder.directory,
env: { NETLIFY_SITE_ID: t.context.siteId },
},
true,
)

const redirectsMessage = fullDeploy.summary.messages.find(({ title }) => title === '3 redirect rules processed')
t.is(redirectsMessage.description, 'All redirect rules deployed without errors.')

await validateDeploy({ deploy, siteName: SITE_NAME, content, t })

// plugin redirect
t.is(await got(`${deploy.deploy_url}/other-api/hello`).text(), 'hello')
// _redirects redirect
t.is(await got(`${deploy.deploy_url}/api/hello`).text(), 'hello')
// netlify.toml redirect
t.is(await got(`${deploy.deploy_url}/not-existing`).text(), content)
})
})

test.after('cleanup', async (t) => {
const { siteId } = t.context
console.log(`deleting test site "${SITE_NAME}". ${siteId}`)
await callCli(['sites:delete', siteId, '--force'])
})
}
/* eslint-enable require-await */

1 comment on commit 021bbfa

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊 Benchmark results

Package size: 331 MB

Please sign in to comment.