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

Providers - Railway / deployment only #1157

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

OlegGulevskyy
Copy link

Deploy stuff to Railway

Take into account things

  1. railway login does not work in non-interactive mode. Current implementation checks if user logged in, otherwise throw out of the process with a friendly hint what to do next
  2. Global options --wasp-exe <path> and --wasp-project-dir <dir> are being added to each subcommand in the global scope
  3. This implementation expects a specific file for railway deployments to be present in the main root directory of Wasp - wasp.deployrc.railway.json
    It's expected signature is:
	"environment": "production",
	"projectId": "bef41c2c-b1a9-42ef-adb9-e3afa84fbbea",
	"clientService": {
		"name": "client",
		"url": "client-production-6ea1.up.railway.app"
	},
	"serverService": {
		"name": "server",
		"url": "server-production-dfaf.up.railway.app"
	}

Environment - required by Railway as there can exist multiple envs
ProjectID - build folder has to be linked with a respective project
Client / Server Service - info about the client service (ID and its URL). Railways projects consist of services, that you can spin up pretty easily. Each service has its own env variables etc.

Whenever "setup" feature is implemented, we can ensure that this file is create automatically, but I am not entirely sure if that's a good idea to do. Need peoplez thoughts on this. Alternative, we force users to provide those values as flags / arguments.. ?

Refactor suggestions things

  1. Suggesting to keep all types in .d.ts files to clearly indicate what they are

  2. Even though haven't done it properly myself, but I'd probably also remove Capital casing on type files, as I see no benefit in this, if we mark the file with .d.ts extension, it should be clear enough what file is for.

  3. Stick to naming convention of types to indicate where they belong to - FlyDeployOptions, Railway(Rw)DeployOptions. Eases search of specific options across the codebase instead of doing a global search and having 10+ same names

  4. Installed fs-extra package, hoping it's allowed :) otherwise, can be reimplemented (mainly used for ensureDir, but it provides other convenient stuffs)

  5. await $railway up --service ${clientService.name} - is a stream of logs for deploying. Atm this implementation just fires & forgets, giving a URL of logs as an output, so maybe for v1 it's ok, but later do a re-stream? No idea how to re-stream output logs tho

  6. Fn HACK_PACKAGES_JSON has to die, but it allows to continue with implementation, as types are not used in Docker and tsc is run, that leads to bunch of types missing. This is because Server is not built inside the Docker container, so I'd like opinions on what could be / should be done. It might come across as pretty obvious one - just build the server - but do we then cherry pick specific folders from server, aiming just specific types folders etc? I am not fan of this option because if we add a library tomorrow to the server side, and forget to cherry pick its types inside this deployment Docker, we will have a failing build.

  7. Added prettier config for a consist styling, feedback / suggestions on its content is appreciated! For now, I just tried to mirror what has already been put together in terms of style by Shayne :)

A lot has been moved around from /fly provider, as a lot of nice conveniences were living in it, so had to move it up a scope to make them shareable.

It is a very breaking change as I moved a lot of things around, but it was building fine for me... (as always). As I am not a Fly.io user and I have very limited time, I'd appreciate someone's help with testing this to ensure no regression.

Select what type of change this PR introduces:

  1. Just code/docs improvement (no functional change).
  2. Bug fix (non-breaking change which fixes an issue).
  3. New feature (non-breaking change which adds functionality).
  4. Breaking change (fix or feature that would cause existing functionality to not work as expected).

Update Waspc ChangeLog and version if needed

If you did a bug fix, new feature, or breaking change, that affects waspc, make sure you satisfy the following:

  1. I updated ChangeLog.md with description of the change this PR introduces.
  2. I bumped waspc version in waspc.cabal to reflect changes I introduced, with regards to the version of the latest wasp release, if the bump was needed.

@vincanger
Copy link
Contributor

vincanger commented Apr 21, 2023

Very nice, @OlegGulevskyy 🚀. This seems like a really great start. This is the first time I've actually looked at the deploy code as this isn't really my domain. Learning new things myself here :)

