Guide
Mutations
Mutations should be used to modify database content. We implemented a set of operations based on automation's actions. These operations can be performed one by one for created or filtered database's entities. In other words multiple actions can be executed for added entities or selected by filtering arguments.
Find below the syntax of mutation. Filter argument to select entities for modification is the same as defined for find query. Every action has the result. It is a message about action execution, affected entities.
mutation {
database(filter) {
action1(args){message,entities{id,type}}
action2(args){message,entities{id,type}}
...
actionN(args){message,entities{id,type}}
}
}
The operations can not be duplicated inside mutation. Batch alternative of action can be used in case multiple arguments supposed to be performed for the same action. Batch action data argument is an array of actions' arguments.
#Single command
action(arguments){message}
#Batch command
actionBatch(data:[arguments]){message}
The available database actions or operations can be found in Docs → Mutation.
Example of creating entity and appending content to its rich field
mutation{
bugs{
create(name: "New Bug"){message}
appendContentToStepsToReproduce(value: "TBD"){message}
}
}
Output:
{
"data": {
"bugs": {
"create": {
"message": "Create: 1 Bug added"
},
"appendContentToStepsToReproduce": {
"message": "Append content to Steps To Reproduce: Steps To Reproduce updated for 1 Bug"
}
}
}
}
Example of closing bugs with name "New Bug" and notifying assignees using text template
mutation{
bugs(name:{is:"New Bug"}){
moveToFinalState{message}
notifyAssignees(subject:"{{Name}} bug was closed"){message}
}
}
Output
{
"data": {
"bugs": {
"moveToFinalState": {
"message": "Move to final state executed"
},
"notifyAssignees": {
"message": "Notify Assignees: 0 notifications sent"
}
}
}
}
Create
New entities can be added to database using create or createBatch. The arguments of these actions native database fields. One-to-one fields and inner list items also can be linked.
Create one release and link all bugs in "To Do" state
mutation {
releases {
create(
name: "Urgent"
bugs: {
state:{ name: {is:"To Do"}}
}
)
{
entities {
id
type
}
}
}
}
Output
{
"data": {
"releases": {
"create": {
"entities": [
{
"id": "13114b4a-fa4b-400a-8da3-257cef0e22f5",
"type": "Software Development/Release"
}
]
}
}
}
}
Create several bugs in different states, assign to current user and add comment
mutation {
bugs{
createBatch(data:[
{name: "Login failure", state:{name:{is:"In Progress"}}}
{name: "Design is br0ken", state:{name:{is:"To Do"}}}
]){message}
assignToMe{message}
addComment(value:"I will fix this bug ASAP"){message}
}
}
Output
{
"data": {
"bugs": {
"createBatch": {
"message": "Create: 2 Bugs added"
},
"assignToMe": {
"message": "Assign to me: User(s) assigned to 2 Bugs"
},
"addComment": {
"message": "Add comment: Comments added to 2 Bugs"
}
}
}
}
Update
Use update action if it is required to modify some fields or relations. The database mutation filter argument for selection entities should be provided for actions like update.
Change effort and release of bugs in "To Do" with effort equals to 15
mutation {
bugs(effort:{is: 15}, state:{name:{is:"To Do"}}){
update(
release:{name:{is:"1.0"}}
effort: 10
){entities{id}}
countOfEntities #count of found bugs
}
}
Output
{
"data": {
"bugs": {
"update": {
"entities": [
{
"id": "fa39df10-912b-11eb-a0bf-cb515797cdf8"
},
{
"id": "f42d7db6-6c6f-429d-bf5c-c60b0d9d072d"
},
{
"id": "fb670021-4fe6-4489-86b4-8a17e60e9227"
}
]
},
"countOfEntities": 3
}
}
}
Delete
Use delete action to remove entities which satisfy provided criterion. Be careful with this command and verify that only required entities are going to be deleted by using find command before execute delete.
Verify entities to be deleted using listEntities or countOfEntities
mutation {
bugs(state:{name:{is:"Done"}}){
listEntities{id}
countOfEntities
}
}
Proceed with delete
mutation {
bugs(state:{name:{is:"Done"}}){
delete{message}
}
}
Output
{
"data": {
"bugs": {
"delete": {
"message": "Delete: 4 Bugs deleted"
}
}
}
}
Create and link relations
Related one-to-one, one-to-many or many-to-many entities can be created using AddRelation or AddRelationItem actions.
Mind using GraphQL aliases to have convenient names in output
mutation {
releases{
release: create(name: "3.0.1"){entities{id,type}}
tasks: addTasksItemBatch(data:[
{name:"Do design"}
{name:"Do development"}
]){entities{id,type}}
bugs: addBugsItemBatch(data:[
{name:"Fix design"}
{name:"Fix development"}
{name:"Remove code"}
]){entities{id,type}}
}
}
Output
{
"data": {
"releases": {
"release": {
"entities": [
{
"id": "c09b246b-3e47-49fa-9a28-94438dc640c3",
"type": "Software Development/Release"
}
]
},
"tasks": {
"entities": [
{
"id": "e9ddd110-e8ac-11ec-a77e-d74e2f66036c",
"type": "Software Development/Task"
},
{
"id": "e9f095c0-e8ac-11ec-a77e-d74e2f66036c",
"type": "Software Development/Task"
}
]
},
"bugs": {
"entities": [
{
"id": "ea19a190-e8ac-11ec-a77e-d74e2f66036c",
"type": "Software Development/bug"
},
{
"id": "ea290ae0-e8ac-11ec-a77e-d74e2f66036c",
"type": "Software Development/bug"
},
{
"id": "ea3a48f0-e8ac-11ec-a77e-d74e2f66036c",
"type": "Software Development/bug"
}
]
}
}
}
}
Rich Text fields
There are some additional actions which may be handy in modifying rich fields and generating PDFs.
Rich fields can be modified by actions started from appendContent, overwriteContent, prependContent. attachPdfUsingTemplate can be used for generating PDF files.
The templating capabilities can be used in the same way it is available in automations.
mutation {
bugs(assignees:{containsAny:{email:{contains:"oleg"}}}){
appendContentToStepsToReproduce(value:"Line for state: {{State.Name}}"){message}
attachPdfUsingTemplate(value:"{{CurrentUser.Email}} is an author"){message}
}
}
Here is the result of the mutations:
Unlink/Link relations
Relations can be linked or unlinked using link<Relation Name> or unlink<Relation Name> actions.
mutation {
bugs(release:{id:{isNull:false}}){
unlinkRelease{message}
}
}
Output
{
"data": {
"bugs": {
"unlinkRelease": {
"message": "Unlink Release: Release unlinked from 12 Bugs"
}
}
}
}
Link bugs with effort greater than 5 to empty release
mutation {
releases(name:{is:"3.0"}){
linkBugs(effort:{greater:5}){message}
}
}
Unlink bugs with effort greater than 15 from release
mutation {
releases(bugs:{isEmpty:false}){
unlinkBugs(effort:{greaterOrEquals:15}){message}
}
}
Delete relations
Relations can be removed from system by executing delete<Relation Name>. Again be careful with this operation since the data will be erased.
Delete release from bugs with release
mutation {
bugs(release:{id:{isNull:false}}){
deleteRelease{message}
}
}
Delete bug items in "Done" state from selected release
mutation {
releases(bugs: {isEmpty:false}){
deleteBugs(state:{name:{is: "Done"}}){message}
}
}
Send notifications via GraphQL
The build-in notifications can be sent using NotifyUsers and other actions related to notifications like it is done for automatons. Text templates are supported.
Text templates have the same capabilities as Markdown Templates excluding support of Markdown Syntax, in other words it is just a text.
mutation {
bugs(release:{id:{isNull:false}}){
notifyCreatedBy(subject: "Please take a look"){message}
notifyAssignees(
subject: "Fix ASAP"
message: "Fix bug {{Name}} ASAP"
){message}
notifyUsers(
to:{email:{contains:"oleg"}}
message: "Waiting for fix..."
){message}
}
}
Add file from URL
The file can be attached to entities by using addFileFromUrl action.
mutation {
bugs(release:{id:{isNull:false}}){
addFileFromUrl(
name: "Super File"
url:"https://api.fibery.io/images/logo.svg"
){message}
}
}
How to avoid timeouts
Request (server) timeouts can be a problem for long-running tasks.
We propose several ways to avoid it:
Run mutations as background job
Use paging for mutations to reduce amount of data to be processed.
Use background jobs
There is a possibility in our GraphQL API to execute long-running actions in background. Huge set of operations with large amount of data can be executed as background jobs.
The following steps should be used:
Start executing mutations as background job
Monitor the status of job execution via executing job query. There are three statuses: EXECUTING, FAILED and COMPLETED
Execute job query again if status still equals to EXECUTING
actions will be populated with data when job status equals to COMPLETED
The job results will be available in ~30 minutes.
Start background job defining actions to be executed in background
mutation{
features{
executeAsBackgroundJob{
jobId
actions{
createBatch(data:[
{name: "Feature 1"}
{name: "Feature 2"}
]){message}
}
}
}
}
The result contains jobId to monitor job status
{
"data": {
"features": {
"executeAsBackgroundJob": {
"jobId": "6fc2d2b3-7b31-4511-b829-99a8cefb36b3",
"actions": null
}
}
}
}
Monitor job status using jobId
{
job(id:"6fc2d2b3-7b31-4511-b829-99a8cefb36b3"){
status
message
actions{
actionName
result{
message
entities{id}
}
}
}
}
The actions will be populated when status equals to "COMPLETED"
{
"data": {
"job": {
"status": "COMPLETED",
"message": "Completed successfully",
"actions": [
{
"actionName": "createBatch",
"result": {
"message": "Create: 2 Features added",
"entities": [
{
"id": "9d7deab7-a72d-4e09-adde-f888ca455fbe"
},
{
"id": "2c8f16ce-c9b6-4273-b74e-7e924a308a1f"
}
]
}
}
]
}
}
}
Use paging for mutations
Use limit, offset and orderBy in case of executing huge operational sets since it is required a lot of processing time and timeouts may be a problem. Please find an example on how to set sprint to stories by execution of the mutation with limit several times to avoid facing timeout. The main idea to update limited set of database until it has records which should be updated. In our case we are updating stories until some of them don't have sprint.
Execute mutation with limit for first time:
mutation{
stories(limit:10, sprint:{id:{isNull:true}}){
update(sprint:{limit:1, orderBy:{dates:{start:ASC}}}){message}
countOfEntities
}
}
Result contains 10 entities. So we will need to execute it again.
{
"data": {
"stories": {
"update": {
"message": "Update: 10 Stories updated"
},
"countOfEntities": 10
}
}
}
Execute the same mutation again with the same limit:
mutation{
stories(limit:10, sprint:{id:{isNull:true}}){
update(sprint:{limit:1, orderBy:{dates:{start:ASC}}}){message}
countOfEntities
}
}
Looks like no need to execute again since count of processed less than limit (10)
{
"data": {
"stories": {
"update": {
"message": "Update: 4 Stories updated"
},
"countOfEntities": 4
}
}
}