- Bulk Update
- Auto-Assignment
- SLA Monitoring
- Custom Dashboard Data
- Field Sync
- Dynamic Forms (UIM)
- Async Workflow
- Sprint Automation
- Issue Cloning
- Data Export
- Next Steps
Bulk Update
Mass-update issue fields by JQL query.
Features used: Issues.searchAll, issue.update
const issues = await Issues.searchAll("project = PROJ AND status = Open AND priority = Low")
for (const issue of issues.issues) {
await issue.update({ priority: { name: "Medium" } })
log(`Updated ${issue.key}`)
}
return `Updated ${issues.issues.length} issues`
Auto-Assignment
Automatically assign issues when created, based on component or issue type.
Features used: Event trigger (issue_created), Issues.get, issue.assign, Users.findAssignable
// Trigger: Event - issue_created
const issue = await Issues.get(issueKey)
const assignmentRules = {
"Backend": "5b10ac8d82e05b22cc7d4ef5",
"Frontend": "5b10ac8d82e05b22cc7d4ef6",
}
for (const comp of issue.components) {
const accountId = assignmentRules[comp.name]
if (accountId) {
await issue.assign(accountId)
log(`Assigned ${issue.key} to ${comp.name} lead`)
break
}
}
SLA Monitoring
Scheduled script to find overdue issues and notify via comments.
Features used: Scheduled trigger, Issues.searchAll, issue.addComment, DateUtils
// Trigger: Scheduled - Daily
const overdue = await Issues.searchAll(
"project = PROJ AND status != Done AND duedate < now()"
)
for (const issue of overdue.issues) {
const days = DateUtils.diffDays(issue.fields.duedate, new Date())
await issue.addComment(`This issue is ${days} days overdue. Please review.`)
log(`Notified: ${issue.key} (${days} days overdue)`)
}
return `Found ${overdue.issues.length} overdue issues`
Custom Dashboard Data
Collect project statistics into a custom table for reporting.
Features used: Scheduled trigger, Issues.count, tables
// Trigger: Scheduled - Daily
const projects = ["PROJ", "DEV", "OPS"]
for (const proj of projects) {
const open = await Issues.count(`project = ${proj} AND status != Done`)
const bugs = await Issues.count(`project = ${proj} AND issuetype = Bug AND status != Done`)
const created = await Issues.count(`project = ${proj} AND created >= -7d`)
await tables.addRow("daily_stats", {
project: proj,
date: DateUtils.format(new Date(), "YYYY-MM-DD"),
open_issues: open,
open_bugs: bugs,
created_7d: created
})
}
Field Sync
Sync a field value from parent to all subtasks when updated.
Features used: Event trigger (issue_updated), Issues.get, Issues.search, issue.update
// Trigger: Event - issue_updated
const parent = await Issues.get(issueKey)
const subtasks = await Issues.search(`parent = ${issueKey}`, {
fields: ["priority"]
})
for (const sub of subtasks.issues) {
if (sub.priority !== parent.priority) {
await sub.update({ priority: { name: parent.priority } })
log(`Synced priority to ${sub.key}`)
}
}
Dynamic Forms (UIM)
Show/hide fields based on issue type and set defaults on creation.
Features used: UIM trigger, uim.setVisible, uim.setValue, uim.setRequired
// Trigger: UIM (onInit + onChange)
if (uimData.callbackType === 'onInit' || uimData.changedFieldId === 'issuetype') {
const type = uimData.fieldValues?.issuetype?.value
if (type === 'Bug') {
uim.setVisible('environment', true)
uim.setRequired('environment', true)
uim.setVisible('customfield_10100', true) // Steps to reproduce
} else {
uim.setVisible('environment', false)
uim.setRequired('environment', false)
uim.setVisible('customfield_10100', false)
}
}
// Auto-fill defaults on create
if (uimData.callbackType === 'onInit' && uimData.viewType === 'GIC') {
const due = DateUtils.addDays(new Date(), 14)
uim.setValue('duedate', DateUtils.format(due, 'YYYY-MM-DD'))
}
Async Workflow
Chain processing steps using async events and queues.
Features used: asyncEvent, queue, Issues.get
// Script 1: Trigger async processing chain
const issues = await Issues.searchAll("project = PROJ AND labels = needs-review")
for (const issue of issues.issues) {
await queue.push("review-queue", {
issueKey: issue.key,
priority: issue.priority
})
}
log(`Queued ${issues.issues.length} issues for review`)
// Script 2: Process the queue (Scheduled trigger)
const messages = await queue.consume("review-queue", 10)
for (const msg of messages) {
const issue = await Issues.get(msg.payload.issueKey)
await issue.addComment("Automated review: checked by scheduled job")
await issue.update({ labels: [...issue.labels.filter(l => l !== "needs-review"), "reviewed"] })
log(`Reviewed: ${msg.payload.issueKey}`)
}
Sprint Automation
Automatically move unfinished issues to the next sprint when a sprint closes.
Features used: Event trigger (sprint_closed), Boards.getSprints, Sprints.getIssues, Sprints.moveIssues
// Trigger: Event - sprint_closed
const boardId = event.boardId
// Find the next active/future sprint
const sprints = await Boards.getSprints(boardId, "active")
if (sprints.length === 0) {
return "No active sprint to move issues to"
}
const nextSprint = sprints[0]
// Get incomplete issues from closed sprint
const closedSprintId = event.sprintId
const issues = await Sprints.getIssues(closedSprintId, {
jql: "status != Done"
})
const keys = issues.issues.map(i => i.key)
if (keys.length > 0) {
await Sprints.moveIssues(nextSprint.id, keys)
log(`Moved ${keys.length} issues to ${nextSprint.name}`)
}
return `Moved ${keys.length} unfinished issues`
Issue Cloning
Clone issues with modifications - useful for recurring tasks.
Features used: Issues.get, issue.clone
// Clone a template issue with new values
const template = await Issues.get("PROJ-100")
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
const month = months[new Date().getMonth()]
const clone = await template.clone({
summary: `Monthly Report - ${month}`,
description: `Monthly report for ${month}. Based on template ${template.key}.`
})
log(`Created ${clone.key} from template ${template.key}`)
return clone.key
Data Export
Export Jira data to a custom table for reporting or integration.
Features used: Scheduled trigger, Issues.searchAll, tables, CSV, DateUtils
// Trigger: Scheduled - Weekly
const issues = await Issues.searchAll(
"project = PROJ AND resolved >= -7d",
{ fields: ["summary", "status", "assignee", "resolutiondate", "priority"] }
)
// Save to custom table
for (const issue of issues.issues) {
await tables.addRow("weekly_resolved", {
key: issue.key,
summary: issue.summary,
assignee: issue.assignee ?? "Unassigned",
priority: issue.priority,
resolved: issue.fields.resolutiondate,
week: DateUtils.format(new Date(), "YYYY-MM-DD")
})
}
// Also generate CSV summary
const csv = CSV.stringify(issues.issues.map(i => ({
Key: i.key,
Summary: i.summary,
Assignee: i.assignee ?? "Unassigned",
Priority: i.priority
})))
log(csv)
return `Exported ${issues.issues.length} resolved issues`
Next Steps
- Scripting API - Full API reference
- Scripting Language - Language syntax and features
- Triggers - Trigger configuration
- Data Storage - Tables and queues