The one thing I could comment on here concerns the wasp.deployrc.railway.json file. From what I know about Railway, the user would have to set up a "service" and "generate a domain" for both the client and server first, before defining it in the json file. Currently, it seems that its not possible to create a service via the CLI (https://docs.railway.app/reference/cli-api#service), which would make the script a lot friendlier, although it does seem like you can generate a domain via CLI with railway domain. Do you know if there is a possible way to add a service programatically, without the user having to define it first within the Railway dashboard?

Also, would be nice at some point to use railway add to add the Postgres database and seed it with wasp db seed (https://wasp-lang.dev/docs/language/features#seeding).

But, yeah, great work. Looking forward to following the progress here 👏

@OlegGulevskyy
Copy link
Author

OlegGulevskyy commented Apr 21, 2023

This is the first time I've actually looked at the deploy code as this isn't really my domain. Learning new things myself here :)

Yeah, deploy code is just a node cli with TS, so we all can contribute :)

Do you know if there is a possible way to add a service programatically

Not that I know of, no. It seems their CLI is very limited when it comes to setting things up. That's also one of the reasons why I solely focused on deploying as a first feature. At least you can configure your stuff in their UI and just do one line command re-deployments.
But I do agree that comparing to fly provider, this is much more humble functionality (even if we just compare deploy part and not entirely the provider).

Also, would be nice at some point to use railway add to add the Postgres database

