Allow Fly to build locally (#1006)

This commit is contained in:
Shayne Czyzewski 2023-02-16 10:27:30 -05:00 committed by GitHub
parent 2622f3c4cd
commit 868362d103
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 44 additions and 20 deletions

View File

@ -3,3 +3,13 @@ export interface CommonOptions {
waspProjectDir: string;
flyTomlDir?: string;
}
export interface DbOptions {
vmSize: string;
initialClusterSize: string;
volumeSize: string;
}
export interface LocalBuildOptions {
buildLocally: boolean;
}

View File

@ -1,7 +1,3 @@
import { CommonOptions } from '../CommonOptions.js';
import { CommonOptions, DbOptions } from '../CommonOptions.js';
export interface CreateDbOptions extends CommonOptions {
vmSize: string;
initialClusterSize: string;
volumeSize: string;
}
export interface CreateDbOptions extends CommonOptions, DbOptions {}

View File

@ -1,6 +1,6 @@
import { CommonOptions } from '../CommonOptions.js';
import { CommonOptions, LocalBuildOptions } from '../CommonOptions.js';
export interface DeployOptions extends CommonOptions {
export interface DeployOptions extends CommonOptions, LocalBuildOptions {
skipBuild?: boolean;
skipClient?: boolean;
skipServer?: boolean;

View File

@ -50,7 +50,7 @@ export async function deploy(options: DeployOptions): Promise<void> {
const inferredBaseName = getInferredBasenameFromServerToml(tomlFilePaths);
const deploymentInfo = createDeploymentInfo(inferredBaseName, undefined, options, tomlFilePaths);
await buildWasp();
await deployServer(deploymentInfo);
await deployServer(deploymentInfo, options);
}
if (!clientTomlExistsInProject(tomlFilePaths)) {
@ -61,11 +61,11 @@ export async function deploy(options: DeployOptions): Promise<void> {
const inferredBaseName = getInferredBasenameFromClientToml(tomlFilePaths);
const deploymentInfo = createDeploymentInfo(inferredBaseName, undefined, options, tomlFilePaths);
await buildWasp();
await deployClient(deploymentInfo);
await deployClient(deploymentInfo, options);
}
}
async function deployServer(deploymentInfo: DeploymentInfo) {
async function deployServer(deploymentInfo: DeploymentInfo, { buildLocally }: DeployOptions) {
waspSays('Deploying your server now...');
cdToServerBuildDir(deploymentInfo.options.waspProjectDir);
@ -84,7 +84,10 @@ async function deployServer(deploymentInfo: DeploymentInfo) {
exit(1);
}
await $`flyctl deploy --remote-only`;
const deployArgs = [
buildLocally ? '--local-only' : '--remote-only',
];
await $`flyctl deploy ${deployArgs}`;
// NOTE: Deploy is not expected to update the toml file, but doing this just in case.
// However, if it does and we fail to copy it back, we would be in an inconsistent state.
@ -94,7 +97,7 @@ async function deployServer(deploymentInfo: DeploymentInfo) {
waspSays('Server has been deployed!');
}
async function deployClient(deploymentInfo: DeploymentInfo) {
async function deployClient(deploymentInfo: DeploymentInfo, { buildLocally }: DeployOptions) {
waspSays('Deploying your client now...');
cdToClientBuildDir(deploymentInfo.options.waspProjectDir);
@ -115,7 +118,10 @@ async function deployClient(deploymentInfo: DeploymentInfo) {
fs.writeFileSync('Dockerfile', dockerfileContents);
fs.writeFileSync('.dockerignore', '');
await $`flyctl deploy --remote-only`;
const deployArgs = [
buildLocally ? '--local-only' : '--remote-only',
];
await $`flyctl deploy ${deployArgs}`;
copyLocalClientTomlToProject(deploymentInfo.tomlFilePaths);

View File

@ -13,13 +13,16 @@ class FlyCommand extends Command {
return this.argument('<basename>', 'base app name to use on Fly.io (must be unique)');
}
addRegionArgument(): this {
return this.argument('<region>', 'deployment region to use on Fly.io');
return this.argument('<region>', '3 letter deployment region to use on Fly.io');
}
addDbOptions(): this {
return this.option('--vm-size <vmSize>', 'flyctl postgres create option', 'shared-cpu-1x')
.option('--initial-cluster-size <initialClusterSize>', 'flyctl postgres create option', '1')
.option('--volume-size <volumeSize>', 'flyctl postgres create option', '1');
}
addLocalBuildOption(): this {
return this.option('--build-locally', 'build Docker containers locally instead of remotely', false);
}
}
const flyLaunchCommand = makeFlyLaunchCommand();
@ -47,8 +50,8 @@ export function addFlyCommand(program: Command): void {
// NOTE: When we add another provider, consider pulling `--wasp-exe` and `--wasp-project-dir`
// up as a global option that every provider can use (if possible).
fly.commands.forEach((cmd) => {
cmd.requiredOption('--wasp-exe <path>', 'Wasp executable (either on PATH or absolute path)', 'wasp')
.requiredOption('--wasp-project-dir <dir>', 'absolute path to Wasp project dir')
cmd.addOption(new Option('--wasp-exe <path>', 'Wasp executable (either on PATH or absolute path)').hideHelp().makeOptionMandatory())
.addOption(new Option('--wasp-project-dir <dir>', 'absolute path to Wasp project dir').hideHelp().makeOptionMandatory())
.option('--fly-toml-dir <dir>', 'absolute path to dir where fly.toml files live')
.hook('preAction', ensureFlyReady)
.hook('preAction', ensureDirsInCmdAreAbsoluteAndPresent)
@ -67,6 +70,7 @@ function makeFlyLaunchCommand(): Command {
.addBasenameArgument()
.addRegionArgument()
.addDbOptions()
.addLocalBuildOption()
.action(launchFn);
}
@ -84,6 +88,7 @@ function makeFlyDeployCommand(): Command {
.option('--skip-build', 'do not run `wasp build` before deploying')
.option('--skip-client', 'do not deploy the web client')
.option('--skip-server', 'do not deploy the server')
.addLocalBuildOption()
.action(deployFn);
}

View File

@ -0,0 +1,3 @@
import { CommonOptions, DbOptions, LocalBuildOptions } from '../CommonOptions.js';
export interface LaunchOptions extends CommonOptions, DbOptions, LocalBuildOptions {}

View File

@ -1,5 +1,5 @@
import { exit } from 'process';
import { CreateDbOptions } from '../createDb/CreateDbOptions';
import { LaunchOptions } from './LaunchOptions.js';
import { DeployOptions } from '../deploy/DeployOptions.js';
import { getCommandHelp, waspSays } from '../helpers/helpers.js';
import { setup } from '../setup/setup.js';
@ -8,7 +8,7 @@ import { deploy } from '../deploy/deploy.js';
import { clientTomlExistsInProject, getTomlFilePaths, serverTomlExistsInProject } from '../helpers/tomlFileHelpers.js';
import { createFlyDbCommand, flyDeployCommand, flySetupCommand } from '../index.js';
export async function launch(basename: string, region: string, options: CreateDbOptions): Promise<void> {
export async function launch(basename: string, region: string, options: LaunchOptions): Promise<void> {
waspSays('Launching your Wasp app to Fly.io!');
const tomlFilePaths = getTomlFilePaths(options);

View File

@ -54,6 +54,10 @@ You may notice after running `setup` you have a `fly-server.toml` and `fly-clien
Finally, we `deploy` which will push your client and server live. We run this single command each time you want to update your app.
:::note
Fly.io offers support for both locally built Docker containers and remotely built ones. However, for simplicity and reproducability, the CLI defaults to the use of a remote Fly.io builder. If you wish to build locally, you may supply the `--build-locally` option to `wasp deploy fly launch` or `wasp deploy fly deploy`.
:::
If you would like to run arbitrary Fly commands (eg, `flyctl secrets list` for your server app), you can run them like so:
```shell
wasp deploy fly cmd secrets list --context server
@ -110,7 +114,7 @@ Server uses following environment variables, so you need to ensure they are set
Fly.io offers a variety of free services that are perfect for deploying your first Wasp app! You will need a Fly.io account and the [`flyctl` CLI](https://fly.io/docs/hands-on/install-flyctl/).
:::note
Fly.io offers support for both locally built Docker containers and remotely built ones. However, for simplicity and reproducability, we will force the use of a remote Fly.io builder.
Fly.io offers support for both locally built Docker containers and remotely built ones. However, for simplicity and reproducability, we will default to the use of a remote Fly.io builder.
Additionally, `fly` is a symlink for `flyctl` on most systems and they can be used interchangeably.
:::