-
Notifications
You must be signed in to change notification settings - Fork 85
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
Tail Up #86
Tail Up #86
Changes from 20 commits
7fb1b1b
c5b9fce
65c97a8
eb0d866
6d40cda
d9d2c94
195c813
a156456
37d8166
4219921
5160c21
790cf2f
4318461
f89e601
68bdaae
d69764e
14111a3
43667d6
c5e2e7d
8211097
0b4742e
7561a47
605131c
be59758
56874e1
26872fb
eaee90c
ebe870e
b903df0
eadea0d
99e2392
1612327
3d0a471
e758abe
435862f
e0d29e8
87a4ae6
33b3dd1
8ee0741
dc4499f
ae3b695
cb6016e
3a8c17d
3b7edab
0a0f732
bc7e15d
dcd5ac5
00cbe76
c85ae11
9596b7c
4267093
1fa5ca9
8441dd9
ddcc28f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 1,15 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/railwayapp/cli/entity" | ||
) | ||
|
||
func (h *Handler) Logs(ctx context.Context, req *entity.CommandRequest) error { | ||
numLines, err := req.Cmd.Flags().GetInt32("num_lines") | ||
if err != nil { | ||
return err | ||
} | ||
return h.ctrl.GetActiveDeploymentLogs(ctx, numLines) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,5 18,12 @@ func (h *Handler) Up(ctx context.Context, req *entity.CommandRequest) error { | |
} else { | ||
ui.StopSpinner(fmt.Sprintf("☁️ Deploy available at %s\n", ui.GrayText(url))) | ||
} | ||
return nil | ||
detach, err := req.Cmd.Flags().GetBool("detach") | ||
if err != nil { | ||
return err | ||
} | ||
if detach { | ||
return nil | ||
} | ||
return h.ctrl.GetActiveDeploymentLogs(ctx, 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might need to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LOL |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 1,76 @@ | ||
package controller | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math" | ||
"strings" | ||
"time" | ||
|
||
"github.com/railwayapp/cli/entity" | ||
) | ||
|
||
func (c *Controller) GetActiveDeploymentLogs(ctx context.Context, numLines int32) error { | ||
projectID, err := c.cfg.GetProject() | ||
if err != nil { | ||
return err | ||
} | ||
environmentID, err := c.cfg.GetEnvironment() | ||
if err != nil { | ||
return err | ||
} | ||
deployments, err := c.gtwy.GetDeploymentsForEnvironment(ctx, projectID, environmentID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
latestDeploy := deployments[0] | ||
// Streaming | ||
prevIdx := 0 | ||
status := latestDeploy.Status | ||
for { | ||
err := func() error { | ||
if prevIdx != 0 { | ||
time.Sleep(time.Second * 2) | ||
} | ||
deploy, err := c.gtwy.GetDeploymentByID(ctx, projectID, latestDeploy.ID) | ||
if err != nil { | ||
return err | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also check |
||
if deploy.Status != status { | ||
// Reset when moving states | ||
prevIdx = 0 | ||
status = deploy.Status | ||
} | ||
logs := fetchCurrentLogs(*deploy) | ||
partials := strings.Split(logs, "\n") | ||
nextIdx := len(partials) | ||
delimiter := prevIdx | ||
if numLines != 0 { | ||
// If num is provided do a walkback by n lines to get latest n logs | ||
delimiter = int(math.Max(float64(len(partials)-int(numLines)), float64(prevIdx))) | ||
} | ||
delta := partials[delimiter:nextIdx] | ||
if len(delta) == 0 { | ||
return nil | ||
} | ||
fmt.Println(strings.Join(delta, "\n")) | ||
prevIdx = nextIdx | ||
return nil | ||
}() | ||
if err != nil { | ||
return err | ||
} | ||
if numLines != 0 { | ||
// Break if numlines provided | ||
return nil | ||
} | ||
} | ||
} | ||
|
||
func fetchCurrentLogs(deployment entity.Deployment) string { | ||
if deployment.Status == "BUILDING" { | ||
return deployment.BuildLogs | ||
} | ||
return deployment.DeployLogs | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 1,8 @@ | ||
package entity | ||
|
||
type Deployment struct { | ||
ID string `json:"id"` | ||
BuildLogs string `json:"buildLogs"` | ||
DeployLogs string `json:"deployLogs"` | ||
Status string `json:"status"` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 1,64 @@ | ||
package gateway | ||
|
||
import ( | ||
"context" | ||
|
||
gql "github.com/machinebox/graphql" | ||
"github.com/railwayapp/cli/entity" | ||
"github.com/railwayapp/cli/errors" | ||
) | ||
|
||
func (g *Gateway) GetDeploymentsForEnvironment(ctx context.Context, projectId string, environmentId string) ([]entity.Deployment, error) { | ||
gqlReq := gql.NewRequest(` | ||
query ($projectId: ID!, $environmentId: ID!) { | ||
allDeploymentsForEnvironment(projectId: $projectId, environmentId: $environmentId) { | ||
id | ||
status | ||
} | ||
} | ||
`) | ||
|
||
gqlReq.Var("projectId", projectId) | ||
gqlReq.Var("environmentId", environmentId) | ||
|
||
err := g.authorize(ctx, gqlReq.Header) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var resp struct { | ||
Deployments []entity.Deployment `json:"allDeploymentsForEnvironment"` | ||
} | ||
if err := g.gqlClient.Run(ctx, gqlReq, &resp); err != nil { | ||
return nil, errors.PluginGetFailed | ||
} | ||
return resp.Deployments, nil | ||
} | ||
|
||
func (g *Gateway) GetDeploymentByID(ctx context.Context, projectId string, deploymentId string) (*entity.Deployment, error) { | ||
gqlReq := gql.NewRequest(` | ||
query ($projectId: ID!, $deploymentId: ID!) { | ||
deploymentById(projectId: $projectId, deploymentId: $deploymentId) { | ||
id | ||
buildLogs | ||
deployLogs | ||
status | ||
} | ||
} | ||
`) | ||
gqlReq.Var("projectId", projectId) | ||
gqlReq.Var("deploymentId", deploymentId) | ||
|
||
err := g.authorize(ctx, gqlReq.Header) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var resp struct { | ||
Deployment *entity.Deployment `json:"deploymentById"` | ||
} | ||
if err := g.gqlClient.Run(ctx, gqlReq, &resp); err != nil { | ||
return nil, errors.PluginGetFailed | ||
} | ||
return resp.Deployment, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that
railway up
, by default, streams both build and runtime logs indefinitely after?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd vote to only see build logs after
up
.My flow is usually to make sure the deploy worked, then go back to writing code. Right now it's difficult to see when it switches from build to deploy then you have to ctrl-C out (which may also not be obvious to less-experienced devs).
One idea might be to detect when the build succeeded and prompt the user to continue streaming the deploy logs or exit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured the "Build Completed" line is solid for this
My issue is that we fire build completed regardless of outcome, and only fetch the actual deployment logs (Which contains the "Failed to Deploy!" stuff. If we do a prompt, users might not see that
Could see it either way tho. Don't really have a strong opinion so can add a prompt pretty easily