Engineering Efficiency in LINE

48
Engineering Efficiency powered by Go Huy Do Software Engineering LINE corp

Transcript of Engineering Efficiency in LINE

Page 1: Engineering Efficiency in LINE

Engineering Efficiency powered by Go

Huy Do Software Engineering

LINE corp

Page 2: Engineering Efficiency in LINE

reflect.TypeOf(Who)me := &Who { Name: "Huy Do", Location: "Tokyo", Org: "LINE corp", Misc: "admin member of Ruby Vietnam group, and co-founded kipalog.com",}

Page 3: Engineering Efficiency in LINE

Engineering Efficiency

Page 4: Engineering Efficiency in LINE

How to measure effectiveness?

Page 5: Engineering Efficiency in LINE

effectiveness =

Time Saved

Page 6: Engineering Efficiency in LINE

“We massively underinvest in this kind of work”

Peter Seibel, Twitter

Page 7: Engineering Efficiency in LINE

How many dedicated engineers?

Page 8: Engineering Efficiency in LINE

http://www.gigamonkeys.com/flowers/

Page 9: Engineering Efficiency in LINE

Engineering Efficiency at LINE

Page 10: Engineering Efficiency in LINE

We do anything, except raising your

salary!

Page 11: Engineering Efficiency in LINE

• Building in-house deploy system • Building scale in-house monitoring system • Building / maintaining OSS CI/Repository

system

Building many tools help our colleague engineers focus in write code efficiently

https://linecorp.com/ja/career/position/786

Page 12: Engineering Efficiency in LINE

Introduce Lineflow

Page 13: Engineering Efficiency in LINE

LINE Development process

Page 14: Engineering Efficiency in LINE

https://engineering.linecorp.com/ja/blog/detail/38

1. Make JIRA ticket 2. Create local branch follow TICKET-ID-feature 3. Make a Pull Request to upstream/develop 4. Release to Beta server 5. Request QA team to confirm feature 6. Cherry-pick changes to local TICKET-ID-release branch 7. Make a Pull Request to upstream/release 8. Increase artifact version 9. Create RC branch and release to staging server and confirm

integration 10. Release to Canary server and confirm no big problem 11. Release to all server 12. Close JIRA ticket

Page 15: Engineering Efficiency in LINE

We need to follow many conventions as well

Page 16: Engineering Efficiency in LINE

12 steps needed to release your code production!!!!

Page 17: Engineering Efficiency in LINE

it's just too much!!!!!

Page 18: Engineering Efficiency in LINE

But Process is needed

• Procedures protect us from stepping on another's toes

• Conventions help us inspect problem

Page 19: Engineering Efficiency in LINE

Problem 1: Manual copy paste is just painful

Page 20: Engineering Efficiency in LINE
Page 21: Engineering Efficiency in LINE

design CLI tool for process automation

Page 22: Engineering Efficiency in LINE

Lineflow goals

• Extensible • Safe • Reflect the domain • Zero dependency

Page 23: Engineering Efficiency in LINE
Page 24: Engineering Efficiency in LINE
Page 25: Engineering Efficiency in LINE
Page 26: Engineering Efficiency in LINE

Some concepts • flow

• Set of commands belong to same domain

• subcommand• Represent single execute step

Page 27: Engineering Efficiency in LINE

workflow

subcommand

Page 28: Engineering Efficiency in LINE

Implementation

Page 29: Engineering Efficiency in LINE

type Command struct { Execute func(cmd *Command, args *Args) Flag flag.FlagSet

... Name string parent *Command childs map[string]*Command }

type Args struct { Executable string Command string ProgramPath string Params []string

... }

type Executor struct { commands map[string]*Command execute func(cmds []*cmd.Cmd) error }

We wrote simple wrapper for os/exec

Page 30: Engineering Efficiency in LINE

func (r *Executor) Execute() ExecError { .... cmd := Find(args.Command) if cmd != nil { return r.Call(cmd, args) } printUsage() return newExecError(errors.New("command not exist")) }

func (r *Executor) Find(name string) *Command { return r.commands[name] }

Page 31: Engineering Efficiency in LINE

Problem 2: I just forgot what I should do next

Page 32: Engineering Efficiency in LINE

Command suggestion

Page 33: Engineering Efficiency in LINE
Page 34: Engineering Efficiency in LINE

Implementation

Page 35: Engineering Efficiency in LINE

Define flow order

Page 36: Engineering Efficiency in LINE

flowSpec.Next(cmdCommit). Next(cmdDevelopPullRequest). Next(cmdReleaseCherryPick). Next(cmdReleasePullRequest). Next(cmdVersionCommit). Next(cmdRcBranchCreate). Next(cmdReleaseShareTemplate). Next(cmdNewDevelopBranch)

DSL to define depedency graph

Page 37: Engineering Efficiency in LINE

type FlowSpec struct { root *CmdNode last *CmdNode }

func (f *FlowSpec) NextOf(cmd *c.Command) (*c.Command, error)

func (f *FlowSpec) Next(cmd *c.Command) *FlowSpec

struct called FlowSpec to implement the DSL

Page 38: Engineering Efficiency in LINE

type CmdNode struct { value *c.Command next *CmdNode prev *CmdNode } func (n *CmdNode) Prev(cn *CmdNode) { n.prev = cn cn.next = n }

func (n *CmdNode) Next(cn *CmdNode) { n.next = cn cn.prev = n }

func (n *CmdNode) GetNext() *CmdNode { return n.next }

func (n *CmdNode) GetPrev() *CmdNode { return n.prev }

Simple double linked list

Page 39: Engineering Efficiency in LINE

What is the last thing that you've done ?

Page 40: Engineering Efficiency in LINE

• Branch name as unique identity

• Just store every executed command in ~/.lineflow_history (same idea with .bash_history)

Page 41: Engineering Efficiency in LINE

type History struct { fileLocation string commands []*c.Command }

func (h *History) Register(cs ...*c.Command)

func (h *History) Save(cmd *c.Command, meta string) error

func (h *History) traverseFromTop( f func(*c.Command, string) bool) error

func (h *History) Last(parent *c.Command, meta string) *c.Command

func (h *History) toHistoryString(cmd *c.Command) string

func (h *History) historyStringToCommand(s string) (*c.Command, string, error)

Page 42: Engineering Efficiency in LINE

So basically that's how lineflow is built

Page 43: Engineering Efficiency in LINE

Thanks to https://github.com/studio3104

lineflow + peco

Page 44: Engineering Efficiency in LINE

Lineflow impact• Saved time

• 500 engineer * 5 minutes ~ 41 hours (per day)

• Make foundation for further internal tool intergration

• Help new comer get used to the process

Page 45: Engineering Efficiency in LINE

What we learned• Golang is bad at writing DSL • Hard to develop plugin-style due static

code loader (compare to ruby)

Page 46: Engineering Efficiency in LINE

How golang survive in Java shop

• IntelliJ Golang plugin is great (we can work with both java/golang in same editor)

• go tools ecosystem is great (debugger, benchmark, test tool..)

• Distribute golang code is great (we love binary)

Page 47: Engineering Efficiency in LINE

How to build good internal product

• MUST invest resource (there are no good short-term solution)

• API, and good API • You need to be an evangelist for your

own product, or no body will use yours :(

Page 48: Engineering Efficiency in LINE

Thank you