Resources
Cookbook
Practical recipes built on confirmed capabilities. Validate and Dry Run each in your own instance before publishing.
Set a field based on another field (taskActionDone)
if (issue.field("Requirement Type").is("Roadmap Requirement")) {
issue.update({ Priority: "Medium" })
api.log("Priority set to Medium")
}
Block an update while a requirement is In Review (taskPreAction)
if (
issue.issueType.is("Requirement") &&
issue.status.is("In Review") &&
issue.anyFieldChanged()
) {
api.reject("Requirements cannot be updated while In Review")
}
Act only when a field changed to a specific value (event / taskActionDone)
if (issue.status.changedTo("Blocked")) {
issue.update({ Priority: "Highest" })
api.log("Escalated blocked issue")
}
Comment and mention the assignee on a status-category change (event)
if (
issue.anyStatusChanged() &&
issue.statusCategory.changedTo("in_progress") &&
issue.issueType.is("User Story")
) {
issue.addComment({
text: "Status moved into progress.",
mentions: [issue.assignee.mention()]
})
}
.mention()is pending re-verification in 1.1 — confirm with a Dry Run before relying on it.
Post-action external webhook (taskActionDone / event)
if (issue.status.changedTo("Done")) {
const response = await api.fetchExternal({
url: "https://example.com/hooks/ones-status",
method: "POST",
headers: { Authorization: "Bearer " + vars.get("WEBHOOK_TOKEN") },
body: { issueUUID: context.taskUUID, status: "Done" },
timeoutMs: 5000
})
api.log("Webhook status: " + response.statusCode)
}
Idempotent event listener (event)
const eventID = String(event.eventID || context.eventID || "")
const key = "event:" + eventID
if (eventID && (await api.storage.get(key))) {
return // already processed
}
if (issue.field("Found in Production").changedTo("Yes")) {
issue.update({ Priority: "Highest" })
}
if (eventID) {
await api.storage.set(key, true)
}
Scheduled query with issue.search (timer)
const issues = await issue.search({
where: { issueType: "Requirement", status: "In Review" },
select: ["Priority"],
limit: 100
})
for (const item of issues) {
api.log("In review: " + item.field("Priority").value)
}
Process multiple pages of issues with Cursor (timer or Run now)
let cursor = ""
do {
const issues = await issue.search({
where: { issueType: "Requirement", status: "In Review" },
limit: 100,
cursor
})
for (const item of issues) {
api.log("In review: " + item.key)
}
cursor = issues.pageInfo.hasNextPage
? issues.pageInfo.endCursor
: ""
} while (cursor)
limit controls how many issues each call returns. For continuous paging, pass the current page's pageInfo.endCursor to the next call.
Keep a child's planned end date within its parent (hierarchy) (taskPreAction)
if (context.action === "update" && issue.field("Planned end date").changed()) {
const next = issue.field("Planned end date").newValue
if (issue.hierarchy("Upstream").any.field("Planned end date").isBefore(next)) {
api.reject("The planned end date must not be later than the upstream (parent) issue.")
}
}
Block a transition until linked prerequisites are done (taskPreAction)
if (issue.status.changedTo("In Progress")) {
try {
if (!issue.linkedIssues("Prerequisites").all.statusCategory.is("done")) {
api.reject("Finish the prerequisite issues before starting this issue.")
}
} catch (e) {
api.reject("Cannot verify prerequisites — try again.")
}
}
Email owners about overdue issues on a schedule (timer; On-Premises only)
const overdue = await issue.search({
where: { status: "In Progress" },
select: ["Assignee"],
limit: 100
})
for (const item of overdue) {
api.notify({
channel: "email",
recipients: [item.assignee.value], // ONES user UUID
title: "An issue needs your attention",
message: "This issue has stayed in progress and may be overdue.",
issue: item.uuid
})
}
Delivery is not retried automatically — check Execute Log for the per-notification outcome. See
api.notify.
Limitations & roadmap
Already native in ONES (no script needed) — several things that require ScriptRunner add-ons in Jira are built into ONES (conditional field display, dependent option filtering, parent/child roll-ups & calculated fields), so they don't need a script at all. See What becomes native configuration.
Not available yet
- Conditional required/non-empty validation — e.g. "if field A = X, field B can't be empty," and pop-up prompts during form entry. (Value-based conditional validation — "if A = a, B can't be 1" — is supported via a
taskPreActionvalidator.)
On the roadmap 🔜
- SaaS deployment (On-Premises is available today)
- Conditional required/non-empty validation / interactive in-form prompts
- A dedicated Query UI (querying inside scripts via
api.queryIssues(...)works today) - Permissions / roles (author vs. run, scoping)
To be defined ❓
- Retention/export for version history, Execute Log, Event Log, and the system audit log
FAQ, glossary & feedback
FAQ (starter set — expand as questions come in)
- Which languages can I use? JavaScript, TypeScript, or Groovy (Groovy is On-Premises only, via an external runner).
- Will it run on-prem? Yes — On-Premises is available today; SaaS is coming soon.
- Is it the same as Automation? No — Automation handles the everyday with no-code rules; ONEScript is the code layer beneath that picks up where no-code leaves off.
- Can I test without changing data? Yes — use Dry Run, which never changes data. Run now is a live execution, appears only for an eligible latest published script, and requires confirmation.
- How do I make a script run automatically? Publish it, then bind it under Automation → Trigger Bindings (or Timer Rules for schedules).
- How do I inspect executions for one script or Timer Rule? Open Execute history from the script's More menu or the Timer Rule card. ONEScript opens the Execute Log filtered to that object.
- Who can see what a script changed? The issue history (shown as "ONEScript updated …"), the Execute Log, and the system audit log.
- Can I use an AI assistant to write scripts? Yes — download the AI Skill (
Skill.md) and load it into your assistant. See Author with an AI assistant.
Glossary
- Trigger Binding — connects a published script to a project/issue-type/action so it runs on events or workflow actions (under Automation).
- Timer Rule — runs a script on a schedule (under Automation).
- Dry Run — execute a script to see what it would do, without writing changes.
- Run now — execute an eligible latest published version once against live data; it is neither a Dry Run nor a trigger.
- Execute history — open the Execute Log filtered to a script or Timer Rule.
- Cursor — the paging continuation returned by
issue.search(...), used to read the next page. - Semantic syntax — the readable authoring style that resolves fields/statuses/options by display name.
- Execute Log / Event Log — execution results, and event delivery/rule matching, respectively.
issue.search(...)— the canonical semantic query helper; find issues by conditions and read chosen fields. See Reference → Querying data.- ONESQL — ONES's query language, used inside scripts via
api.queryIssues(...)as an advanced escape hatch.
Changelog
- 1.1.3 — Added native Float and Selection scripted fields, Run now, Timer Rules in seconds/minutes/hours/days, exact execution-history entry points, Cursor paging for
issue.search(...), and caller-mode issue search, update, comment, and status-transition operations under the current requester's permissions. - 1.1.1 — Added
issue.worklogworkflow guards, raw-JSON Dry Run by visible issue key, trusted Project / Issue Type scope resolution with immediate rule activation, and clearer REST endpoint, safe logging, and execution-capacity contracts. - 1.1.0 — Expanded semantic field syntax,
issue.search(...),api.notify(...), linked / hierarchy helpers, and pre-change field reads.
Feedback (early preview). ONEScript is an early preview, shaped by the teams using it. Tell us what your scripts need — share your feedback →