| Index: appengine/monorail/proto/tracker_pb2.py
|
| diff --git a/appengine/monorail/proto/tracker_pb2.py b/appengine/monorail/proto/tracker_pb2.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..00e546bedf0db4a37ba4488a02a4ab96f8435cf4
|
| --- /dev/null
|
| +++ b/appengine/monorail/proto/tracker_pb2.py
|
| @@ -0,0 +1,386 @@
|
| +# Copyright 2016 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is govered by a BSD-style
|
| +# license that can be found in the LICENSE file or at
|
| +# https://developers.google.com/open-source/licenses/bsd
|
| +
|
| +"""The Monorail issue tracker uses ProtoRPC for storing business objects."""
|
| +
|
| +from protorpc import messages
|
| +
|
| +
|
| +class FieldValue(messages.Message):
|
| + """Holds a single custom field value in an issue.
|
| +
|
| + Multi-valued custom fields will have multiple such FieldValues on a given
|
| + issue. Note that enumerated type custom fields are represented as key-value
|
| + labels.
|
| + """
|
| + field_id = messages.IntegerField(1, required=True)
|
| + # Only one of the following fields will hve any value.
|
| + int_value = messages.IntegerField(2)
|
| + str_value = messages.StringField(3)
|
| + user_id = messages.IntegerField(4, default=0)
|
| +
|
| + derived = messages.BooleanField(5, default=False)
|
| +
|
| +
|
| +class DanglingIssueRef(messages.Message):
|
| + """Holds a reference to an issue still on Google Codesite."""
|
| + project = messages.StringField(1, required=True)
|
| + issue_id = messages.IntegerField(2, required=True)
|
| +
|
| +
|
| +class Issue(messages.Message):
|
| + """Holds all the current metadata about an issue.
|
| +
|
| + The most frequent searches can work by consulting solely the issue metadata.
|
| + Display of the issue list is done solely with this issue metadata.
|
| + Displaying one issue in detail with description and comments requires
|
| + more info from other objects.
|
| +
|
| + The issue_id field is the unique primary key for retrieving issues. Local ID
|
| + is a small integer that counts up in each project.
|
| +
|
| + Summary, Status, Owner, CC, reporter, and opened_timestamp are hard
|
| + fields that are always there. All other metadata is stored as
|
| + labels or custom fields.
|
| + Next available tag: 54.
|
| + """
|
| + # Globally unique issue ID.
|
| + issue_id = messages.IntegerField(42)
|
| + # project_name is not stored in the DB, only the project_id is stored.
|
| + # project_name is used in RAM to simplify formatting logic in lots of places.
|
| + project_name = messages.StringField(1, required=True)
|
| + project_id = messages.IntegerField(50)
|
| + local_id = messages.IntegerField(2, required=True)
|
| + summary = messages.StringField(3, default='')
|
| + status = messages.StringField(4, default='')
|
| + owner_id = messages.IntegerField(5)
|
| + cc_ids = messages.IntegerField(6, repeated=True)
|
| + labels = messages.StringField(7, repeated=True)
|
| + component_ids = messages.IntegerField(39, repeated=True)
|
| +
|
| + # Denormalized count of stars on this Issue.
|
| + star_count = messages.IntegerField(8, required=True, default=0)
|
| + reporter_id = messages.IntegerField(9, required=True, default=0)
|
| + # Time that the issue was opened, in seconds since the Epoch.
|
| + opened_timestamp = messages.IntegerField(10, required=True, default=0)
|
| +
|
| + # This should be set when an issue is closed and cleared when a
|
| + # closed issue is reopened. Measured in seconds since the Epoch.
|
| + closed_timestamp = messages.IntegerField(12, default=0)
|
| +
|
| + # This should be updated every time an issue is modified. Measured
|
| + # in seconds since the Epoch.
|
| + modified_timestamp = messages.IntegerField(13, default=0)
|
| +
|
| + # Issue IDs of issues that this issue is blocked on.
|
| + blocked_on_iids = messages.IntegerField(16, repeated=True)
|
| +
|
| + # Issue IDs of issues that this issue is blocking.
|
| + blocking_iids = messages.IntegerField(17, repeated=True)
|
| +
|
| + # References to 'dangling' (still in codesite) issue relations.
|
| + dangling_blocked_on_refs = messages.MessageField(
|
| + DanglingIssueRef, 52, repeated=True)
|
| + dangling_blocking_refs = messages.MessageField(
|
| + DanglingIssueRef, 53, repeated=True)
|
| +
|
| + # Issue ID of issue that this issue was merged into most recently. When it
|
| + # is missing or 0, it is considered to be not merged into any other issue.
|
| + merged_into = messages.IntegerField(18)
|
| +
|
| + # Default derived via rules, used iff status == ''.
|
| + derived_status = messages.StringField(30, default='')
|
| + # Default derived via rules, used iff owner_id == 0.
|
| + derived_owner_id = messages.IntegerField(31, default=0)
|
| + # Additional CCs derived via rules.
|
| + derived_cc_ids = messages.IntegerField(32, repeated=True)
|
| + # Additional labels derived via rules.
|
| + derived_labels = messages.StringField(33, repeated=True)
|
| + # Additional notification email addresses derived via rules.
|
| + derived_notify_addrs = messages.StringField(34, repeated=True)
|
| + # Additional components derived via rules.
|
| + derived_component_ids = messages.IntegerField(40, repeated=True)
|
| +
|
| + # Soft delete of the entire issue.
|
| + deleted = messages.BooleanField(35, default=False)
|
| +
|
| + # Total number of attachments in the issue
|
| + attachment_count = messages.IntegerField(36, default=0)
|
| +
|
| + # Total number of comments on the issue (not counting the initial comment
|
| + # created when the issue is created).
|
| + comment_count = messages.IntegerField(37, default=0)
|
| +
|
| + # Custom field values (other than enums)
|
| + field_values = messages.MessageField(FieldValue, 41, repeated=True)
|
| +
|
| + is_spam = messages.BooleanField(51, default=False)
|
| +
|
| +
|
| +class FieldID(messages.Enum):
|
| + """Possible fields that can be updated in an Amendment."""
|
| + # The spelling of these names must match enum values in tracker.sql.
|
| + SUMMARY = 1
|
| + STATUS = 2
|
| + OWNER = 3
|
| + CC = 4
|
| + LABELS = 5
|
| + BLOCKEDON = 6
|
| + BLOCKING = 7
|
| + MERGEDINTO = 8
|
| + PROJECT = 9
|
| + COMPONENTS = 10
|
| + CUSTOM = 11
|
| +
|
| +
|
| +class Amendment(messages.Message):
|
| + """Holds info about one issue field change."""
|
| + field = messages.EnumField(FieldID, 11, required=True)
|
| + # User-visible string describing the change
|
| + newvalue = messages.StringField(12, required=True)
|
| + # Newvalue could have + or - characters to indicate that labels and CCs
|
| + # were added or removed
|
| + # Users added to owner or cc field
|
| + added_user_ids = messages.IntegerField(29, repeated=True)
|
| + # Users removed from owner or cc
|
| + removed_user_ids = messages.IntegerField(30, repeated=True)
|
| + custom_field_name = messages.StringField(31)
|
| + # When having newvalue be a +/- string doesn't make sense (e.g. status),
|
| + # store the old value here so that it can still be displayed.
|
| + oldvalue = messages.StringField(32)
|
| +
|
| +
|
| +class Attachment(messages.Message):
|
| + """Holds info about one attachment."""
|
| + attachment_id = messages.IntegerField(21, required=True)
|
| + # Client-side filename
|
| + filename = messages.StringField(22, required=True)
|
| + filesize = messages.IntegerField(23, required=True)
|
| + # File mime-type, or at least our best guess.
|
| + mimetype = messages.StringField(24, required=True)
|
| + deleted = messages.BooleanField(27, default=False)
|
| + gcs_object_id = messages.StringField(29, required=False)
|
| +
|
| +
|
| +class IssueComment(messages.Message):
|
| + """Holds one issue description or one additional comment on an issue.
|
| +
|
| + The IssueComment with the lowest timestamp is the issue description.
|
| + Next available tag: 52
|
| + """
|
| + id = messages.IntegerField(32)
|
| + # Issue ID of the issue that was commented on.
|
| + issue_id = messages.IntegerField(31, required=True)
|
| + project_id = messages.IntegerField(50)
|
| + # User who entered the comment
|
| + user_id = messages.IntegerField(4, required=True, default=0)
|
| + # Time when comment was entered (seconds).
|
| + timestamp = messages.IntegerField(5, required=True)
|
| + # Text of the comment
|
| + content = messages.StringField(6, required=True)
|
| + # Audit trail of changes made w/ this comment
|
| + amendments = messages.MessageField(Amendment, 10, repeated=True)
|
| +
|
| + # Soft delete that can be undeleted.
|
| + # Deleted comments should not be shown to average users.
|
| + # If deleted, deleted_by contains the user id of user who deleted.
|
| + deleted_by = messages.IntegerField(13)
|
| +
|
| + attachments = messages.MessageField(Attachment, 20, repeated=True)
|
| +
|
| + # TODO(jrobbins): Always store unescaped text and let EZT do the
|
| + # escaping on output. Then I can eliminate this.
|
| + was_escaped = messages.BooleanField(25, default=True)
|
| +
|
| + # Sequence number of the comment
|
| + # The field is optional for compatibility with code existing before
|
| + # this field was added.
|
| + sequence = messages.IntegerField(26)
|
| +
|
| + # The body text of the inbound email that caused this issue comment
|
| + # to be automatically entered. If this field is non-empty, it means
|
| + # that the comment was added via an inbound email. Headers and attachments
|
| + # are not included.
|
| + inbound_message = messages.StringField(28)
|
| +
|
| + is_spam = messages.BooleanField(51, default=False)
|
| +
|
| +class SavedQuery(messages.Message):
|
| + """Store a saved query, for either a project or a user."""
|
| + query_id = messages.IntegerField(1)
|
| + name = messages.StringField(2)
|
| + base_query_id = messages.IntegerField(3)
|
| + query = messages.StringField(4, required=True)
|
| +
|
| + # For personal cross-project queries.
|
| + executes_in_project_ids = messages.IntegerField(5, repeated=True)
|
| +
|
| + # For user saved queries.
|
| + subscription_mode = messages.StringField(6)
|
| +
|
| +
|
| +class NotifyTriggers(messages.Enum):
|
| + """Issue tracker events that can trigger notification emails."""
|
| + NEVER = 0
|
| + ANY_COMMENT = 1
|
| + # TODO(jrobbins): ANY_CHANGE, OPENED_CLOSED, ETC.
|
| +
|
| +
|
| +class FieldTypes(messages.Enum):
|
| + """Types of custom fields that Monorail supports."""
|
| + ENUM_TYPE = 1
|
| + INT_TYPE = 2
|
| + STR_TYPE = 3
|
| + USER_TYPE = 4
|
| + DATE_TYPE = 5
|
| + BOOL_TYPE = 6
|
| + # TODO(jrobbins): more types, see tracker.sql for all TODOs.
|
| +
|
| +
|
| +class FieldDef(messages.Message):
|
| + """This PB stores info about one custom field definition."""
|
| + field_id = messages.IntegerField(1, required=True)
|
| + project_id = messages.IntegerField(2, required=True)
|
| + field_name = messages.StringField(3, required=True)
|
| + field_type = messages.EnumField(FieldTypes, 4, required=True)
|
| + applicable_type = messages.StringField(11)
|
| + applicable_predicate = messages.StringField(10)
|
| + is_required = messages.BooleanField(5, default=False)
|
| + is_multivalued = messages.BooleanField(6, default=False)
|
| + docstring = messages.StringField(7)
|
| + is_deleted = messages.BooleanField(8, default=False)
|
| + admin_ids = messages.IntegerField(9, repeated=True)
|
| +
|
| + # validation details for int_type
|
| + min_value = messages.IntegerField(12)
|
| + max_value = messages.IntegerField(13)
|
| + # validation details for str_type
|
| + regex = messages.StringField(14)
|
| + # validation details for user_type
|
| + needs_member = messages.BooleanField(15, default=False)
|
| + needs_perm = messages.StringField(16)
|
| +
|
| + # semantics for user_type fields
|
| + grants_perm = messages.StringField(17)
|
| + notify_on = messages.EnumField(NotifyTriggers, 18)
|
| +
|
| +
|
| +class ComponentDef(messages.Message):
|
| + """This stores info about a component in a project."""
|
| + component_id = messages.IntegerField(1, required=True)
|
| + project_id = messages.IntegerField(2, required=True)
|
| + path = messages.StringField(3, required=True)
|
| + docstring = messages.StringField(4)
|
| + admin_ids = messages.IntegerField(5, repeated=True)
|
| + cc_ids = messages.IntegerField(6, repeated=True)
|
| + deprecated = messages.BooleanField(7, default=False)
|
| + created = messages.IntegerField(8)
|
| + creator_id = messages.IntegerField(9)
|
| + modified = messages.IntegerField(10)
|
| + modifier_id = messages.IntegerField(11)
|
| +
|
| +
|
| +class FilterRule(messages.Message):
|
| + """Filter rules implement semantics as project-specific if-then rules."""
|
| + predicate = messages.StringField(10, required=True)
|
| +
|
| + # If the predicate is satisfied, these actions set some of the derived_*
|
| + # fields on the issue: labels, status, owner, or CCs.
|
| + add_labels = messages.StringField(20, repeated=True)
|
| + default_status = messages.StringField(21)
|
| + default_owner_id = messages.IntegerField(22)
|
| + add_cc_ids = messages.IntegerField(23, repeated=True)
|
| + add_notify_addrs = messages.StringField(24, repeated=True)
|
| +
|
| +
|
| +class StatusDef(messages.Message):
|
| + """Definition of one well-known issue status."""
|
| + status = messages.StringField(11, required=True)
|
| + means_open = messages.BooleanField(12, default=False)
|
| + status_docstring = messages.StringField(13)
|
| + deprecated = messages.BooleanField(14, default=False)
|
| +
|
| +
|
| +class LabelDef(messages.Message):
|
| + """Definition of one well-known issue label."""
|
| + label = messages.StringField(21, required=True)
|
| + label_docstring = messages.StringField(22)
|
| + deprecated = messages.BooleanField(23, default=False)
|
| +
|
| +
|
| +class TemplateDef(messages.Message):
|
| + """Definition of one issue template."""
|
| + template_id = messages.IntegerField(57)
|
| + name = messages.StringField(31, required=True)
|
| + content = messages.StringField(32, required=True)
|
| + summary = messages.StringField(33)
|
| + summary_must_be_edited = messages.BooleanField(34, default=False)
|
| + owner_id = messages.IntegerField(35)
|
| + status = messages.StringField(36)
|
| + # Note: labels field is considered to have been set iff summary was set.
|
| + labels = messages.StringField(37, repeated=True)
|
| + # This controls what is listed in the template drop-down menu. Users
|
| + # could still select any template by editing the URL, and that's OK.
|
| + members_only = messages.BooleanField(38, default=False)
|
| + # If no owner_id is specified, and owner_defaults_to_member is
|
| + # true, then when an issue is entered by a member, fill in the initial
|
| + # owner field with the signed in user's name.
|
| + owner_defaults_to_member = messages.BooleanField(39, default=True)
|
| + admin_ids = messages.IntegerField(41, repeated=True)
|
| +
|
| + # Custom field values (other than enums)
|
| + field_values = messages.MessageField(FieldValue, 42, repeated=True)
|
| + # Components.
|
| + component_ids = messages.IntegerField(43, repeated=True)
|
| + component_required = messages.BooleanField(44, default=False)
|
| +
|
| +
|
| +class ProjectIssueConfig(messages.Message):
|
| + """This holds all configuration info for one project.
|
| +
|
| + That includes canned queries, well-known issue statuses,
|
| + and well-known issue labels.
|
| +
|
| + "Well-known" means that they are always offered to the user in
|
| + drop-downs, even if there are currently no open issues that have
|
| + that label or status value. Deleting a well-known value from the
|
| + configuration does not change any issues that may still reference
|
| + that old label, and users are still free to use it.
|
| +
|
| + Exclusive label prefixes mean that a given issue may only have one
|
| + label that begins with that prefix. E.g., Priority should be
|
| + exclusive so that no issue can be labeled with both Priority-High
|
| + and Priority-Low.
|
| + """
|
| +
|
| + project_id = messages.IntegerField(60)
|
| + well_known_statuses = messages.MessageField(StatusDef, 10, repeated=True)
|
| + # If an issue's status is being set to one of these, show "Merge with:".
|
| + statuses_offer_merge = messages.StringField(14, repeated=True)
|
| +
|
| + well_known_labels = messages.MessageField(LabelDef, 20, repeated=True)
|
| + exclusive_label_prefixes = messages.StringField(2, repeated=True)
|
| +
|
| + field_defs = messages.MessageField(FieldDef, 5, repeated=True)
|
| + component_defs = messages.MessageField(ComponentDef, 6, repeated=True)
|
| +
|
| + templates = messages.MessageField(TemplateDef, 30, repeated=True)
|
| +
|
| + default_template_for_developers = messages.IntegerField(3, required=True)
|
| + default_template_for_users = messages.IntegerField(4, required=True)
|
| +
|
| + # These options control the default appearance of the issue list or grid.
|
| + default_col_spec = messages.StringField(50, default='')
|
| + default_sort_spec = messages.StringField(51, default='')
|
| + default_x_attr = messages.StringField(52, default='')
|
| + default_y_attr = messages.StringField(53, default='')
|
| +
|
| + # This bool controls whether users are able to enter odd-ball
|
| + # labels and status values, or whether they are limited to only the
|
| + # well-known labels and status values defined on the admin subtab.
|
| + restrict_to_known = messages.BooleanField(16, default=False)
|
| +
|
| + # Allow special projects to have a custom URL for the "New issue" link.
|
| + custom_issue_entry_url = messages.StringField(56)
|
|
|