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
11 changes: 11 additions & 0 deletions cmd/up.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cmd

import (
"context"

"github.com/railwayapp/cli/entity"
)

func (h *Handler) Up(ctx context.Context, req *entity.CommandRequest) error {
return h.ctrl.Up(ctx)
}
95 changes: 95 additions & 0 deletions controller/up.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package controller

import (
"archive/tar"
"bytes"
"compress/gzip"
"context"
"io"
"io/ioutil"
"os"
"path/filepath"

"github.com/monochromegane/go-gitignore"
)

func compress(src string, buf io.Writer) error {
// tar > gzip > buf
zr := gzip.NewWriter(buf)
tw := tar.NewWriter(zr)

ignore, err := gitignore.NewGitIgnore(".gitignore", ".")
if err != nil {
return err
}
// walk through every file in the folder
filepath.Walk(src, func(file string, fi os.FileInfo, err error) error {
if ignore.Match(file, fi.IsDir()) {
return nil
}
// generate tar header
header, err := tar.FileInfoHeader(fi, file)
if err != nil {
return err
}

if err != nil {
return err
}
// must provide real name
// (see https://golang.org/src/archive/tar/common.go?#L626)
header.Name = filepath.ToSlash(file)

// write header
if err := tw.WriteHeader(header); err != nil {
return err
}
// if not a dir, write file content
if !fi.IsDir() {
Comment thread
coffee-cup marked this conversation as resolved.
data, err := os.Open(file)
if err != nil {
return err
}
if _, err := io.Copy(tw, data); err != nil {
return err
}
}
return nil
})

// produce tar
if err := tw.Close(); err != nil {
return err
}
// produce gzip
if err := zr.Close(); err != nil {
return err
}
return nil
}

func (c *Controller) Up(ctx context.Context) error {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If this is only enabled for admins, should we also prevent non-admins from using this command?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That would mean exposing an endpoint to determine if a user is or isn't an admin. Too much leakage IMO.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We already have a gql endpoint setup to fetch the user. We could a also return the isAdmin flag there. Alternatively, we could just check if there is any user config defined (admins will obviously be logged in)

// projectID, err := c.cfg.GetProject()
// if err != nil {
// return err
// }
// environmentID, err := c.cfg.GetEnvironment()
// if err != nil {
// return err
// }
var buf bytes.Buffer
if err := compress("./", &buf); err != nil {
return err
}
ioutil.WriteFile("./out.tar.gz", buf.Bytes(), 0777)
// res, err := c.gtwy.Up(ctx, &entity.UpRequest{
// Data: buf,
// ProjectID: projectID,
// EnvironmentID: environmentID,
// })
// if err != nil {
// return err
// }
//fmt.Printf("Deploy available at %s\n", res.URL)
return nil
}
13 changes: 13 additions & 0 deletions entity/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package entity

import "bytes"

type UpRequest struct {
Data bytes.Buffer
ProjectID string
EnvironmentID string
}

type UpResponse struct {
URL string
}
6 changes: 5 additions & 1 deletion gateway/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ func (g *Gateway) setProjectToken(ctx context.Context, req *gql.Request) error {
return nil
}

func GetGQLHost() string {
func GetHost() string {
baseURL := "https://backboard.railway.app"
if configs.IsDevMode() {
baseURL = fmt.Sprintf("http://localhost:8082")
}
return baseURL
}

func GetGQLHost() string {
baseURL := GetHost()
return fmt.Sprintf("%s/graphql", baseURL)
}

Expand Down
60 changes: 60 additions & 0 deletions gateway/up.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package gateway

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"mime/multipart"
"net/http"

"github.com/railwayapp/cli/entity"
)

func constructReq(ctx context.Context, req *entity.UpRequest) (*http.Request, error) {
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", req.ProjectID)
if err != nil {
return nil, err
}
part.Write(req.Data.Bytes())

err = writer.Close()
if err != nil {
return nil, err
}
url := fmt.Sprintf("%s/project/%s/up", GetHost(), req.ProjectID)
httpReq, err := http.NewRequest("POST", url, body)
if err != nil {
return nil, err
}
httpReq.Header.Set("Content-Type", writer.FormDataContentType())
return httpReq, nil
}

func (g *Gateway) Up(ctx context.Context, req *entity.UpRequest) (*entity.UpResponse, error) {
httpReq, err := constructReq(ctx, req)
if err != nil {
return nil, err
}
client := &http.Client{}
resp, err := client.Do(httpReq)
if err != nil {
return nil, err
}
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
return nil, errors.New(string(bodyBytes))
}
var res entity.UpResponse
if err := json.Unmarshal(bodyBytes, &res); err != nil {
return nil, err
}
return &res, nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381
github.com/machinebox/graphql v0.2.2
github.com/manifoldco/promptui v0.7.0
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
github.com/spf13/cobra v1.0.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
Expand Down
5 changes: 5 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ func init() {
Short: "Run command inside the Railway environment",
RunE: contextualize(handler.Run),
})
rootCmd.AddCommand(&cobra.Command{
Use: "up",
Short: "Upload and deploy",
RunE: contextualize(handler.Up),
})
}

func main() {
Expand Down