LogoLogo
  • ๐Ÿ“‘Introduction
  • ๐Ÿ› ๏ธCookbooks
    • โฑ๏ธExport Issue History
    • ๐Ÿ‘พCreate Jira Issue
    • ๐ŸงฉExtract customfields from issue(s)
    • ๐ŸŒ„Upload Content Attachment
    • ๐ŸšฎCreate Jira ITSM Request
    • ๐ŸšœEdit Jira Issue (Explicit)
    • ๐Ÿš›Edit Jira Issue (Implicit)
    • ๐ŸšŽCreate Jira Workflow
    • ๐Ÿ—ƒ๏ธAdd CustomField to Screen
    • ๐ŸšŸSearch Project Boards
    • ๐Ÿ“…Get User Last-Login Info
    • ๐Ÿค’Remove User Access
    • ๐ŸคฏSuspend User Access
    • ๐ŸฅณRestore User Access
    • ๐Ÿš‹Extract Project Administrators
    • ๐ŸงบSearch Jira User By Email
    • ๐ŸšžSearch Contents By CQL
    • ๐ŸŒŠCascade Permissions from Parent to Child
    • ๐ŸŽญPage Permission Helper
    • ๐Ÿค–Atlassian SCIM Onboarding
    • ๐Ÿ˜ƒCreate User via SCIM
    • ๐Ÿ›ฐ๏ธIssue Permission Helper
  • Jira Software Cloud
    • ๐Ÿ—ƒ๏ธIntroduction
    • ๐Ÿ“ฎAnnouncement Banner
    • ๐Ÿ”Application Roles
    • ๐Ÿ›ก๏ธ Audit records
    • ๐Ÿ“ˆDashboards
    • ๐Ÿ—„๏ธFilters
      • ๐ŸคSharing
    • ๐Ÿ‘ซGroups
    • ๐ŸžIssues
      • ๐Ÿ“ŽAttachments
      • ๐Ÿ“ฌComments
      • ๐ŸƒFields
        • ๐Ÿ–ผ๏ธConfiguration
          • ๐ŸคItems
          • ๐Ÿ”ƒSchemes
        • ๐ŸณContext
          • ๐Ÿ•งOption
        • ๐Ÿ—‘๏ธTrash
      • ๐Ÿท๏ธ Labels
      • ๐Ÿ”—Link
        • ๐Ÿ”ƒRemote
        • ๐Ÿ–‡๏ธTypes
      • ๐Ÿš›Metadata
      • ๐ŸฃPriorities
      • ๐Ÿ€Resolutions
      • ๐Ÿ“ŒSearch
      • ๐Ÿ“ฆType
        • ๐ŸŽดScheme
        • ๐Ÿ›…Screen Scheme
      • ๐Ÿ“ Vote
      • ๐ŸŽฏWatcher
      • ๐Ÿ•ฐ๏ธWorklogs
      • ๐Ÿ“คProperties
      • ๐Ÿ“ญArchiving
    • ๐Ÿ”“Permissions
      • ๐Ÿ“œScheme
        • ๐Ÿ”‘Grant
    • ๐Ÿ“šProjects
      • ๐ŸงฉCategories
      • ๐Ÿ”ฎComponents
      • ๐ŸšงPermission Schemes
      • ๐Ÿ“ฌNotification Schemes
      • ๐Ÿ’ผRoles
        • ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งActors
      • ๐ŸงตTypes
      • ๐ŸงฑVersions
      • ๐Ÿช”Validation
      • ๐Ÿ™ŒFeatures
      • ๐Ÿ“คProperties
    • ๐Ÿ““Screens
      • ๐Ÿ“‚Tabs
        • ๐ŸงฐFields
      • ๐Ÿ“ Schemes
    • โš™๏ธServer
    • ๐Ÿ”ฉJQL
    • โš—๏ธTasks
    • ๐Ÿค“Users
      • ๐Ÿ“ Search
    • ๐Ÿ–จ๏ธWorkflow
      • ๐Ÿš›Scheme
        • ๐Ÿ“ฏIssue Type
      • ๐Ÿ—บ๏ธStatus
    • โš–๏ธMyself
    • ๐Ÿ“Teams
  • Jira Agile
    • ๐Ÿœ๏ธIntroduction
    • ๐Ÿ“‰Boards
      • ๐Ÿ“ƒBacklog
    • ๐Ÿ—“๏ธSprints
    • ๐Ÿ“ˆEpics
  • Jira Service Management
    • ๐Ÿ—บ๏ธIntroduction
    • ๐Ÿ‘จโ€โš–๏ธCustomer
    • โ„น๏ธInfo
    • ๐Ÿ“šKnowledgebase
    • ๐Ÿ›‚Organization
    • ๐Ÿ“™Request
      • ๐ŸšซApproval
      • ๐Ÿ“‚Attachments
      • ๐Ÿ“ฌComments
      • ๐Ÿ“ฎFeedback
      • ๐Ÿ‘ฅParticipants
      • โฐSLA
      • ๐Ÿ’พTypes
      • โš™๏ธService Desk
        • ๐Ÿ›Ž๏ธQueue
    • ๐Ÿ“™Workspaces
  • Jira Assets
    • ๐Ÿ“ Introduction
    • ๐Ÿ‘พIcons
    • ๐Ÿ”ŽAql
    • ๐Ÿ›๏ธObject
      • ๐Ÿ“ Schema
      • ๐ŸงฐType
        • ๐Ÿ›Ž๏ธAttribute
  • Confluence Cloud
    • ๐ŸŽ‘Introduction
    • ๐Ÿ“‰Analytics
    • ๐Ÿ“ขContent
      • ๐ŸŽฎProperties
      • ๐Ÿ“‚Attachments
      • ๐Ÿ“ฌComments
      • ๐ŸšฉLabels
      • ๐ŸŽŽChildren/Descendants
      • ๐Ÿ›ก๏ธPermissions
      • ๐Ÿ”žRestrictions
        • ๐ŸŽ‘Operations
          • ๐Ÿซ‚Group
          • ๐Ÿ‘คUser
      • ๐Ÿ”ƒVersions
    • ๐Ÿ’พSpace
      • ๐Ÿ›ก๏ธPermissions
    • ๐Ÿ”ฐLabel
    • ๐Ÿ”ŽSearch
    • ๐Ÿ–ผ๏ธLong Task
    • ๐Ÿ—ƒ๏ธTemplate
    • ๐ŸŒŠV2
      • ๐Ÿ”๏ธIntroduction
      • ๐ŸงบAttachments
        • ๐Ÿ’ปVersions
      • ๐Ÿ“ƒPage
      • ๐ŸชŸSpace
      • ๐Ÿ—ƒ๏ธCustom Content
  • Atlassian Admin Cloud
    • ๐ŸŒŒIntroduction
    • โ„น๏ธOrganization
      • ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆDirectory
      • ๐Ÿ‘”Policy
    • ๐Ÿ‘ฅUser
      • ๐Ÿ”“Token
    • ๐ŸงฐSCIM
      • ๐Ÿง™โ€โ™‚๏ธUsers
      • โ›น๏ธโ€โ™‚๏ธGroups
      • ๐Ÿ”ฉSchemas
  • Bitbucket Cloud
    • ๐Ÿ‘จโ€๐Ÿ’ปIntroduction
    • ๐Ÿ“ฐWorkspace
      • ๐Ÿ›ก๏ธPermissions
      • ๐Ÿ’พWebhooks
Powered by GitBook
On this page
  • Step 1: Create a new Go project
  • Step 2: Install the "go-atlassian" library
  • Step 3: Import the required packages
  • Step 4: Set up Jira API client
  • Step 5: Create a workflow
  • Step 5.1: Extract the status ID's
  • Step 5.2: Create the workflow transitions
  • Step 5.3: Create the workflow
  • Git Gist File

Was this helpful?

Export as PDF
  1. Cookbooks

Create Jira Workflow

In this article, I would be showing you how to create Jira workflow and append transitions using go-atlassian

Step 1: Create a new Go project

Create a new directory for your project and navigate to it in your terminal or command prompt. Initialize a new Go module using the following command:

go mod init your-module-name

Step 2: Install the "go-atlassian" library

To use the "go-atlassian" library, you need to install it as a dependency in your project. Run the following command:

go get github.com/ctreminiom/go-atlassian

Step 3: Import the required packages

Create a new Go file, e.g., main.go, and import the necessary packages:

package main

import (
	"fmt"
	"log"

	jira "github.com/ctreminiom/go-atlassian/jira/v2"
)

Step 4: Set up Jira API client

Initialize the Jira API client with your Jira base URL and API token:

func main() {
	jiraClient, err := jira.New(nil, "https://your-jira-instance.atlassian.net")
	if err != nil {
		log.Fatal(err)
	}

	// Set API token for authentication
	jiraClient.Auth.SetBasicAuth(mail, token)
}

Step 5: Create a workflow

To create a new workflow, we need to the create the models.WorkflowPayloadScheme payload struct with the following information.

  1. Worfklow Name.

  2. Workflow Description.

  3. Workflow Statuses.

  4. Workflow Transitions.

Let's try to create a workflow with directed transitions and all-to-all transitions, something like this:

Step 5.1: Extract the status ID's

The first step to create a Jira workflow is recognize what's gonna be the statuses you want to use.

Statuses represent the different stages that an issue can go through in a workflow.

In this particular example, we're needed to use the following statuses:

  • Open

  • In Progress

  • QA

  • Waiting for approval

  • Escalated

  • Closed

  • Resolved

var statusesNamesAsSlice = []string{
	"Open", "In Progress", "QA",
	"Waiting for approval", "Escalated",
	"Closed", "Resolved",
}

