func()

in ccadb2OneCRL/main.go [477:595]


func (u *Updater) OpenBug() transaction.Transactor {
	u.bugID = -1
	return transaction.NewTransaction().WithCommit(func() error {
		// Human readable, line delimited, "issuer: %s serial: %s"
		issuerSerialPairs := ""
		proposedAdditions := make([]*onecrl.Record, 0)
		for _, record := range u.changes {
			issuerSerialPairs += fmt.Sprintf("issuer: %s serial: %s\n", record.IssuerName, record.SerialNumber)
			proposedAdditions = append(proposedAdditions, record)
		}
		// Try to read the environment variable that declares a list of Bugzilla accounts to put on CC.
		_cc, err := csv.NewReader(strings.NewReader(os.Getenv(BugzillaCcAccounts))).ReadAll()
		if err != nil {
			log.WithError(err).
				WithField("BugzillaCcAccounts", os.Getenv(BugzillaCcAccounts)).
				Error("the CC environment variable appears to be malformed")
			return err
		}
		// The CSV parser is always going to return a [][]string, but really
		// we only want the first "row".
		var cc []string = nil
		if len(_cc) > 0 {
			cc = _cc[0]
			log.WithField("CC", cc).Debug("using CC environment variable")
		}
		bug := &bugs.Create{
			Product:     "Core",
			Component:   "Security Block-lists, Allow-lists, and other State",
			Summary:     fmt.Sprintf("CCADB entries generated %s", time.Now().UTC().Format(time.RFC3339)),
			Version:     "unspecified",
			Severity:    "normal",
			Type:        "enhancement",
			Description: "Adding entries to OneCRL based on revoked intermediate certificates reported in the CCADB.",
			Cc:          cc,
		}
		log.WithField("payload", bug).Debug("sending bugzilla creation payload")
		resp, err := u.bugzilla.CreateBug(bug)
		if err != nil {
			log.WithError(err).Error("bugzilla create failed")
			return errors.WithStack(err)
		}
		log.WithField("id", resp.Id).
			WithField("url", u.bugzilla.ShowBug(resp.Id)).
			Debug("created bugzilla ticket")
		u.bugID = resp.Id
		for _, record := range u.changes {
			record.Details.Bug = u.bugzilla.ShowBug(u.bugID)
		}
		log.WithField("issuerSerialPairs", issuerSerialPairs).Debug("attempting to post issuer/serial pairs")
		_, err = u.bugzilla.CreateAttachment((&attachments.Create{
			BugId:       resp.Id,
			Data:        []byte(issuerSerialPairs),
			FileName:    "BugData.txt",
			Summary:     "Line delimited issuer/serial pairs",
			ContentType: "text/plain",
		}).AddBug(resp.Id))
		if err != nil {
			log.WithError(err).WithField("attachment", "BugData.txt").Warn(attachmentWarning)
		}
		additions, err := json.MarshalIndent(proposedAdditions, "", "  ")
		log.WithField("additions", proposedAdditions).Debug("attempting to post proposed OneCRL additions")
		if err != nil {
			return errors.WithStack(err)
		}
		_, err = u.bugzilla.CreateAttachment((&attachments.Create{
			BugId:       resp.Id,
			Data:        additions,
			FileName:    "OneCRLAdditions.txt",
			Summary:     "The additions to OneCRL proposed by this bug.",
			ContentType: "text/plain",
		}).AddBug(resp.Id))
		if err != nil {
			log.WithError(err).WithField("attachment", "OneCRLAdditions.txt").Warn(attachmentWarning)
		}
		comparisons := make([]interface{}, 0)
		for _, record := range u.changes {
			d, err := record.ToComparison()
			if err != nil {
				log.WithField("record", record).
					WithError(err).
					Error("failed to generate a OneCRL/CCADB comparison")
				return errors.WithStack(err)
			}
			comparisons = append(comparisons, d)
		}
		d, err := json.MarshalIndent(comparisons, "", "  ")
		if err != nil {
			return errors.WithStack(err)
		}
		log.WithField("comparison", comparisons).Debug("attempting to post OneCRL/CCADB comparison")
		_, err = u.bugzilla.CreateAttachment((&attachments.Create{
			BugId:       resp.Id,
			Data:        d,
			FileName:    "DecodedEntries.txt",
			Summary:     "Entries with their names decoded to plain text and hexadecimal serials/hashes.",
			ContentType: "text/plain",
		}).AddBug(resp.Id))
		if err != nil {
			log.WithError(err).WithField("attachment", "DecodedEntries.txt").Warn(attachmentWarning)
		}
		return nil
	}).WithRollback(func(cause error) error {
		if u.bugID == -1 {
			return nil
		}
		report := &strings.Builder{}
		logger := log.New()
		logger.SetFormatter(&log.JSONFormatter{PrettyPrint: true})
		logger.SetOutput(report)
		logger.WithError(cause).
			WithField("stacktrace", fmt.Sprintf("%+v", cause)). // "%+v" gets us a stack trace printed out
			Error("This tool experienced a fatal error downstream of posting this bug. This bug will be " +
				"closed. Please review the provided cause and call site of the cause for more information.")
		log.WithError(cause).WithField("bugzilla", u.bugzilla.ShowBug(u.bugID)).Error("closing the listed " +
			"bug due to a critical failure")
		_, err := u.bugzilla.UpdateBug(bugs.Invalidate(u.bugID, report.String()))
		return errors.WithStack(err)
	})
}