Object Customization
This functionality is in Beta. It is not recommended for use in production applications.
DevRev allows you to customize its core objects such as issue and ticket to fit your organization’s unique workflows and reporting needs. By using the customization framework, you can extend these objects with custom fields that reflect your processes.
This guide provides an overview of the customization framework and walks you through the process of tracking bugs in your organization. By the end of this guide, you’ll be able to:
- Customize DevRev objects such as issue and ticket.
- Create custom stages and stage transition diagrams for your objects.
- Create dependent fields for your objects.
Concepts
Schema fragment
DevRev objects are customized using schema fragments. A fragment is a building block that defines a specific set of custom fields. When creating or updating an object record, multiple schema fragments can be combined to determine the full set of custom fields available for that record. The term fragment is used because each schema fragment contributes a portion of the overall object schema.
Tenant custom field
Tenant custom fields allow extending the DevRev objects by adding new fields. These custom fields are applied to all records of the specified object type within the organization. For example, a release notes tenant custom field for issue is applicable to all issue records in the organization.
Tenant custom fields are defined in a schema fragment of type tenant_fragment
.
Subtype
Subtypes are kinds of DevRev object types. They inherit all fields from the parent type and can include additional specific fields. For example, a bug subtype of issue would have all issue fields plus bug-specific fields like RCA.
Subtypes are defined using a schema fragment of type custom_type_fragment
.
Customizing a DevRev object
Let’s say you want to track bugs across various environments in your organization.
First, create a schema fragment defining the fields for the bug subtype.
Make sure to replace <TOKEN>
with your API token.
Let’s say a bug has been identified in the Prod environment. The person who reported the anomaly creates a bug-flavored issue object to track it and assigns a relevant owner.
After resolving the bug, the developer can update the issue object with release notes. Adding release notes provides a clear record of what was deployed to resolve the bug which can be valuable for future reference and communication with stakeholders.
To add release notes for the completed work, you can create a tenant custom field for the issue.
Since release notes are relevant to all issues, a tenant custom field is used instead of a subtype-specific field.
Populate the release notes in the issue object created above:
The final issue object now looks as follows:
The following observations can be made from the above example:
- The custom fields defined by different fragments are held in different namespaces in an object.
- Subtype fields are of the form
ctype__<field_name>
. - Tenant fields are of the form
tnt__<field_name>
.
- Subtype fields are of the form
- References to each fragment are stored with the object.
- When updating an object, the
custom_schema_spec
can specify only the fragments being modified. Here, only the tenant fragment is specified as only the release notes field is being updated.
Supported custom field types
The following custom field types are supported -
The list variants of all the supported custom field types are also supported. For
example, []int
, []tokens
, etc.
Schema fragment versioning
Schema fragments are immutable. When evolving a fragment:
- A new fragment is created and chained to the older one.
- The older fragment remains intact.
- Objects referencing the older fragment are unaffected (more on this later).
The same API endpoint schemas.custom.set
is used to create and update fragments. The
API internally figures out how to version and chain the fragments.
Let’s say you want to add a new boolean field customer_impact to the bug subtype and delete the regression field.
The API call to add the new field and delete the old field is shown below:
Note that:
- The API payload reflects the entire state of the new fragment version.
- The
deleted_fields
array specifies the field names that are being deleted. If not provided, the API call fails due to the lack of an explicit field deletion confirmation. This prevents accidental field deletions.
The above API call internally performs the following steps:
- Creates a new fragment with the specified payload.
- Updates the new fragment to point to the previous fragment. The
old_fragment_ref
system field in the new fragment points to the previous fragment. - Updates the old fragment to point to the new fragment. The
new_fragment_ref
system field in the old fragment points to the new fragment.
The diagram below shows the relationship between the fragments and how the versioning scheme preserves the referential integrity.
Object upgrades
A natural question arises at this point: what happens to the objects referencing the old fragment version?
The object get and list APIs automatically upgrade the object in-memory to the latest fragment version when queried. The necessary field adjustments are done in this process. In the example above, when the object referencing the old fragment is read, the regression field is dropped in the response.
The object now references the latest fragment version (custom_type_fragment/2
). While
the optional release notes field is absent, the tenant fragment remains attached,
allowing for future tenant-specific field additions.
Deprecating a custom schema fragment
Custom schema fragments can be deprecated to avoid creating work items using them. The
following POST request payload to schemas.custom.set
can be used:
Listing custom schema fragments
The following API call can be used to list all the custom schema fragments in your organization:
Deprecated fragments aren’t listed in the response.
UI hints
UI hints allow customizing the UI/UX of custom fields. So far, ui.display_name
has
been used to set the display name of a field. Let’s look at the other supported UI
hints:
display_name
: The display name of the field.is_hidden
: Whether the field is hidden.placeholder
: The placeholder text for the field.is_sortable
: Whether the field is sortable. Requiresis_filterable
to be true.is_groupable
: Whether the field is groupable. Requiresis_filterable
to be true.
is_filterable
is not a UI hint but a top level field property.
Stock field overrides
The fields available in native DevRev objects are called stock fields. For example,
priority
is a stock field of issue.
Let’s say you want to do the following modifications to the priority field in your organization:
- Update the UI display name from Priority to Urgency Level.
- Update the allowed values from P0, P1, P2, and P3 to Low, Medium, High, and Blocker.
Since the modification is applicable to all issues, you can create a tenant schema fragment with the following payload:
A few observations can be made from the above payload:
- The
stock_field_overrides
array contains the overrides for the stock fields. - The
name
field in the override specifies the stock field to be overridden. - The
uenum_values
array contains the new allowed values for the stock field. - Each allowed value in the
uenum_values
array must have a uniqueid
. Since labels can change, theid
is used to identify the value. - The
ordinal
field is used to determine the sort order of the values. - The
ui.display_name
field updates the display name of the stock field.
If you want the overrides to be scoped to a subtype, you can add them to the subtype instead.
Stage customization
Stages represent the different phases an object can be in during its lifecycle. For example, an issue might go through the following lifecycle:
Customizing the stages allows you to tailor the object lifecycle to your organization’s specific requirements.
A state is a group of stages. For example, the open state groups the triage, backlog, and prioritized stages. By default, DevRev creates open, in_progress, and closed states in your organization.
Let’s say you want to add a new stage Needs RCA to the bug subtype.
Adding a custom stage
A stage can be referenced by any object type. For example, both issue and ticket object types can use the in_development stage. It’s incorrect to say that the stage is bound to an issue or ticket.
Stage diagram
A stage diagram determines the allowed transitions between stages for a given object. For example, triage stage can transition to backlog stage but not vice versa.
Let’s create a stage diagram for the bug subtype:
It is important to specify the start stage for the diagram. This is the default stage that gets assigned to the newly created objects.
Using a stage diagram
The stage diagram created above can be referenced in the bug subtype as follows:
All objects of the bug subtype now adhere to the stage diagram created above.
Dependent fields
Let’s say that the developers in your organization tend to forget to add an RCA when resolving the bugs. You can make the RCA field required when a bug object is moved to the completed stage by adding a dependent field constraint.
Any attempt to update a bug object to the completed stage without populating the RCA field is rejected.
The supported operators are ==
, !=
, >
, >=
, <
, <=
. The expression
is a
boolean expression that must return a boolean value.
The effects
array contains the list of effects of the condition. The following effects are supported:
require
: Whether the field must be set for the condition to be met.show
: Whether the field must be shown for the condition to be met.allowed_values
: The conditional allowed values for the enum type field.
don:core:dvrv-us-1:devo/test:stage/5
is the ID of the completed stage. The
stage display name is not used in the expression because it is liable to change.