Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/refresh-project-after-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"cf": patch
---

Use the configured project's commands on the first `cf dev` or `cf build` after setup

When `cf dev` or `cf build` set up a project, they kept the commands and environment detected before setup. If setup changes the project's tooling, for example by setting up a Next.js project with vinext, the first run would use the old commands. cf now analyses the project again after setup, as it already did after converting a Wrangler config.
39 changes: 37 additions & 2 deletions packages/cli/src/__tests__/lib/autoconfig-migration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,49 @@ describe("project preparation", () => {
outputDir: "dist",
buildCommand: "npm run build",
};
mocks.getDetailsForAutoConfig.mockResolvedValue(unconfiguredDetails);
const configuredDetails = {
...unconfiguredDetails,
configured: true,
devCommand: "npx vite dev",
env: { CONFIGURED: "true" },
};
mocks.getDetailsForAutoConfig
.mockResolvedValueOnce(unconfiguredDetails)
.mockResolvedValueOnce(configuredDetails);
mocks.maybeMigrateWranglerProject.mockResolvedValue(false);
mocks.runAutoConfig.mockResolvedValue(configuration);

await expect(prepareProject("/project")).resolves.toEqual({
details: configuredDetails,
configuration,
});
expect(mocks.runAutoConfig).toHaveBeenCalledWith(
unconfiguredDetails,
expect.objectContaining({ runBuild: false })
);
expect(mocks.getDetailsForAutoConfig).toHaveBeenCalledTimes(2);
});

it("keeps the pre-setup details when the configured project cannot be analyzed", async () => {
const configuration = { scripts: {}, outputDir: "dist" };
mocks.getDetailsForAutoConfig
.mockResolvedValueOnce(unconfiguredDetails)
.mockRejectedValueOnce(
new (await import("@cloudflare/autoconfig")).AutoConfigDetectionError(
"not detected",
{
telemetryMessage: "not detected",
configured: false,
}
)
);
mocks.maybeMigrateWranglerProject.mockResolvedValue(false);
mocks.runAutoConfig.mockResolvedValue(configuration);

await expect(prepareProject("/project")).resolves.toEqual({
details: unconfiguredDetails,
configuration,
});
expect(mocks.runAutoConfig).toHaveBeenCalledOnce();
});

it("dry-runs framework setup when Wrangler config conversion did not run", async () => {
Expand All @@ -112,6 +146,7 @@ describe("project preparation", () => {
unconfiguredDetails,
expect.objectContaining({ dryRun: true, runBuild: false })
);
expect(mocks.getDetailsForAutoConfig).toHaveBeenCalledOnce();
expect(mocks.maybeMigrateWranglerProject).toHaveBeenCalledWith(
"/project",
expect.any(Function),
Expand Down
26 changes: 17 additions & 9 deletions packages/cli/src/lib/autoconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,10 @@ export async function configureProject(

/**
* Choose project setup before a build: an accepted Wrangler config conversion
* takes precedence over framework setup. In a dry run, `setupNeeded` means
* a setup route was selected but not applied, so callers must skip the build.
* takes precedence over framework setup. After either route is applied, the
* returned details describe the configured project. In a dry run,
* `setupNeeded` means a setup route was selected but not applied, so callers
* must skip the build.
*/
export async function prepareProject(
cwd: string,
Expand Down Expand Up @@ -131,14 +133,20 @@ export async function prepareProject(
return { details };
}

if (!details) {
return { details };
}

const configuration = await configureProject(details, options);
if (options.dryRun) {
return { details, configuration, setupNeeded: true };
}

// Setup can change which tools the project uses, so callers need the
// details of the configured project rather than the pre-setup analysis.
return {
details,
...(details
? {
configuration: await configureProject(details, options),
...(options.dryRun ? { setupNeeded: true as const } : {}),
}
: {}),
details: (await analyzeProject(cwd, options)) ?? details,
configuration,
};
}

Expand Down
Loading