Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: broken deploy with --skip-functions-cache #6433

Merged
merged 5 commits into from Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.cjs
Expand Up @@ -42,6 +42,7 @@ 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',
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

just useless this linting rule

},
overrides: [
...overrides,
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,26 @@ 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(`No such directory ${deployFolder}! Did you forget to run a build?`)
lukasholzer marked this conversation as resolved.
Show resolved Hide resolved
}

// 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 +136,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 +164,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 +193,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,13 +354,14 @@ const uploadDeployBlobs = async ({
silent,
siteId,
}: {
cachedConfig: any
cachedConfig: $TSFixMe
deployId: string
options: OptionValues
packagePath?: string
silent: boolean
siteId: string
}) => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
lukasholzer marked this conversation as resolved.
Show resolved Hide resolved
const statusCb = silent ? () => {} : deployProgressCb()

statusCb({
Expand Down Expand Up @@ -402,7 +404,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 +434,7 @@ const runDeploy = async ({
title,
}: {
functionsFolder?: string
command: BaseCommand
}) => {
let results
let deployId
Expand Down Expand Up @@ -486,11 +488,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,
// eslint-disable-next-line @typescript-eslint/no-empty-function
statusCb: silent ? () => {} : deployProgressCb(),
deployTimeout,
syncFileLimit: SYNC_FILE_LIMIT,
Expand Down Expand Up @@ -572,6 +575,7 @@ const bundleEdgeFunctions = async (options, command: BaseCommand) => {
// eslint-disable-next-line n/prefer-global/process, unicorn/prefer-set-has
const argv = process.argv.slice(2)
const statusCb =
// eslint-disable-next-line @typescript-eslint/no-empty-function
lukasholzer marked this conversation as resolved.
Show resolved Hide resolved
options.silent || argv.includes('--json') || argv.includes('--silent') ? () => {} : deployProgressCb()

statusCb({
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}/`)