In this page

Transitioning an issue to "In Progress" automatically

This automation moves an issue from the "To Do" status to "In Progress" when a new VCS commit is created linked to it.

It updates the issue status automatically if the developer forgets to do that after he has started working on the issue.

Configuration

  1. Login to Jira as admin, go to AdministrationSystemAutomation rules.
  2. Click Create rule.
  3. Select the trigger Commit created (from the DevOps category).
  4. Click Save.
  5. Click New action.
  6. Select the action Run Groovy script.
    1. Enter "Transition issue to "In Progress" as committer" to the Description field.
    2. Enter this Groovy script:
      import com.atlassian.jira.component.ComponentAccessor
      
      def issueService = ComponentAccessor.issueService
      
      if (!issues) {
      	return
      }
      
      def sourceStatusId = jiraHelper.getStatusByName("To Do").id
      def targetStatusId = jiraHelper.getStatusByName("In Progress").id
      
      def author = devops.committerByUsername ?: {throw new IllegalArgumentException("No user found with username \"${devops.commit.username}\"")}()
      // def author = devops.committerByEmailAddress ?: {throw new IllegalArgumentException("No user found with email address \"${devops.commit.emailAddress}\"")}() // (alternative, see the Smart Value Reference!)
      
      issues.forEach { issue ->
      	if (issue.status.id != sourceStatusId) {
      		return
      	}
      	try {
      		def transitionId = jiraHelper.getTransitionByTargetStatus(issue.key, Long.valueOf((String) targetStatusId)).transitionId
      
      		def validationResult = issueService.validateTransition(author, issue.id, transitionId as int, issueService.newIssueInputParameters())
      		if (validationResult.isValid()) {
      			def issueResult = issueService.transition(author, validationResult)
      			if (issueResult.issue.status.id == targetStatusId) {
      				auditLog.info("${issue.key} transitioned to <${issueResult.issue.status.name}>")
      			} else {
      				auditLog.error("${issue.key} not transitioned! (check the workflow configuration!)")
      			}
      		} else {
      			(validationResult.errorCollection.errors.collect { "<${it.key}> field error: ${it.value}" } + validationResult.errorCollection.errorMessages).each { auditLog.error(it) }
      		}
      	} catch (Exception e) {
      		auditLog.error(e.message ?: "${e} ${e.stackTrace}")
      	}
      }
      
  7. Click Save.
  8. Click Add component and select New condition.
  9. Select the condition Issue fields condition.
    1. Select Status from the Field dropdown.
    2. Select equals from the Condition dropdown.
    3. Select "To Do" from the Value dropdown.
  10. Click Save.
  11. Click New action.
  12. Select the action Transition issue.
    1. Select the Selecting the destination status option.
    2. Set "In Progress" as destination status.
  13. Click Save.
  14. Name your automation rule intuitively, and click Turn it on.

Usage

  1. Create a commit with this commit message:
    Add a unit test to reproduce the FOO-1 bug.
  2. The status of the issue FOO-1 will change to "In Progress".

Troubleshooting

If you don't get the expected results:

  1. Check if a transition from the status "To Do" to "In Progress" exists?
  2. See the general troubleshooting steps.

Transitioning an issue to "Done" if the commit message contains "fix", "fixes" or "fixed"

This automation moves an issue to the status "Done" when a new VCS commit is created linked to it and its commit message contains "fix", "fixes" or "fixed" case-insensitively.

It updates the issue status automatically if the developer forgets to do that after he has resolved the issue. Note that this recipe can also be used for other automations that rely on checking keywords in the commit message.

Configuration

  1. Login to Jira as admin, go to AdministrationSystemAutomation rules.
  2. Click Create rule.
  3. Select the trigger Commit created (from the DevOps category).
  4. Click Save.
  5. Click Add component and select New condition.
  6. Select the condition Advanced compare condition.
    1. Enter {{devops.commit.message}} to the First value field.
    2. Choose the contains regular expression option from the Condition dropdown.
    3. Enter (?si)(\bfix\b|\bfixes\b|\bfixed\b) to the Second value field.
  7. Click Save.
  8. Click New action.
  9. Select the action Run Groovy script.
    1. Enter "Transition issue to "Done" as committer" to the Description field.
    2. Enter this Groovy script:
      import com.atlassian.jira.component.ComponentAccessor
      
      def issueService = ComponentAccessor.issueService
      
      if (!issues) {
      	return
      }
      
      def sourceStatusId = jiraHelper.getStatusByName("In Progress").id
      def targetStatusId = jiraHelper.getStatusByName("Done").id
      
      def author = devops.committerByUsername ?: {throw new IllegalArgumentException("No user found with username \"${devops.commit.username}\"")}()
      // def author = devops.committerByEmailAddress ?: {throw new IllegalArgumentException("No user found with email address \"${devops.commit.emailAddress}\"")}() // (alternative, see the Smart Value Reference!)
      
      issues.forEach { issue ->
      	if (issue.status.id != sourceStatusId) {
      		return
      	}
      	try {
      		def transitionId = jiraHelper.getTransitionByTargetStatus(issue.key, Long.valueOf((String) targetStatusId)).transitionId
      
      		def validationResult = issueService.validateTransition(author, issue.id, transitionId as int, issueService.newIssueInputParameters())
      		if (validationResult.isValid()) {
      			def issueResult = issueService.transition(author, validationResult)
      			if (issueResult.issue.status.id == targetStatusId) {
      				auditLog.info("${issue.key} transitioned to <${issueResult.issue.status.name}>")
      			} else {
      				auditLog.error("${issue.key} not transitioned! (check the workflow configuration!)")
      			}
      		} else {
      			(validationResult.errorCollection.errors.collect { "<${it.key}> field error: ${it.value}" } + validationResult.errorCollection.errorMessages).each { auditLog.error(it) }
      		}
      	} catch (Exception e) {
      		auditLog.error(e.message ?: "${e} ${e.stackTrace}")
      	}
      }
      
  10. Click Save.
  11. Click Add component and select New condition.
  12. Select the condition Issue fields condition.
    1. Select Status from the Field dropdown.
    2. Select equals from the Condition dropdown.
    3. Select "In Progress" from the Value dropdown.
  13. Click Save.
  14. Click New action.
  15. Select the action Transition issue.
    1. Select the Selecting the destination status option.
    2. Set "Done" as destination status.
  16. Click Save.
  17. Name your automation rule intuitively, and click Turn it on.

Usage

  1. Create a commit with this commit message:
    Fix the FOO-1 bug.
  2. The status of the issue FOO-1 will change to "Done".

Troubleshooting

If you don't get the expected results:

  1. Check if a transition from the status "In Progress" to "Done" exists?
  2. See the general troubleshooting steps.

Transitioning an issue to another status

This automation moves an issue to another status and optionally updates the issue's resolution by parsing the status name and the resolution name from the VCS commit message:

It is an extended variant of the previous automation that allows choosing both the target status and the resolution.

Configuration

  1. Login to Jira as admin, go to AdministrationSystemAutomation rules.
  2. Click Create rule.
  3. Select the trigger Genius Commit created (from the DevOps category).
  4. Choose the command Set issue status, and click Save.
  5. Click New action.
  6. Select the action Run Groovy script.
    1. Enter "Execute transition as committer" to the Description field.
    2. Enter this Groovy script:
      import com.atlassian.jira.component.ComponentAccessor
      
      def issueService = ComponentAccessor.issueService
      
      if (!issues) {
      	return
      }
      
      def statusId = jiraHelper.getStatusByName(devops.status).id
      def resolutionId = devops.resolution ? jiraHelper.getResolutionByName(devops.resolution).id : null
      
      def author = devops.committerByUsername ?: {throw new IllegalArgumentException("No user found with username \"${devops.commit.username}\"")}()
      // def author = devops.committerByEmailAddress ?: {throw new IllegalArgumentException("No user found with email address \"${devops.commit.emailAddress}\"")}() // (alternative, see the Smart Value Reference!)
      
      issues.forEach { issue ->
      	if (issue.status.id == statusId &&
      		(!resolutionId || issue.resolution?.id == resolutionId)) {
      		return
      	}
      	try {
      		def transitionId = jiraHelper.getTransitionByTargetStatus(issue.key, Long.valueOf((String) statusId)).transitionId
      
      		def issueParams = issueService.newIssueInputParameters()
      		if (resolutionId) {
      			issueParams.setResolutionId(resolutionId)
      		}
      
      		def validationResult = issueService.validateTransition(author, issue.id, transitionId as int, issueParams)
      		if (validationResult.isValid()) {
      			def issueResult = issueService.transition(author, validationResult)
      			if (issueResult.issue.status.id == statusId) {
      				def resolutionInfo = resolutionId ? " and resolution <${issueResult.issue.resolution.name}>" : ""
      				auditLog.info("${issue.key} transitioned to <${issueResult.issue.status.name}>${resolutionInfo}")
      			} else {
      				auditLog.error("${issue.key} not transitioned! (check the workflow configuration!)")
      			}
      			if (resolutionId && (issueResult.issue.resolution?.id != resolutionId)) {
      				auditLog.error("${issue.key} resolution not changed! (check the workflow configuration!)")
      			}
      		} else {
      			(validationResult.errorCollection.errors.collect { "<${it.key}> field error: ${it.value}" } + validationResult.errorCollection.errorMessages).each { auditLog.error(it) }
      		}
      	} catch (Exception e) {
      		auditLog.error(e.message ?: "${e} ${e.stackTrace}")
      	}
      }
      
  7. Click Save.
  8. Click New action.
  9. Select the action Transition issue.
    1. Select the Selecting the destination status option.
    2. Click inside the Destination status field and enter {{jiraHelper.getStatusByName(devops.status).id}}.
    3. Click More options.
    4. Enter the following content in the Additional fields:
      {
      	{{#stringHelper.trimToNull(devops.resolution)}}
      		"fields": {
      			"resolution": {
      				"id": "{{jiraHelper.getResolutionByName(devops.resolution).id}}"
      			}
      		}
      	{{/}}
      }
      
  10. Click Save.
  11. Name your automation rule intuitively, and click Turn it on.

Usage

Status only
  1. Create a commit with this commit message:
    Protect against the null value that caused the FOO-1 bug. @status Done
  2. The status of the issue FOO-1 will change to "Done".
Status and resolution
  1. Create a commit with this commit message:
    Protect against the null value that caused the FOO-1 bug. @status Done/Fixed
    Note the status name and the resolution name separated with /.
  2. The status of the issue FOO-1 will change to "Done" and its resolution will change to "Fixed".

Troubleshooting

If you don't get the expected results:

  1. Check if the @status command is defined in the Genius Commands screen? (It's a default command.)
  2. Check if the @status command followed by the status name and optionally the resolution name was included in the commit message?
  3. Check if the status with that name exists?
  4. Check if the resolution with that name exists?
  5. Check if either a transition from the issue's source status to the target status or a global transition to the target status exists (which allows every other status to transition to it)?
  6. See the general troubleshooting steps.

Transitioning an issue by executing a transition

This automation executes a transition on an issue and optionally updates the issue's resolution by parsing the transition name and the resolution name from the VCS commit message.

It is a variant of the previous automation that allows choosing the transition instead of the target status.

Configuration

  1. Login to Jira as admin, go to AdministrationSystemAutomation rules.
  2. Click Create rule.
  3. Select the trigger Genius Commit created (from the DevOps category).
  4. Choose the command Transition issue, and click Save.
  5. Click New action.
  6. Select the action Run Groovy script.
    1. Enter "Execute transition as committer" to the Description field.
    2. Enter this Groovy script:
      import com.atlassian.jira.component.ComponentAccessor
      
      def issueService = ComponentAccessor.issueService
      
      if (!issues) {
      	return
      }
      
      def resolutionId = devops.resolution ? jiraHelper.getResolutionByName(devops.resolution).id : null
      
      def author = devops.committerByUsername ?: {throw new IllegalArgumentException("No user found with username \"${devops.commit.username}\"")}()
      // def author = devops.committerByEmailAddress ?: {throw new IllegalArgumentException("No user found with email address \"${devops.commit.emailAddress}\"")}() // (alternative, see the Smart Value Reference!)
      
      issues.forEach { issue ->
      	try {
      		def transition = jiraHelper.getTransitionByName(issue.key, devops.transition)
      		def transitionId = transition.transitionId
      
      		if (issue.status.id == String.valueOf(transition.toStatusId) &&
      			(!resolutionId || issue.resolution?.id == resolutionId)) {
      			return
      		}
      
      		def issueParams = issueService.newIssueInputParameters()
      		if (resolutionId) {
      			issueParams.setResolutionId(resolutionId)
      		}
      
      		def validationResult = issueService.validateTransition(author, issue.id, transitionId as int, issueParams)
      		if (validationResult.isValid()) {
      			def issueResult = issueService.transition(author, validationResult)
      			if (issueResult.issue.status.id == String.valueOf(transition.toStatusId)) {
      				def resolutionInfo = resolutionId ? " with a resolution of <${issueResult.issue.resolution.name}>" : ""
      				auditLog.info("${issue.key} transitioned to <${issueResult.issue.status.name}>${resolutionInfo}")
      			} else {
      				auditLog.error("${issue.key} not transitioned! (check the workflow configuration!)")
      			}
      			if (resolutionId && (issueResult.issue.resolution?.id != resolutionId)) {
      				auditLog.error("${issue.key} resolution not changed! (check the workflow configuration!)")
      			}
      		} else {
      			(validationResult.errorCollection.errors.collect { "<${it.key}> field error: ${it.value}" } + validationResult.errorCollection.errorMessages).each { auditLog.error(it) }
      		}
      	} catch (Exception e) {
      		auditLog.error(e.message ?: "${e} ${e.stackTrace}")
      	}
      }
      
  7. Click Save.
  8. Click Add component and select Branch rule / related issues.
  9. Select Current issue from the Type of related issues dropdown.
  10. Click Save.
  11. Click New action.
  12. Select the action Send web request.
    1. Enter the Webhook URL as:
      {{baseUrl}}/rest/api/2/issue/{{issue.key}}/transitions/
    2. Add a header with the name "Authorization" and with the value of the Basic Access Authentication credentials. The credentials are generated from a valid Jira username and its password.
      Notes:
      1. The full header value looks something like "Basic YWRtaW46YWRtaW4=".
      2. Don't forget to put "Basic" to the start!
      3. If you don't know how to generate the second part, use this safe online form. Just enter the username and the password in the format "myusername:mypassword" (separated with ":"), click Base64 Encode, then copy the resulted string back to the action's configuration. (The form runs fully in your browser, it does not store or transmit anything, therefore it is safe to use.)
    3. Add a header with the name "Content-Type" and with value of "application/json".
    4. Choose POST as HTTP method.
    5. Choose Custom data as Webhook body.
    6. Enter the following data:
      {
      	{{#stringHelper.trimToNull(devops.resolution)}}
      		"fields": {
      			"resolution": {
      				"id": "{{jiraHelper.getResolutionByName(devops.resolution).id}}"
      			}
      		},
      	{{/}}
      	"transition": {
      		"id": "{{jiraHelper.getTransitionByName(issue.key, devops.transition).transitionId}}"
      	}
      }
      
      You can read more about the expected JSON content here.
  13. Click Save.
  14. Name your automation rule intuitively, and click Turn it on.

Usage

Transition only
  1. Create a commit with this commit message:
    Protect against the null value that caused the FOO-1 bug. @transition Done
    In the example above, the issue FOO-1 is in status "In Progress" and the project workflow allows it to be transitioned to another status through transition "Done".
  2. Issue FOO-1 will be transitioned through "Done".
Transition and resolution
  1. Create a commit with this commit message:
    Protect against the null value that caused the FOO-1 bug. @transition Done/Fixed
    Note the transition name and the resolution name separated with /. In the example above, the issue FOO-1 is in status "In Progress" and the project workflow allows it to be transitioned to another status through transition "Done" with resolution "Fixed".
  2. Issue FOO-1 will be transitioned through "Done" with resolution "Fixed".

Troubleshooting

If you don't get the expected results:

  1. Check if the @transition command is defined in the Genius Commands screen? (It's a default command.)
  2. Check if the @transition command followed by the transition name and optionally the resolution name was included in the commit message?
  3. Check if the transition with that name exists?
  4. Check if the resolution with that name exists?
  5. See the general troubleshooting steps.

Questions?

Ask us any time.