var statusesAsMap = make(map[string]*models.WorkflowStatusDetailScheme)
for _, statusName := range statusesNamesAsSlice {

	options := &models.WorkflowStatusSearchParams{
		SearchString: statusName,
	}

	page, response, err := instance.Workflow.Status.Search(context.Background(), options, 0, 1)
	if err != nil {
		if response != nil {
			log.Println(response.Bytes.String())
			log.Println(response.Code)
		}

		log.Fatal(err)
	}

	var wasFound bool
	for _, status := range page.Values {

		if status.Name == statusName {
			statusesAsMap[status.Name] = status
			wasFound = true
			break
		}
	}

	if !wasFound {

		// If the workflow is not found, it's required to create a new global status
		statusPayload := &models.WorkflowStatusPayloadScheme{
			Statuses: []*models.WorkflowStatusNodeScheme{
				{
					Name:           statusName,
					StatusCategory: "IN_PROGRESS",
				},
			},
			Scope: &models.WorkflowStatusScopeScheme{
				Type: "GLOBAL",
			},
		}

		statuses, response, err := instance.Workflow.Status.Create(context.Background(), statusPayload)
		if err != nil {
			if response != nil {
				log.Println(response.Bytes.String())
				log.Println(response.Code)
			}

			log.Fatal(err)
		}

		for _, status := range statuses {

			if status.Name == statusName {
				statusesAsMap[status.Name] = status
				break
			}
		}
	}
}

for name, data := range statusesAsMap {
	fmt.Println(name, data.ID)
}

The previously code extracts the status ID's from the Jira instance and if one status is not available on the instance, it'll automatically create the statuses and append the information on the statusesAsMap variable.

With the status ID's, we can proceed with the creation of the workflow statuses payload

var workflowStatuses []*models.WorkflowTransitionScreenScheme
for _, status := range statusesAsMap {

	workflowStatuses = append(workflowStatuses, &models.WorkflowTransitionScreenScheme{
		ID:         status.ID,
		Properties: nil,
	})
}

Step 5.2: Create the workflow transitions

With the statuses id's extracted, we can create a workflow transitions. The transitions define the paths that an issue can take from one status to another.

For example: an issue in the "Open" status can transition to the "In Progress" status when work begins on it.

There're the conditional validations needed to create a valid workflow transition:

  • include one initial transition.

  • not use the same name for a global and directed transition.

  • have a unique name for each global transition.

  • have a unique 'to' status for each global transition.

  • have unique names for each transition from a status.

  • not have a 'from' status on initial and global transitions.

  • have a 'from' status on directed transitions.

var workflowTransitions []*models.WorkflowTransitionPayloadScheme

// -----
// The initial transition is required, it creates the relationship between the creation trigger with the
// first status
// -----
workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "Create",
	To:   "1",
	Type: "initial",
})

// -----
// Create the Escalated and Waiting for approval statuses because the relationship is all-to-all
workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "Escalated",
	To:   statusesAsMap["Escalated"].ID,
	Type: "global",
})

workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "Waiting for approval",
	To:   statusesAsMap["Waiting for approval"].ID,
	Type: "global",
})
// -----

// ----
// Create the directed transitions, it's required to use the from and to statuses

// Open -----------------------> In Progress
workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "In Progress",
	From: []string{statusesAsMap["Open"].ID},
	To:   statusesAsMap["In Progress"].ID,
	Type: "directed",
})

// In Progress -----------------------> QA
workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "QA",
	From: []string{statusesAsMap["In Progress"].ID},
	To:   statusesAsMap["QA"].ID,
	Type: "directed",
})

// QA -----------------------> In Progress
workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "QA",
	From: []string{statusesAsMap["QA"].ID},
	To:   statusesAsMap["In Progress"].ID,
	Type: "directed",
})

// QA -----------------------> Closed
workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "Closed",
	From: []string{statusesAsMap["QA"].ID},
	To:   statusesAsMap["Closed"].ID,
	Type: "directed",
})

// QA -----------------------> Resolved
workflowTransitions = append(workflowTransitions, &models.WorkflowTransitionPayloadScheme{
	Name: "Resolved",
	From: []string{statusesAsMap["QA"].ID},
	To:   statusesAsMap["Resolved"].ID,
	Type: "directed",
})

Step 5.3: Create the workflow

In conclusion, we can combine the statuses and transitions structs and create the workflow using the structs created on the previous steps.

workflowPayload := &models.WorkflowPayloadScheme{
	Name:        "Workflow Name - Sample",
	Description: "Workflow Name - Description",
	Statuses:    workflowStatuses,
	Transitions: workflowTransitions,
}

newWorkflow, response, err := instance.Workflow.Create(context.Background(), workflowPayload)
if err != nil {
	if response != nil {
		log.Println(response.Bytes.String())
		log.Println(response.Code)
	}

	log.Fatal(err)
}

log.Println(newWorkflow.Name)
log.Println(newWorkflow.EntityID)

Git Gist File

PreviousEdit Jira Issue (Implicit)NextAdd CustomField to Screen

Last updated 1 year ago

Was this helpful?

๐Ÿ› ๏ธ
๐ŸšŽ
Page cover image