Skip to content

Commit

Permalink
fix: broken deploy with --skip-functions-cache (#6433)
Browse files Browse the repository at this point in the history
* fix: broken deploy with --skip-functions-cache

as the getPathInProject function is not monorepo aware this breaks on monorepos

* chore: fix test

* Update src/commands/deploy/deploy.ts

Co-authored-by: Eduardo Bouças <mail@eduardoboucas.com>

* chore: fix linting errors and disable rules globally

---------

Co-authored-by: Eduardo Bouças <mail@eduardoboucas.com>
  • Loading branch information
lukasholzer and eduardoboucas committed Mar 13, 2024
1 parent 38ae744 commit d804a96
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 185 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.cjs
Expand Up @@ -42,6 +42,9 @@ module.exports = {
'unicorn/consistent-destructuring': 0,
// TODO: harmonize with filename snake_case in other Netlify Dev projects
'unicorn/filename-case': [2, { case: 'kebabCase' }],
'max-params': 'off',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': 'off',
},
overrides: [
...overrides,
Expand Down Expand Up @@ -136,6 +139,7 @@ module.exports = {
rules: {
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
},
},
],
Expand Down
7 changes: 7 additions & 0 deletions src/commands/base-command.ts
Expand Up @@ -695,6 +695,13 @@ export default class BaseCommand extends Command {
}
}

/**
* get a path inside the `.netlify` project folder
*/
getPathInProject(...paths: string[]): string {
return join(this.workspacePackage || '', '.netlify', ...paths)
}

/**
* Returns the context that should be used in case one hasn't been explicitly
* set. The default context is `dev` most of the time, but some commands may
Expand Down
134 changes: 69 additions & 65 deletions src/commands/deploy/deploy.ts
@@ -1,3 +1,4 @@
import { Stats } from 'fs'
import { stat } from 'fs/promises'
import { basename, resolve } from 'path'

Expand Down Expand Up @@ -37,6 +38,7 @@ import openBrowser from '../../utils/open-browser.js'
import BaseCommand from '../base-command.js'
import { link } from '../link/link.js'
import { sitesCreate } from '../sites/sites-create.js'
import { $TSFixMe } from '../types.js'

// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
const triggerDeploy = async ({ api, options, siteData, siteId }) => {
Expand Down Expand Up @@ -65,19 +67,21 @@ const triggerDeploy = async ({ api, options, siteData, siteId }) => {
}
}

/**
* Retrieves the folder containing the static files that need to be deployed
* @param {object} config
* @param {import('../base-command.js').default} config.command The process working directory
* @param {object} config.config
* @param {import('commander').OptionValues} config.options
* @param {object} config.site
* @param {object} config.siteData
* @returns {Promise<string>}
*/
// @ts-expect-error TS(7031) FIXME: Binding element 'command' implicitly has an 'any' ... Remove this comment to see the full error message
const getDeployFolder = async ({ command, config, options, site, siteData }) => {
let deployFolder
/** Retrieves the folder containing the static files that need to be deployed */
const getDeployFolder = async ({
command,
config,
options,
site,
siteData,
}: {
command: BaseCommand
config: $TSFixMe
options: OptionValues
site: $TSFixMe
siteData: $TSFixMe
}): Promise<string> => {
let deployFolder: string | undefined
// if the `--dir .` flag is provided we should resolve it to the working directory.
// - in regular sites this is the `process.cwd`
// - in mono repositories this will be the root of the jsWorkspace
Expand All @@ -102,31 +106,28 @@ const getDeployFolder = async ({ command, config, options, site, siteData }) =>
filter: (input) => resolve(command.workingDir, input),
},
])
deployFolder = promptPath
deployFolder = promptPath as string
}

return deployFolder
}