This seems to be a viable option, but needs to be played around with (maybe next item on the agenda), however I do have my doubts:

  • output results (if we don't know the details of the created DB, it's kind of pointless, as we need to link server and DB together, so it's easier to do it through UI potentially)
  • setting env variables on services. without those env variables on each service, they are pretty useless in terms of one click deployments. Maybe I am just not seeing the elephant in the room and I don't know if that's handled in fly.io but if we can't retrieve newly created DB's URL and set it as env variable in server service, I am not sure it's useful at all (just do it altogether in UI)

Copy link
Sponsor Contributor

@shayneczyzewski shayneczyzewski left a comment

Choose a reason for hiding this comment

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

Amazing effort and work so far @OlegGulevskyy! 🥳 I think your refactoring of things makes sense. And your suggestions for future work are also solid. To be honest, this was the first TS code I've ever written, so I am glad it was a decent enough start, but we will keep improving upon it!

I think given the restrictions of the Railway API, the ability to only (re-)deploy to existing projects makes sense. The overall design makes sense at first glance to me as well.

I will do a deeper dive and do some actual test deploys on Monday, but wanted to provide some initial feedback (left as comments). The TLDR is thanks for doing this, I think it is awesome and on the right track, and have a great weekend! 🙏🏻

@@ -2,5 +2,7 @@ To run the deploy package as a standalone TS project, run:
```sh
npm install
npm run build
node dist/index.js fly ...
npm run cli fly ...
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Nice adding to package.json and documenting the two required options, thnx!👍🏻

@@ -0,0 +1,7 @@
import { CommonOptions, LocalBuildOptions } from '../../shared/CommonOptions';

export interface FlyDeployOptions extends CommonOptions, LocalBuildOptions {
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

I like the renaming of types to be provider-specific, to help distinguish/searching. Is there any way we may be able to encode this convention into the type system? Just thinking out loud to make sure all providers "do the right thing" here.

Copy link
Author

Choose a reason for hiding this comment

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

Probably is possible, not 100% sure, with tslint or similar (linting) but I do imagine this being a complex thing and I don't know if it's really worth it. Instead, it might be easier for a while making a note of it or README.md file to instruct people to stick to this convention and pay attention to those during code reviews

Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Yeah, agreed, let's keep it simple for now and rely on conventions. 👍🏻

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

Choose a reason for hiding this comment

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

Can this be a shared hook?

Copy link
Author

Choose a reason for hiding this comment

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

I think I tried, but fly checks for different folder, like toml dir while Railway doesn't at all, apart from wasp dir. So while they need to do similar types of checks (existence of dir), dirs are different. So extracted dir checking logic and just making each provider check different dirs on its own. But it could be probably done a bit different, if we'd set a getter for dirs in Command extension, and then in the shared util just use this getter to verify dirs. Only thought of this now

Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Ah ok, sorry, I totally missed the Fly toml check in the diff. Separate seems fine to me, thanks for the explanation! 👍🏻

@@ -0,0 +1,6 @@
module.exports = {
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Awesome job adding prettier. 🎨 We will want to make sure it plays nicely with the eslint config. Check output from npx eslint src. I am fine using whatever convention so long as they both align. Thanks! :) 👍🏻

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, the current project reports a lot of errors. This article seems to give a good explanation on how to integrate them. :)

@@ -0,0 +1,39 @@
### Take into account things
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Great writeup!


1. `railway login` does not work in non-interactive mode. Current implementation checks if user logged in, otherwise throw out of the process with a friendly hint what to do next
2. Global options `--wasp-exe <path>` and `--wasp-project-dir <dir>` are being added to each subcommand in the global scope
3. This implementation expects a specific file for railway deployments to be present in the main root directory of Wasp - `wasp.deployrc.railway.json`
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Do you think it makes sense to make the path to a railway.json file an option, so they can have multiple envs? Similar to how we treat the fly*.toml files?

Copy link
Author

Choose a reason for hiding this comment

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

yeah absolutely, has to be added

Copy link
Contributor

Choose a reason for hiding this comment

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

Great job on documenting your thoughts here 👍

When we close to finishing up the implementation, let's keep in mind to cleanup this README 😄

@@ -0,0 +1,7 @@
import { CommonOptions } from '../../shared/CommonOptions';

export interface RwDeployOptions extends CommonOptions {
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Do you think at the type level, using the full name makes sense? e.g swap Rw for Railway? Mainly thinking for clarity/readability's sake.

Copy link
Author

Choose a reason for hiding this comment

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

full name wouldn't hurt :)

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 on using full names vs. rw shorthand in all types

export const RAILWAY_CONFIG_FILE_NAME = 'wasp.deployrc.railway.json';

// Docker file that will be used to copy to the client side of Wasp
export const REACT_DOCKER_TEMPLATE = `FROM node:18-alpine AS builder
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

If you want to simplify this (maybe, unsure if it will work on Railway), you can do what we had to do on Fly. It, too, wasn't expressly made for React client hosting and as such went with this approach: https://github.com/wasp-lang/wasp/blob/main/waspc/packages/deploy/src/providers/fly/deploy/deploy.ts#L110-L118

It feels functionally equivalent, but just a bit shorter. If it achieves the same aim on both providers maybe we can turn it into a shared helper?

Copy link
Author

Choose a reason for hiding this comment

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

worth double checking! thanks

Comment on lines +7 to +8
environment: string;
projectId: string;
Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

This may be misaligned with below.

@shayneczyzewski
Copy link
Sponsor Contributor

Hi @OlegGulevskyy, nice work again! I got a chance to play with it today and my thoughts are below.

  1. Fly stuff looks good and still appears to work as expected, nice!

  2. If the wasp.deployrc.railway.json file is missing, perhaps we can check and provide a nicer message?

🚀  Deploying your Wasp app to Railway!
$ cd /tmp/wasp/waspc/examples/todoApp/
node:fs:600
  handleErrorFromBinding(ctx);
  ^

Error: wasp.deployrc.railway.json: ENOENT: no such file or directory, open 'wasp.deployrc.railway.json'
    at Object.openSync (node:fs:600:3)
    at Object.readFileSync (node:fs:468:35)
    at Object.readFileSync (/tmp/wasp/waspc/data/packages/deploy/node_modules/jsonfile/index.js:50:22)
    at getRailwayConfig (file:///tmp/wasp/waspc/data/packages/deploy/dist/providers/railway/helpers/helpers.js:49:15)
    at RailwayCommand.deploy (file:///tmp/wasp/waspc/data/packages/deploy/dist/providers/railway/deploy/deploy.js:10:22)
    at RailwayCommand.listener [as _actionHandler] (/tmp/wasp/waspc/data/packages/deploy/node_modules/commander/lib/command.js:482:17)
    at /tmp/wasp/waspc/data/packages/deploy/node_modules/commander/lib/command.js:1264:65
    at /tmp/wasp/waspc/data/packages/deploy/node_modules/commander/lib/command.js:1155:33
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Command.parseAsync (/tmp/wasp/waspc/data/packages/deploy/node_modules/commander/lib/command.js:916:5) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: 'wasp.deployrc.railway.json'
}
  1. I set up a Railway app with the two services in the file, but despite the CLI saying it was deployed, it actually failed to build. Here is the output from the client and server services:
=========================
Using Detected Dockerfile
=========================
context: 8061f20702d6d02060c6efe45a69e52c
#1 [internal] load .dockerignore
 
#1 transferring context: 2B 0.0s done
 
#1 DONE 0.1s
 
 
 
#2 [internal] load build definition from Dockerfile
 
#2 transferring dockerfile: 47B 0.0s done
 
#2 DONE 0.1s
Dockerfile:1
-------------------
1 | >>> ## HELLO!
2 |
-------------------
ERROR: failed to solve: file with no instructions

 
=========================
Using Detected Dockerfile
=========================
context: e3702485d84e1a5ad0ac8661e46a05cc
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 47B done
 
#1 DONE 0.1s
 
#2 [internal] load .dockerignore
#2 transferring context: 2B done
#2 DONE 0.1s
Dockerfile:1
-------------------
1 | >>> ## HELLO!
2 |
-------------------
ERROR: failed to solve: file with no instructions

I was attempting to build this project: https://github.com/wasp-lang/wasp/tree/main/waspc/examples/todoApp

Here is my JSON file:

{
  "environment": "production",
	"projectId": "0a469ab4-78b6-4283-8674-1d80c09a0fb8",
	"clientService": {
		"name": "client",
		"url": "client-production-7866.up.railway.app"
	},
	"serverService": {
		"name": "server",
		"url": "server-production-22f3.up.railway.app"
	}
}

Any ideas on what may be up?

  1. Where/how should I wire in a DB?

Thanks for the help in getting my first Railway deploy up! 🚀

@shayneczyzewski
Copy link
Sponsor Contributor

P.S. I've asked @sodic to review this as time permits, so you will have someone better than me for your TS stuff @OlegGulevskyy :)

Copy link
Contributor

@infomiho infomiho left a comment

Choose a reason for hiding this comment

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

Great work! I'm excited about having Railway as a deployment provider in Wasp :)

@@ -0,0 +1,19 @@
import { Command, Option } from 'commander';

export const createGlobalOptions = (cmd: Command): void => {
Copy link
Contributor

Choose a reason for hiding this comment

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

@OlegGulevskyy I would maybe go with addGlobalOptions since it confused me for a bit, what does create mean? Why don't we return it if it's created etc.

@@ -0,0 +1,20 @@
import fs from 'fs';
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit:hooks reminds me of React hooks, maybe commandHooks.ts would be more clear?

@@ -0,0 +1,108 @@
import fs from 'fs';
Copy link
Contributor

Choose a reason for hiding this comment

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

We try to avoid generic helper files e.g. helpers.ts, utils.ts, tools.ts etc. and try to name the file in a way that represents some kind of helpers or specific domain.

Here's my take on splitting these functions into multiple helper files:

terminal.ts

  • waspSays
  • displayWaspRocketImage
  • trimUsage
  • getCommandHelp
  • isYes

shell.ts

  • makeIdempotent
  • silence

fileSystem.ts

  • ensureDirAbsoluteAndExists
  • getWaspBuildDir
  • cdToClientBuildDir
  • cdToServerBuildDir

Copy link
Contributor

Choose a reason for hiding this comment

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

These files have just been moved from fly, but the comment is still valid. @OlegGulevskyy You can change it as @infomiho suggested if you want to, but it's not a big deal if you don't :)

@@ -0,0 +1,81 @@
import { Command } from 'commander';
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar as the comment on the otherhelpers.ts file, I would suggest a more meaningful name.

Since this file deals only with hooks, I would recommend commandHooks.ts (I've commented also on the hooks.ts naming below which I feel should be commandHooks.ts)

@@ -0,0 +1,7 @@
import { CommonOptions, LocalBuildOptions } from '../../shared/CommonOptions';
Copy link
Contributor

Choose a reason for hiding this comment

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

@OlegGulevskyy You can stick to .ts files instead of .d.ts since this is a Typescript package. I guess there is no harm in writing .d.ts but maybe down the line we want to declare some helper functions close to types, then we have to rename the file.

Using .ts has no downsides AFAIK.

@sodic am I missing something?

@@ -0,0 +1,7 @@
import { CommonOptions } from '../../shared/CommonOptions';

export interface RwDeployOptions extends CommonOptions {
Copy link
Contributor

Choose a reason for hiding this comment

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

+1 on using full names vs. rw shorthand in all types

import { CommonOptions } from '../../shared/CommonOptions';
import { RailwayDeploymentConfig } from '../types';

export type RwDeploymentInfo = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: We used interfaces for the Fly implementation and extended the CommonOptions. We should probably be consistent if we can.

Here's we are defining types and embedding the CommonOptions. I could go either way, but it would be nice if we both for both providers :)


class RailwayCommand extends Command {}

const rwDeployCommand = makeRailwayDeployCommand();
Copy link
Contributor

Choose a reason for hiding this comment

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

If we don't need this const outside of addRailwayCommand we could move it inside addRailwayCommand


// For some reason, the colors from the chalk package wouldn't
// show up when run as a subprocess by the Wasp CLI. This works.
export function waspSays(str: string): void {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should implement waspWarns and waspScreams for warnings and errors as we do in Haskell :)

Probably out of scope for this PR but just a thought I had.


// TODO: add support for multiple environmental files (prod, dev)
// with flag for user to pass which config file to use
export function getRailwayConfig(): RailwayDeploymentConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

@OlegGulevskyy I would maybe also add a check for this file instead of failing with

🚀  Deploying your Wasp app to Railway!
$ cd /Users/ilakovac/dev/contributors/oleg/wasp/waspc/examples/todoApp/
node:fs:601
  handleErrorFromBinding(ctx);
  ^

Error: wasp.deployrc.railway.json: ENOENT: no such file or directory, open 'wasp.deployrc.railway.json'

Copy link
Contributor

Choose a reason for hiding this comment

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

What would be even better for DX, if the file doesn't exists:

  • say it need to exists
  • describe the expected file format (or even offer to generate it, but that's maybe a stretch)
  • let them know how can they can create the project and services (railway init, railway list --jsonetc.)

Copy link
Contributor

@infomiho infomiho Apr 25, 2023

Choose a reason for hiding this comment

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

For me as a user that hasn't deploy to Railway before, the hardest thing was figuring out how to create that file 😢

Copy link
Contributor

@sodic sodic left a comment

Choose a reason for hiding this comment

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

Thanks a lot @OlegGulevskyy!

Most of my comments talk about TypeScript, code structure and refactoring. I didn't test out the functionality and study the implementation since @infomiho and @shayneczyzewski already have that covered.

@@ -0,0 +1,6 @@
module.exports = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, the current project reports a lot of errors. This article seems to give a good explanation on how to integrate them. :)

Comment on lines +1 to +15
export interface CommonOptions {
waspExe: string;
waspProjectDir: string;
flyTomlDir?: string;
}

export interface DbOptions {
vmSize: string;
initialClusterSize: string;
volumeSize: string;
}

export interface LocalBuildOptions {
buildLocally: boolean;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't seem quite right.

Several (if not most) of these options are specific to providers (one that I'm sure about is flyTomlDir). Any current overlap between Railway and Fly is caused more by accident than by semantics. Therefore, I don't think we should be extracting them as something "common". Each provider should have their own set of options (duplication is better than an forced abstraction).

@shayneczyzewski and @OlegGulevskyy. Of course, I didn't write any of this code so please tell me if I'm missing something.

Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

Ah, good point, I totally missed this. Yes, I would say DbOptions is purely related to Fly, as is flyTomlDir?.

I think waspExe and waspProjectDir will be needed for all providers, however. 👍🏻

import { createFlyDbCommand } from '../index.js';
import { cdToClientBuildDir, cdToServerBuildDir, getCommandHelp, makeIdempotent, waspSays } from '../../shared/helpers.js';
Copy link
Contributor

Choose a reason for hiding this comment

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

I think Prettier takes care of this automatically when they get too long.

Comment on lines +9 to +12
export async function deployServer({
commonOptions,
serverService,
}: RwServerDeploymentInfo) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Mind the module boundaries: wasp-lang/vscode-wasp#6 (comment).

Our ESLint reports this too, so I'm just providing an explanation behind the rule.

@@ -0,0 +1,19 @@
import { Command, Option } from 'commander';

export const createGlobalOptions = (cmd: Command): void => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip: Avoid arrow functions on the top level if you don't need them. Details: #487.

### Refactor suggestions things

4. Suggesting to keep all types in `.d.ts` files to clearly indicate what they are
5. Even though haven't done it properly myself, but I'd probably also remove Capital casing on type files, as I see no benefit in this, if we mark the file with `.d.ts` extension, it should be clear enough what file is for.
Copy link
Contributor

Choose a reason for hiding this comment

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

You can convert the names to lowercase if you want :)


4. Suggesting to keep all types in `.d.ts` files to clearly indicate what they are
5. Even though haven't done it properly myself, but I'd probably also remove Capital casing on type files, as I see no benefit in this, if we mark the file with `.d.ts` extension, it should be clear enough what file is for.
6. Stick to naming convention of types to indicate where they belong to - FlyDeployOptions, Railway(Rw)DeployOptions. Eases search of specific options across the codebase instead of doing a global search and having 10+ same names
Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense, we can do this!

4. Suggesting to keep all types in `.d.ts` files to clearly indicate what they are
5. Even though haven't done it properly myself, but I'd probably also remove Capital casing on type files, as I see no benefit in this, if we mark the file with `.d.ts` extension, it should be clear enough what file is for.
6. Stick to naming convention of types to indicate where they belong to - FlyDeployOptions, Railway(Rw)DeployOptions. Eases search of specific options across the codebase instead of doing a global search and having 10+ same names
7. Installed `fs-extra` package, hoping it's allowed :) otherwise, can be reimplemented (mainly used for `ensureDir`, but it provides other convenient stuffs)
Copy link
Contributor

Choose a reason for hiding this comment

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

@shayneczyzewski Will this have a too negative effect our build size? It can stay, as far as I'm concerned.

Copy link
Sponsor Contributor

Choose a reason for hiding this comment

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

I think we will be ok there, seems pretty small 👍🏻


8. `await $railway up --service ${clientService.name}` - is a stream of logs for deploying. Atm this implementation just fires & forgets, giving a URL of logs as an output, so maybe for v1 it's ok, but later do a re-stream? No idea how to re-stream output logs tho

9. Fn `HACK_PACKAGES_JSON` has to die, but it allows to continue with implementation, as types are not used in Docker and `tsc` is run, that leads to bunch of types missing. This is because Server is not built inside the Docker container, so I'd like opinions on what could be / should be done. It might come across as pretty obvious one - just build the server - but do we then cherry pick specific folders from server, aiming just specific types folders etc? I am not fan of this option because if we add a library tomorrow to the server side, and forget to cherry pick its types inside this deployment Docker, we will have a failing build.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'll come back at some point to discuss this. I knew those types would cause a problem at some point 😅.

Comment on lines +1 to 2
import { CommonOptions } from '../../shared/CommonOptions';
import { ContextOption } from '../helpers/CommonOps.js';
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems some files have the .js extension, while others don't. Can we make this consistent?

Copy link
Sponsor Contributor

@shayneczyzewski shayneczyzewski left a comment

Choose a reason for hiding this comment

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

Hi @OlegGulevskyy! I know you are likely very busy, but just wanted to check in and see if there is any support we can provide here. We appreciate it, and hope you found the review comments useful. Thanks so much!

@OlegGulevskyy
Copy link
Author

Hey @shayneczyzewski , yep sorry I am tad busy currently in my things, so all my activity is on pause, but I should get back to the PR some time soon
Your comments look great, thank you! (quite few to read haha)

@shayneczyzewski
Copy link
Sponsor Contributor

Hey @shayneczyzewski , yep sorry I am tad busy currently in my things, so all my activity is on pause, but I should get back to the PR some time soon Your comments look great, thank you! (quite few to read haha)

Awesome, no worries take your time and thanks for keeping it going when you free up! And yes, quite a few haha welcome to the team :D 😎

@Martinsos
Copy link
Member

Pplz @OlegGulevskyy @shayneczyzewski how are we with this PR, any idea when we could progress further? Should I just rewrite it all to Haskell, has that moment finally come :D?

@shayneczyzewski
Copy link
Sponsor Contributor

Pplz @OlegGulevskyy @shayneczyzewski how are we with this PR, any idea when we could progress further? Should I just rewrite it all to Haskell, has that moment finally come :D?

It is stalled at the moment. I think the refactor part is looking good, but I wasn't able to deploy to Railway using it. It could have just been me, though. @infomiho also gave it a try and eventually got it.

Note: there have been a few deploy updates that will need to be rebased into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants