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

Sets the minimum number of Fly machines to 1 #1535

Merged
merged 7 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
22 changes: 22 additions & 0 deletions waspc/packages/deploy/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions waspc/packages/deploy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@typescript-eslint/eslint-plugin": "^5.48.0",
"@typescript-eslint/parser": "^5.48.0",
"eslint": "^8.31.0",
"prettier": "^2.8.8",
"typescript": "^4.9.4"
}
}
28 changes: 22 additions & 6 deletions waspc/packages/deploy/src/providers/fly/helpers/helpers.ts
Copy link
Member

Choose a reason for hiding this comment

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

Nice job adding prettier, but it really makes it hard to review a PR, because there are so many changes and I have to check what is just formatting and what is something more!

It is usually advised to do formatting as a separate PR, not as part of another PR, for this reason.

Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ export function isYes(str: string): boolean {
}

export function ensureWaspDirLooksRight(thisCommand: Command): void {
const dirContainsWasproot = fs.existsSync(path.join(thisCommand.opts().waspProjectDir, '.wasproot'));
const dirContainsWasproot = fs.existsSync(
path.join(thisCommand.opts().waspProjectDir, '.wasproot'),
);
if (dirContainsWasproot) {
return;
}

waspSays('The supplied Wasp directory does not appear to be a valid Wasp project.');
waspSays(
'The supplied Wasp directory does not appear to be a valid Wasp project.',
);
waspSays('Please double check your path.');
exit(1);
}
Expand All @@ -38,8 +42,11 @@ function getWaspBuildDir(waspProjectDir: string) {
return path.join(waspProjectDir, '.wasp', 'build');
}

