blob: db6da1132f89a7603db46ad03c7e873bdf8a3154 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is a thin wrapper around the Monorail API. It's specifically intended
// for use by the fuchsia roller, which needs to open a monorail issue for every
// failed roll that leads to a tree closure.
// TODO(olivernewman): Have the tree status app file tree closure bugs itself,
// and then delete this code.
package main
import (
type stringSlice []string
func (s *stringSlice) String() string {
return strings.Join([]string(*s), ",")
func (s *stringSlice) Set(value string) error {
*s = append(*s, value)
return nil
func main() {
newIssueCmd := flag.NewFlagSet("new-issue", flag.ExitOnError)
project := newIssueCmd.String("project", "fuchsia", "monorail project name")
summary := newIssueCmd.String("summary", "", "title of the issue")
description := newIssueCmd.String("description", "", "issue body text")
var cc, components, labels stringSlice
newIssueCmd.Var(&cc, "cc", "email addresses to add to CC")
newIssueCmd.Var(&components, "component", "components to add")
newIssueCmd.Var(&labels, "label", "labels to add")
if len(os.Args) < 2 {
log.Fatalf("expected subcommand")
switch os.Args[1] {
case newIssueCmd.Name():
err := createNewIssue(*project, *summary, *description, cc, components, labels)
if err != nil {
log.Fatalf("failed to create issue: %s", err)
log.Fatalf("invalid subcommand: %q", os.Args[1])
func createNewIssue(project, summary, description string, cc, components, labels stringSlice) error {
mr, err := monorail.NewIssueTrackerFromLUCIContext(project)
if err != nil {
return err
ccPeople := make([]monorail.IssuePerson, len(cc))
for i, email := range cc {
ccPeople[i] = monorail.IssuePerson{Name: email}
req := monorail.IssueRequest{
Summary: summary,
Description: description,
CC: ccPeople,
Components: components,
Status: "New",
Labels: labels,
resp, err := mr.AddIssue(req)
if err != nil {
return err
output, err := json.Marshal(resp)
if err != nil {
return err
return nil