Skip to content

Commit 5c53698

Browse files
committed
fix: tell users to re-run netlify dev after interrupting dev to init project
When a user runs `netlify dev` on an unlinked repository and they're using an extension that requires a linked repository (e.g. Neon), we interrupt them to initialize a project. Because of the way we cache information about the current site, we're unable to effectively invalidate the site state before starting the dev process, and so we exit and expect the user to run `netlify dev` again to proceed. We currently don't explicitly tell the user we're about to exit and that they need to re-run `netlify dev`, though, which is jarring and leaves the user in a bit of a lurch. This changeset adds an informational message after `netlify dev` exits, telling them to re-run the dev command. Ideally we would not require this step, but we need to do some work on how we invalidate cached site data before we can do that.
1 parent d604bf9 commit 5c53698

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

src/commands/dev/dev.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
chalk,
1717
log,
1818
normalizeConfig,
19+
netlifyCommand,
1920
} from '../../utils/command-helpers.js'
2021
import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.js'
2122
import { UNLINKED_SITE_MOCK_ID, getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.js'
@@ -111,7 +112,21 @@ export const dev = async (options: OptionValues, command: BaseCommand) => {
111112
} a linked project, but you don't have one linked yet. Let's do that first.`,
112113
)
113114
const { init } = await import('../init/init.js')
114-
await init(getBaseOptionValues(options), command)
115+
const { LINKED_NEW_SITE_EXIT_CODE, LINKED_EXISTING_SITE_EXIT_CODE } = await import('../init/constants.js')
116+
117+
await init(getBaseOptionValues(options), command, {
118+
customizeExitMessage: (code, defaultMessage) => {
119+
switch (code) {
120+
case LINKED_NEW_SITE_EXIT_CODE:
121+
// fallthrough
122+
case LINKED_EXISTING_SITE_EXIT_CODE:
123+
return `${defaultMessage !== '' ? `${defaultMessage}\n` : ''}You can run ${chalk.cyanBright.bold(
124+
`${netlifyCommand()} dev`,
125+
)} again to start the local development server.`
126+
}
127+
},
128+
exitAfterConfiguringRepo: true,
129+
})
115130
}
116131

117132
const blobsContext = await getBlobsContextWithEdgeAccess({

src/commands/init/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const LINKED_NEW_SITE_EXIT_CODE = 'LINKED_NEW_SITE'
2+
3+
export const LINKED_EXISTING_SITE_EXIT_CODE = 'LINKED_EXISTING_SITE'
4+
5+
export type InitExitCode = typeof LINKED_NEW_SITE_EXIT_CODE | typeof LINKED_EXISTING_SITE_EXIT_CODE

src/commands/init/init.ts

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { link } from '../link/link.js'
1212
import { sitesCreate } from '../sites/sites-create.js'
1313
import type { CLIState, SiteInfo } from '../../utils/types.js'
1414
import { getBuildSettings, saveNetlifyToml } from '../../utils/init/utils.js'
15+
import { type InitExitCode, LINKED_EXISTING_SITE_EXIT_CODE, LINKED_NEW_SITE_EXIT_CODE } from './constants.js'
1516

1617
const persistState = ({ siteInfo, state }: { siteInfo: SiteInfo; state: CLIState }): void => {
1718
// Save to .netlify/state.json file
@@ -43,10 +44,12 @@ const createNewSiteAndExit = async ({
4344
command,
4445
state,
4546
disableLinking,
47+
customizeExitMessage,
4648
}: {
4749
command: BaseCommand
4850
state: CLIState
4951
disableLinking: boolean
52+
customizeExitMessage: InitExitMessageCustomizer | undefined
5053
}): Promise<never> => {
5154
const siteInfo = await sitesCreate({}, command)
5255

@@ -78,8 +81,8 @@ const createNewSiteAndExit = async ({
7881
}
7982

8083
log()
81-
log(`To deploy to this project, run ${chalk.cyanBright.bold(`${netlifyCommand()} deploy`)}`)
82-
84+
const defaultExitMesage = `To deploy to this project, run ${chalk.cyanBright.bold(`${netlifyCommand()} deploy`)}.`
85+
log(customizeExitMessage?.(LINKED_NEW_SITE_EXIT_CODE, defaultExitMesage) ?? defaultExitMesage)
8386
return exit()
8487
}
8588

@@ -124,11 +127,13 @@ const handleNoGitRemoteAndExit = async ({
124127
error,
125128
state,
126129
disableLinking,
130+
customizeExitMessage,
127131
}: {
128132
command: BaseCommand
129133
error?: unknown
130134
state: CLIState
131135
disableLinking: boolean
136+
customizeExitMessage: InitExitMessageCustomizer | undefined
132137
}): Promise<never> => {
133138
log()
134139
log(chalk.yellow('No git remote was found, would you like to set one up?'))
@@ -159,7 +164,8 @@ git remote add origin https://github.com/YourUserName/RepoName.git
159164
])
160165

161166
if (noGitRemoteChoice === NEW_SITE_NO_GIT) {
162-
return createNewSiteAndExit({ state, command, disableLinking })
167+
// TODO(ndhoule): Shove a custom error message in here
168+
return createNewSiteAndExit({ state, command, disableLinking, customizeExitMessage })
163169
}
164170
return logGitSetupInstructionsAndExit()
165171
}
@@ -194,15 +200,36 @@ const createOrLinkSiteToRepo = async (command: BaseCommand) => {
194200
return await link({}, command)
195201
}
196202

197-
const logExistingRepoSetupAndExit = ({ repoUrl, siteName }: { repoUrl: string; siteName: string }): void => {
203+
const logExistingRepoSetupAndExit = ({
204+
repoUrl,
205+
siteName,
206+
customizeExitMessage,
207+
}: {
208+
repoUrl: string
209+
siteName: string
210+
customizeExitMessage: InitExitMessageCustomizer | undefined
211+
}): void => {
198212
log()
199213
log(chalk.underline.bold(`Success`))
200-
log(`This project "${siteName}" is configured to automatically deploy via ${repoUrl}`)
214+
215+
const defaultExitMessage = `This project "${siteName}" is configured to automatically deploy via ${repoUrl}.`
216+
log(customizeExitMessage?.(LINKED_EXISTING_SITE_EXIT_CODE, defaultExitMessage) ?? defaultExitMessage)
201217
// TODO add support for changing GitHub repo in site:config command
202218
exit()
203219
}
204220

205-
export const init = async (options: OptionValues, command: BaseCommand): Promise<SiteInfo> => {
221+
type InitExitMessageCustomizer = (code: InitExitCode, defaultMessage: string) => string | undefined
222+
223+
type InitExtraOptions = {
224+
customizeExitMessage?: InitExitMessageCustomizer | undefined
225+
exitAfterConfiguringRepo?: boolean | undefined
226+
}
227+
228+
export const init = async (
229+
options: OptionValues,
230+
command: BaseCommand,
231+
{ customizeExitMessage, exitAfterConfiguringRepo = false }: InitExtraOptions = {},
232+
): Promise<SiteInfo> => {
206233
command.setAnalyticsPayload({ manual: options.manual, force: options.force })
207234

208235
const { repositoryRoot, state } = command.netlify
@@ -222,11 +249,13 @@ export const init = async (options: OptionValues, command: BaseCommand): Promise
222249
// Look for local repo
223250
const repoData = await getRepoData({ workingDir: command.workingDir, remoteName: options.gitRemoteName })
224251
if ('error' in repoData) {
252+
// TODO(ndhoule): Custom error messaage here
225253
return await handleNoGitRemoteAndExit({
226254
command,
227255
error: repoData.error,
228256
state,
229257
disableLinking: options.disableLinking,
258+
customizeExitMessage,
230259
})
231260
}
232261

@@ -237,12 +266,19 @@ export const init = async (options: OptionValues, command: BaseCommand): Promise
237266
// Check for existing CI setup
238267
const remoteBuildRepo = getRepoUrl(siteInfo)
239268
if (remoteBuildRepo && !options.force) {
240-
logExistingRepoSetupAndExit({ siteName: siteInfo.name, repoUrl: remoteBuildRepo })
269+
logExistingRepoSetupAndExit({ siteName: siteInfo.name, repoUrl: remoteBuildRepo, customizeExitMessage })
241270
}
242271

243272
persistState({ state, siteInfo })
244273

245274
await configureRepo({ command, siteId: siteInfo.id, repoData, manual: options.manual })
275+
if (exitAfterConfiguringRepo) {
276+
const customErrorMessage = customizeExitMessage?.(LINKED_EXISTING_SITE_EXIT_CODE, '')
277+
if (customErrorMessage) {
278+
log(customErrorMessage)
279+
}
280+
return exit()
281+
}
246282

247283
return siteInfo
248284
}

0 commit comments

Comments
 (0)