export function ensureDirsInCmdAreAbsoluteAndPresent(thisCommand: Command): void {
const waspProjectDirPath: string | undefined = thisCommand.opts().waspProjectDir;
export function ensureDirsInCmdAreAbsoluteAndPresent(
thisCommand: Command,
infomiho marked this conversation as resolved.
Show resolved Hide resolved
): void {
const waspProjectDirPath: string | undefined =
thisCommand.opts().waspProjectDir;
if (waspProjectDirPath) {
if (!path.isAbsolute(waspProjectDirPath)) {
waspSays('The Wasp dir path must be absolute.');
Expand Down Expand Up @@ -88,6 +95,10 @@ export function waspSays(str: string): void {
console.log('🚀 \x1b[33m ' + str + ' \x1b[0m');
}

export function boldText(str: string): string {
return '\x1b[1m' + str + '\x1b[0m';
}

export function displayWaspRocketImage(): void {
// Escaping backslashes makes it look weird here, but it works in console.
const asciiArt = `
Expand All @@ -109,7 +120,10 @@ export function getCommandHelp(command: Command): string {
}

function trimUsage(usage: string): string {
return usage.split(/[\r\n]+/)[0].replace('Usage: ', '').replace(' [options]', '');
return usage
.split(/[\r\n]+/)[0]
.replace('Usage: ', '')
.replace(' [options]', '');
}

// There is a theoretical race condition here since we are modifying a global `$`
Expand All @@ -118,7 +132,9 @@ function trimUsage(usage: string): string {
// times concurrently could change the setting incorrectly.
// However, our pattern of awaiting for both `$` and `silence` calls without any random
// callbacks using either means this interleaving should not ever happen.
export async function silence(cmd: ($hh: Shell) => Promise<ProcessOutput>): Promise<ProcessOutput> {
export async function silence(
cmd: ($hh: Shell) => Promise<ProcessOutput>,
): Promise<ProcessOutput> {
const verboseSetting = $.verbose;
$.verbose = false;
const proc = await cmd($);
Expand Down
22 changes: 17 additions & 5 deletions waspc/packages/deploy/src/providers/fly/helpers/tomlFileHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import path from 'node:path';
import { CommonOptions } from '../CommonOptions.js';

export interface TomlFilePaths {
serverTomlPath: string;
clientTomlPath: string;
serverTomlPath: string;
clientTomlPath: string;
}

export function getTomlFilePaths(options: CommonOptions): TomlFilePaths {
Expand Down Expand Up @@ -56,18 +56,30 @@ export function getAppNameFromToml(path: string): string {
return data.app;
}

export function getInferredBasenameFromServerToml(paths: TomlFilePaths): string {
export function getInferredBasenameFromServerToml(
paths: TomlFilePaths,
): string {
const serverName = getAppNameFromToml(paths.serverTomlPath);
return serverName.replace('-server', '');
}

export function getInferredBasenameFromClientToml(paths: TomlFilePaths): string {
export function getInferredBasenameFromClientToml(
paths: TomlFilePaths,
): string {
const clientName = getAppNameFromToml(paths.clientTomlPath);
return clientName.replace('-client', '');
}

export function replaceLineInLocalToml(searchValue: string | RegExp, replaceValue: string): void {
export function replaceLineInLocalToml(
searchValue: string | RegExp,
replaceValue: string,
): void {
const content = fs.readFileSync('fly.toml', 'utf8');
const updatedContent = content.replace(searchValue, replaceValue);
fs.writeFileSync('fly.toml', updatedContent);
}

Martinsos marked this conversation as resolved.
Show resolved Hide resolved
export function doesLocalTomlContainLine(searchValue: string | RegExp): boolean {
const content = fs.readFileSync('fly.toml', 'utf8');
return content.search(searchValue) !== -1;
}
84 changes: 71 additions & 13 deletions waspc/packages/deploy/src/providers/fly/setup/setup.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import { $, cd } from 'zx';
import { $, cd, question } from 'zx';
import crypto from 'crypto';
import {
clientTomlExistsInProject,
copyLocalClientTomlToProject,
copyLocalServerTomlToProject,
deleteLocalToml,
doesLocalTomlContainLine,
getTomlFilePaths,
replaceLineInLocalToml,
serverTomlExistsInProject,
} from '../helpers/tomlFileHelpers.js';
import { createDeploymentInfo, DeploymentInfo } from '../DeploymentInfo.js';
import { SetupOptions } from './SetupOptions.js';
import { cdToClientBuildDir, cdToServerBuildDir, makeIdempotent, getCommandHelp, waspSays } from '../helpers/helpers.js';
import {
cdToClientBuildDir,
cdToServerBuildDir,
makeIdempotent,
getCommandHelp,
waspSays,
boldText,
} from '../helpers/helpers.js';
import { createFlyDbCommand } from '../index.js';

export async function setup(baseName: string, region: string, options: SetupOptions): Promise<void> {
export async function setup(
baseName: string,
region: string,
options: SetupOptions,
): Promise<void> {
waspSays('Setting up your Wasp app with Fly.io!');

const buildWasp = makeIdempotent(async () => {
Expand All @@ -24,7 +36,12 @@ export async function setup(baseName: string, region: string, options: SetupOpti
});

const tomlFilePaths = getTomlFilePaths(options);
const deploymentInfo = createDeploymentInfo(baseName, region, options, tomlFilePaths);
const deploymentInfo = createDeploymentInfo(
baseName,
region,
options,
tomlFilePaths,
);

if (serverTomlExistsInProject(tomlFilePaths)) {
waspSays(`${tomlFilePaths.serverTomlPath} exists. Skipping server setup.`);
Expand All @@ -40,7 +57,11 @@ export async function setup(baseName: string, region: string, options: SetupOpti
await setupClient(deploymentInfo);
}

waspSays(`Don't forget to create your database by running "${getCommandHelp(createFlyDbCommand)}".`);
waspSays(
`Don't forget to create your database by running "${getCommandHelp(
createFlyDbCommand,
)}".`,
);
}

async function setupServer(deploymentInfo: DeploymentInfo<SetupOptions>) {
Expand All @@ -50,8 +71,10 @@ async function setupServer(deploymentInfo: DeploymentInfo<SetupOptions>) {
deleteLocalToml();

const launchArgs = [
'--name', deploymentInfo.serverName,
'--region', deploymentInfo.region,
'--name',
deploymentInfo.serverName,
'--region',
deploymentInfo.region,
];

if (deploymentInfo.options.org) {
Expand All @@ -61,6 +84,24 @@ async function setupServer(deploymentInfo: DeploymentInfo<SetupOptions>) {
// This creates the fly.toml file, but does not attempt to deploy.
await $`flyctl launch --no-deploy ${launchArgs}`;

const minMachinesOptionRegex = /min_machines_running = 0/g;

if (!doesLocalTomlContainLine(minMachinesOptionRegex)) {
await question(`⚠️ There was an issue setting up your server app.
We tried modifying your server fly.toml to set ${boldText(
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
'min_machines_running = 1',
)}, but couldn't find the option ${boldText(
'min_machines_running',
)} in the fly.toml.

This might mean your server app might not be always running,
which could cause certain Wasp features like jobs to not work.
Martinsos marked this conversation as resolved.
Show resolved Hide resolved

Press any key to continue or Ctrl+C to cancel.`);
} else {
replaceLineInLocalToml(minMachinesOptionRegex, 'min_machines_running = 1');
}

copyLocalServerTomlToProject(deploymentInfo.tomlFilePaths);

const randomString = crypto.randomBytes(32).toString('hex');
Expand All @@ -74,7 +115,7 @@ async function setupServer(deploymentInfo: DeploymentInfo<SetupOptions>) {
];

if (deploymentInfo.options.serverSecret.length > 0) {
deploymentInfo.options.serverSecret.forEach(secret => {
deploymentInfo.options.serverSecret.forEach((secret) => {
secretsArgs.push(secret);
});
}
Expand All @@ -92,8 +133,10 @@ async function setupClient(deploymentInfo: DeploymentInfo<SetupOptions>) {
deleteLocalToml();

const launchArgs = [
'--name', deploymentInfo.clientName,
'--region', deploymentInfo.region,
'--name',
deploymentInfo.clientName,
'--region',
deploymentInfo.region,
];

if (deploymentInfo.options.org) {
Expand All @@ -103,9 +146,24 @@ async function setupClient(deploymentInfo: DeploymentInfo<SetupOptions>) {
// This creates the fly.toml file, but does not attempt to deploy.
await $`flyctl launch --no-deploy ${launchArgs}`;

// goStatic listens on port 8043 by default, but the default fly.toml
// assumes port 8080 (or 3000, depending on flyctl version).
replaceLineInLocalToml(/internal_port = \d+/g, 'internal_port = 8043');
const internalPortOptionRegex = /internal_port = \d+/g;

if (!doesLocalTomlContainLine(internalPortOptionRegex)) {
await question(`⚠️ There was an issue setting up your client app.
We tried modifying your client fly.toml to set ${boldText(
'internal_port = 8043',
)}, but couldn't find the option ${boldText(
'modifying',
)} in the fly.toml.
Martinsos marked this conversation as resolved.
Show resolved Hide resolved

This might mean your client app might not be accessible,

Martinsos marked this conversation as resolved.
Show resolved Hide resolved
Press any key to continue or Ctrl+C to cancel.`);
} else {
// goStatic listens on port 8043 by default, but the default fly.toml
// assumes port 8080 (or 3000, depending on flyctl version).
replaceLineInLocalToml(internalPortOptionRegex, 'internal_port = 8043');
}

copyLocalClientTomlToProject(deploymentInfo.tomlFilePaths);

Expand Down
1 change: 0 additions & 1 deletion waspc/waspc.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ data-files:
packages/studio/dist/**/*.js
packages/studio/dist/**/*.html
packages/studio/dist/**/*.css
packages/studio/dist/**/*.png
packages/studio/package.json
packages/studio/package-lock.json
data-dir: data/
Expand Down
16 changes: 11 additions & 5 deletions web/docs/advanced/deployment/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,23 @@ wasp deploy fly create-db mia
wasp deploy fly deploy
```

The commands above use the app basename `my-wasp-app` and deploy it to the _Miami, Florida (US) region_ (called `mia`).
The commands above use the app basename `my-wasp-app` and deploy it to the _Miami, Florida (US) region_ (called `mia`). Read more about Fly.io regions [here](#flyio-regions).

:::caution Unique Name
Your app name must be unique across all of Fly or deployment will fail.
:::

The basename is used to create all three app tiers, resulting in three separate apps in your Fly dashboard:

- `my-wasp-app-client`
- `my-wasp-app-server`
- `my-wasp-app-db`

:::caution Unique Name
Your app name must be unique across all of Fly or deployment will fail.
:::
You'll notice that Wasp creates two new files in your project root directory:
- `fly-server.toml`
- `fly-client.toml`

Read more about Fly.io regions [here](#flyio-regions).
You should include these files in your version control so that you can deploy your app with a single command in the future.

### Using a Custom Domain For Your App

Expand Down Expand Up @@ -159,6 +163,8 @@ It accepts the following arguments:
After running `setup`, Wasp creates two new files in your project root directory: `fly-server.toml` and `fly-client.toml`.
You should include these files in your version control.

You **can edit the `fly-server.toml` and `fly-client.toml` files** to further configure your Fly deployments. Wasp will use the TOML files when you run `deploy`.

If you want to maintain multiple apps, you can add the `--fly-toml-dir <abs-path>` option to point to different directories, like "dev" or "staging".

:::caution Execute Only Once
Expand Down
Loading