0

Transition Issue

by
Published Nov 2, 2023

Move an issue through its workflow, e.g. to In Progress or Done. The transition is picked from those currently available on the issue; `fields` and `update` set fields shown on the transition screen (e.g. `{ "resolution": { "name": "Fixed" } }`).

Script jira Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 14 days ago
1
//native
2

3
async function get(auth: RT.Jira, path: string) {
4
  const response = await fetch(`https://${auth.domain}.atlassian.net${path}`, {
5
    headers: {
6
      Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`,
7
      Accept: "application/json",
8
    },
9
  })
10
  if (!response.ok) {
11
    throw new Error(`${response.status} ${await response.text()}`)
12
  }
13
  return await response.json()
14
}
15

16
export type DynSelect_transition_id = string
17

18
// Resolver: the transitions currently available on the chosen issue.
19
export async function transition_id(auth: RT.Jira, issue_id_or_key: string) {
20
  if (!issue_id_or_key) return []
21
  const { transitions } = await get(
22
    auth,
23
    `/rest/api/3/issue/${issue_id_or_key}/transitions`
24
  )
25
  return transitions.map(
26
    (t: { id: string; name: string; to?: { name: string } }) => ({
27
      value: t.id,
28
      label: t.to?.name ? `${t.name} (to ${t.to.name})` : t.name,
29
    })
30
  )
31
}
32

33
/**
34
 * Transition Issue
35
 * Move an issue through its workflow, e.g. to In Progress or Done. The transition is picked from those currently available on the issue; `fields` and `update` set fields shown on the transition screen (e.g. `{ "resolution": { "name": "Fixed" } }`).
36
 */
37
export async function main(
38
  auth: RT.Jira,
39
  issue_id_or_key: string,
40
  transition_id: DynSelect_transition_id,
41
  fields: { [key: string]: any } | undefined,
42
  update: { [key: string]: any } | undefined
43
) {
44
  const url = new URL(
45
    `https://${auth.domain}.atlassian.net/rest/api/3/issue/${issue_id_or_key}/transitions`
46
  )
47

48
  const body: { [key: string]: any } = { transition: { id: transition_id } }
49
  if (fields && Object.keys(fields).length) {
50
    body.fields = fields
51
  }
52
  if (update && Object.keys(update).length) {
53
    body.update = update
54
  }
55

56
  const response = await fetch(url, {
57
    method: "POST",
58
    headers: {
59
      Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`,
60
      "Content-Type": "application/json",
61
      Accept: "application/json",
62
    },
63
    body: JSON.stringify(body),
64
  })
65

66
  if (!response.ok) {
67
    throw new Error(`${response.status} ${await response.text()}`)
68
  }
69

70
  if (response.status === 204) return { success: true }
71
  return await response.json()
72
}
73

Other submissions
  • Submitted by hugo697 Typescript (fetch-only)
    Created 538 days ago
    1
    type Jira = {
    2
      username: string;
    3
      password: string;
    4
      domain: string;
    5
    };
    6
    /**
    7
     * Transition issue
    8
     * Performs an issue transition and, if the transition has a screen, updates the fields from the transition screen.
    9
     */
    10
    export async function main(
    11
      auth: Jira,
    12
      issueIdOrKey: string,
    13
      body: {
    14
        fields?: { [k: string]: unknown };
    15
        historyMetadata?: {
    16
          activityDescription?: string;
    17
          activityDescriptionKey?: string;
    18
          actor?: {
    19
            avatarUrl?: string;
    20
            displayName?: string;
    21
            displayNameKey?: string;
    22
            id?: string;
    23
            type?: string;
    24
            url?: string;
    25
            [k: string]: unknown;
    26
          };
    27
          cause?: {
    28
            avatarUrl?: string;
    29
            displayName?: string;
    30
            displayNameKey?: string;
    31
            id?: string;
    32
            type?: string;
    33
            url?: string;
    34
            [k: string]: unknown;
    35
          };
    36
          description?: string;
    37
          descriptionKey?: string;
    38
          emailDescription?: string;
    39
          emailDescriptionKey?: string;
    40
          extraData?: { [k: string]: string };
    41
          generator?: {
    42
            avatarUrl?: string;
    43
            displayName?: string;
    44
            displayNameKey?: string;
    45
            id?: string;
    46
            type?: string;
    47
            url?: string;
    48
            [k: string]: unknown;
    49
          };
    50
          type?: string;
    51
          [k: string]: unknown;
    52
        };
    53
        properties?: { key?: string; value?: { [k: string]: unknown } }[];
    54
        transition?: {
    55
          expand?: string;
    56
          fields?: {
    57
            [k: string]: {
    58
              allowedValues?: { [k: string]: unknown }[];
    59
              autoCompleteUrl?: string;
    60
              configuration?: { [k: string]: { [k: string]: unknown } };
    61
              defaultValue?: { [k: string]: unknown };
    62
              hasDefaultValue?: boolean;
    63
              key: string;
    64
              name: string;
    65
              operations: string[];
    66
              required: boolean;
    67
              schema: {
    68
                configuration?: { [k: string]: { [k: string]: unknown } };
    69
                custom?: string;
    70
                customId?: number;
    71
                items?: string;
    72
                system?: string;
    73
                type: string;
    74
              };
    75
            };
    76
          };
    77
          hasScreen?: boolean;
    78
          id?: string;
    79
          isAvailable?: boolean;
    80
          isConditional?: boolean;
    81
          isGlobal?: boolean;
    82
          isInitial?: boolean;
    83
          looped?: boolean;
    84
          name?: string;
    85
          to?: {
    86
            description?: string;
    87
            iconUrl?: string;
    88
            id?: string;
    89
            name?: string;
    90
            scope?: {
    91
              project?: {
    92
                avatarUrls?: {
    93
                  "16x16"?: string;
    94
                  "24x24"?: string;
    95
                  "32x32"?: string;
    96
                  "48x48"?: string;
    97
                };
    98
                id?: string;
    99
                key?: string;
    100
                name?: string;
    101
                projectCategory?: {
    102
                  description?: string;
    103
                  id?: string;
    104
                  name?: string;
    105
                  self?: string;
    106
                };
    107
                projectTypeKey?: "software" | "service_desk" | "business";
    108
                self?: string;
    109
                simplified?: boolean;
    110
              };
    111
              type?: "PROJECT" | "TEMPLATE";
    112
              [k: string]: unknown;
    113
            };
    114
            self?: string;
    115
            statusCategory?: {
    116
              colorName?: string;
    117
              id?: number;
    118
              key?: string;
    119
              name?: string;
    120
              self?: string;
    121
              [k: string]: unknown;
    122
            };
    123
            [k: string]: unknown;
    124
          };
    125
          [k: string]: unknown;
    126
        };
    127
        update?: {
    128
          [k: string]: {
    129
            add?: { [k: string]: unknown };
    130
            copy?: { [k: string]: unknown };
    131
            edit?: { [k: string]: unknown };
    132
            remove?: { [k: string]: unknown };
    133
            set?: { [k: string]: unknown };
    134
          }[];
    135
        };
    136
        [k: string]: unknown;
    137
      }
    138
    ) {
    139
      const url = new URL(
    140
        `https://${auth.domain}.atlassian.net/rest/api/2/issue/${issueIdOrKey}/transitions`
    141
      );
    142
    
    
    143
      const response = await fetch(url, {
    144
        method: "POST",
    145
        headers: {
    146
          "Content-Type": "application/json",
    147
          Authorization: "Basic " + btoa(`${auth.username}:${auth.password}`),
    148
        },
    149
        body: JSON.stringify(body),
    150
      });
    151
      if (!response.ok) {
    152
        const text = await response.text();
    153
        throw new Error(`${response.status} ${text}`);
    154
      }
    155
      return await response.json();
    156
    }
    157