/**
* @param {string} deployFolder
*/
// @ts-expect-error TS(7006) FIXME: Parameter 'deployFolder' implicitly has an 'any' t... Remove this comment to see the full error message
const validateDeployFolder = async (deployFolder) => {
/** @type {import('fs').Stats} */
let stats
const validateDeployFolder = async (deployFolder: string) => {
let stats: Stats
try {
stats = await stat(deployFolder)
} catch (error_) {
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
if (error_.code === 'ENOENT') {
return error(`No such directory ${deployFolder}! Did you forget to run a build?`)
}
if (error_ && typeof error_ === 'object' && 'code' in error_) {
if (error_.code === 'ENOENT') {
return error(
`The deploy directory "${deployFolder}" has not been found. Did you forget to run 'netlify build'?`,
)
}

// Improve the message of permission errors
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
if (error_.code === 'EACCES') {
return error('Permission error when trying to access deploy folder')
// Improve the message of permission errors
if (error_.code === 'EACCES') {
return error('Permission error when trying to access deploy folder')
}
}
throw error_
}
Expand All @@ -137,19 +138,22 @@ const validateDeployFolder = async (deployFolder) => {
return stats
}

/**
* get the functions directory
* @param {object} config
* @param {object} config.config
* @param {import('commander').OptionValues} config.options
* @param {object} config.site
* @param {object} config.siteData
* @param {string} config.workingDir // The process working directory
* @returns {string|undefined}
*/
// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
const getFunctionsFolder = ({ config, options, site, siteData, workingDir }) => {
let functionsFolder
/** get the functions directory */
const getFunctionsFolder = ({
config,
options,
site,
siteData,
workingDir,
}: {
config: $TSFixMe
options: OptionValues
site: $TSFixMe
siteData: $TSFixMe
/** The process working directory where the build command is executed */
workingDir: string
}): string | undefined => {
let functionsFolder: string | undefined
// Support "functions" and "Functions"
const funcConfig = config.functionsDirectory
if (options.functions) {
Expand All @@ -162,30 +166,24 @@ const getFunctionsFolder = ({ config, options, site, siteData, workingDir }) =>
return functionsFolder
}

/**
*
* @param {string|undefined} functionsFolder
*/
// @ts-expect-error TS(7006) FIXME: Parameter 'functionsFolder' implicitly has an 'any... Remove this comment to see the full error message
const validateFunctionsFolder = async (functionsFolder) => {
/** @type {import('fs').Stats|undefined} */
let stats
const validateFunctionsFolder = async (functionsFolder: string | undefined) => {
let stats: Stats | undefined
if (functionsFolder) {
// we used to hard error if functions folder is specified but doesn't exist
// but this was too strict for onboarding. we can just log a warning.
try {
stats = await stat(functionsFolder)
} catch (error_) {
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
if (error_.code === 'ENOENT') {
log(
`Functions folder "${functionsFolder}" specified but it doesn't exist! Will proceed without deploying functions`,
)
}
// Improve the message of permission errors
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
if (error_.code === 'EACCES') {
error('Permission error when trying to access functions folder')
if (error_ && typeof error_ === 'object' && 'code' in error_) {
if (error_.code === 'ENOENT') {
log(
`Functions folder "${functionsFolder}" specified but it doesn't exist! Will proceed without deploying functions`,
)
}
// Improve the message of permission errors
if (error_.code === 'EACCES') {
error('Permission error when trying to access functions folder')
}
}
}
}
Expand All @@ -197,8 +195,13 @@ const validateFunctionsFolder = async (functionsFolder) => {
return stats
}

// @ts-expect-error TS(7031) FIXME: Binding element 'deployFolder' implicitly has an '... Remove this comment to see the full error message
const validateFolders = async ({ deployFolder, functionsFolder }) => {
const validateFolders = async ({
deployFolder,
functionsFolder,
}: {
deployFolder: string
functionsFolder?: string
}) => {
const deployFolderStat = await validateDeployFolder(deployFolder)
const functionsFolderStat = await validateFunctionsFolder(functionsFolder)
return { deployFolderStat, functionsFolderStat }
Expand Down Expand Up @@ -353,7 +356,7 @@ const uploadDeployBlobs = async ({
silent,
siteId,
}: {
cachedConfig: any
cachedConfig: $TSFixMe
deployId: string
options: OptionValues
packagePath?: string
Expand Down Expand Up @@ -402,7 +405,6 @@ const runDeploy = async ({
alias,
// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
api,
// @ts-expect-error TS(7031) FIXME: Binding element 'command' implicitly has an 'any' ... Remove this comment to see the full error message
command,
// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
config,
Expand Down Expand Up @@ -433,6 +435,7 @@ const runDeploy = async ({
title,
}: {
functionsFolder?: string
command: BaseCommand
}) => {
let results
let deployId
Expand Down Expand Up @@ -486,11 +489,12 @@ const runDeploy = async ({
packagePath: command.workspacePackage,
})

results = await deploySite(api, siteId, deployFolder, {
results = await deploySite(command, api, siteId, deployFolder, {
// @ts-expect-error FIXME
config,
fnDir: functionDirectories,
functionsConfig,

statusCb: silent ? () => {} : deployProgressCb(),
deployTimeout,
syncFileLimit: SYNC_FILE_LIMIT,
Expand Down
3 changes: 2 additions & 1 deletion src/commands/dev/dev.ts
@@ -1,8 +1,8 @@
import process from 'process'

import { OptionValues, Option } from 'commander'
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module '@net... Remove this comment to see the full error message
import { applyMutations } from '@netlify/config'
import { OptionValues, Option } from 'commander'

import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContext } from '../../lib/blobs/blobs.js'
import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js'
Expand Down Expand Up @@ -216,6 +216,7 @@ export const dev = async (options: OptionValues, command: BaseCommand) => {
await startProxyServer({
addonsUrls,
blobsContext,
command,
config: mutatedConfig,
configPath: configPathOverride,
debug: options.debug,
Expand Down
1 change: 1 addition & 0 deletions src/commands/serve/serve.ts
Expand Up @@ -141,6 +141,7 @@ export const serve = async (options: OptionValues, command: BaseCommand) => {
// @ts-expect-error TS(2345) FIXME: Argument of type '{ addonsUrls: { [k: string]: any... Remove this comment to see the full error message
const url = await startProxyServer({
addonsUrls,
command,
config,
configPath: configPathOverride,
debug: options.debug,
Expand Down
11 changes: 3 additions & 8 deletions src/lib/edge-functions/deploy.ts
Expand Up @@ -12,7 +12,7 @@ const distPath = getPathInProject([EDGE_FUNCTIONS_FOLDER])
* @param {*} file
*/
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
export const deployFileNormalizer = (workingDir, file) => {
export const deployFileNormalizer = (workingDir: string, file) => {
const absoluteDistPath = join(workingDir, distPath)
const isEdgeFunction = file.root === absoluteDistPath
const normalizedPath = isEdgeFunction ? `${PUBLIC_URL_PATH}/${file.normalizedPath}` : file.normalizedPath
Expand All @@ -23,11 +23,7 @@ export const deployFileNormalizer = (workingDir, file) => {
}
}

/**
* @param {string} workingDir
*/
// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
export const getDistPathIfExists = async (workingDir) => {
export const getDistPathIfExists = async (workingDir: string) => {
try {
const absoluteDistPath = join(workingDir, distPath)
const stats = await stat(absoluteDistPath)
Expand All @@ -42,5 +38,4 @@ export const getDistPathIfExists = async (workingDir) => {
}
}

// @ts-expect-error TS(7006) FIXME: Parameter 'filePath' implicitly has an 'any' type.
export const isEdgeFunctionFile = (filePath) => filePath.startsWith(`${PUBLIC_URL_PATH}/`)
export const isEdgeFunctionFile = (filePath: string) => filePath.startsWith(`${PUBLIC_URL_PATH}/`)

2 comments on commit d804a96

@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

  • Dependency count: 1,326
  • Package size: 298 MB
  • Number of ts-expect-error directives: 1,120

@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

  • Dependency count: 1,326
  • Package size: 298 MB
  • Number of ts-expect-error directives: 1,120

Please sign in to comment.