Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Faster Task Organization with ZenHub & Ruboty & peekabow

laprasDrum
February 10, 2018

A Faster Task Organization with ZenHub & Ruboty & peekabow

laprasDrum

February 10, 2018
Tweet

More Decks by laprasDrum

Other Decks in Technology

Transcript

  1. !

  2. • チームの Eng/UX Designer/PM/Biz が Issue 作成 • ZenHub でカンバン管理

    • Issue 作成直後は必ず1番左の Pipeline に入る • 自分のチームでは Inbox と名付けている • 毎日の朝会で 4 Repo の Inbox Issue を共有 • Issue を開いて情報見て文章整形 • #123 設定画面の項目を分かりやすくしたい https://github.com/Org/repo/issues/123 現状を整理してみよう
  3. • チームの Eng/UX Designer/PM/Biz が Issue 作成 • ZenHub でカンバン管理

    • Issue 作成直後は必ず1番左の Pipeline に入る • 自分のチームでは Inbox と名付けている • 毎日の朝会で 4 Repo の Inbox Issue を共有 • Issue を開いて情報見て文章整形 • #123 設定画面の項目を分かりやすくしたい https://github.com/Org/repo/issues/123 現状を整理してみよう トータルで約5分掛かる
  4. やることざっくり Org の Repo って名前の Inbox Issue が知りたい 1. Org/Repo

    の Repo ID 取得 2. Repo ID から Inbox Pipeline の Issue ID を取得 3. Issue ID からタイトルとリンクを取得 & 文章整形
  5. 順を追って説明 peekabow —owner Org —repo Repo —pipeline Inbox 1. Org/Repo

    の Repo ID 取得 2. Repo ID から Inbox Pipeline の Issue ID を取得 3. Issue ID からタイトルとリンクを取得 & 文章整形
  6. 解説ざっくり 1. Org/Repo の Repo ID 取得 var findRepoId struct

    { Repository struct { DatabaseId int } `graphql:"repository(owner: $owner, name: $repo)"` } log(c, " Search repository ID from GitHub...") src := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: config.Token.GitHub}) httpClient := oauth2.NewClient(context.Background(), src) github = githubql.NewClient(httpClient) // owner ͱ repo ͸ CLI Ҿ਺Ͱड͚औ͍ͬͯΔ args := map[string]interface{}{ "owner": githubql.String(owner), "repo": githubql.String(repo), } query := findRepoId if err := github.Query(context.Background(), &query, args); err != nil { panic(err) } log(c, " Found repository ID: "+strconv.Itoa(query.Repository.DatabaseId))
  7. // ZenHub Types type ( Pipelines []Pipeline Board struct {

    Pipelines Pipelines } Pipeline struct { Name string Issues []Issue } Issue struct { IssueNumber int `json:"issue_number"` } ) func (self Pipelines) Find(f func(Pipeline) bool) (Pipeline, bool) { for _, pipeline := range self { if f(pipeline) { return pipeline, true } } return Pipeline{}, false } 解説ざっくり 2. Repo ID から Inbox Pipeline の Issue ID を取得
  8. log(c, " Search pipeline issues from ZenHub...") zenHub := &http.Client{}

    req, _ := http.NewRequest( "GET", "https://api.zenhub.io/p1/repositories/"+strconv.Itoa(query.Repository.DatabaseId)+"/board", nil, ) req.Header.Add("X-Authentication-Token", config.Token.ZenHub) resp, _ := zenHub.Do(req) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) board := new(Board) if err := json.Unmarshal(body, board); err != nil { panic(err) } p, found := board.Pipelines.Find(func(p Pipeline) bool { return p.Name == pipelineName }) 解説ざっくり 2. Repo ID から Inbox Pipeline の Issue ID を取得
  9. 解説ざっくり 3. Issue ID からタイトルとリンクを取得 & 文章整形 // pipeline ໊͸

    CLI Ҿ਺Ͱड͚औ͍ͬͯΔ if !found { fmt.Println("❌ Not Found: " + pipelineName) fmt.Println("❌ Please check whether if your ZenHub pipeline's name is correct.") return } else { fmt.Println(" " + owner + "/" + repo + ": " + pipelineName + "'s issues here:") c := toNumber(p.Issues) // Issue ൪߸ͷ഑ྻग़ྗ༻ channel ʹม׵ out := message(c) // ੔ܗ͞Εͨจষͷग़ྗ༻ channel ʹม׵ var buffer bytes.Buffer for msg := range out { buffer.WriteString(msg + "\n") } if summary := strings.TrimSuffix(buffer.String(), "\n"); summary != "" { fmt.Println(summary) } else { fmt.Println(" No Issue") } }
  10. 解説ざっくり 3. Issue ID からタイトルとリンクを取得 & 文章整形 // GitHub Queries

    type IssueFragment struct { Title string Url string } var findIssue struct { Repository struct { IssueOrPullRequest struct { IssueFragment `graphql:"... on Issue"` } `graphql:"issueOrPullRequest(number: $number)"` } `graphql:"repository(owner: $owner, name: $repo)"` } // Issue ൪߸ͷ഑ྻग़ྗ༻ channel ʹม׵ func toNumber(issues []Issue) <-chan int { out := make(chan int) go func() { for _, issue := range issues { out <- issue.IssueNumber } close(out) }() return out }
  11. // ੔ܗ͞Εͨจষͷग़ྗ༻ channel ʹม׵ func message(in <-chan int) <-chan string

    { out := make(chan string) go func() { for num := range in { args := map[string]interface{}{ "owner": githubql.String(owner), "repo": githubql.String(repo), "number": githubql.Int(num), } query := findIssue err := github.Query(context.Background(), &query, args) if err != nil { panic(err) } if issue := query.Repository.IssueOrPullRequest. IssueFragment; issue.Title != "" { out <- "#" + strconv.Itoa(num) + ": " + issue.Title + " : " + issue.Url } } close(out) }() return out } 解説ざっくり 3. Issue ID からタイトルとリンクを取得 & 文章整形