Server-Side Behaviours

While the primary Behaviours engine uses UI Modifications (client-side), ScriptForge also supports server-side behaviour logic that executes in the Forge backend. This is used for scenarios requiring data lookups, REST API calls, or complex validation that can't run purely in the browser.

When to Use Server-Side Logic

Scenario Client (onInit/onChange) Server (makeRequest)
Show/hide a field Not needed
Set a default value Not needed
Look up data from another issue ✅ Use makeRequest
Validate against external data ✅ Use makeRequest
Check user permissions/groups ✅ Use makeRequest

Using makeRequest in Behaviours

The makeRequest(path, options) function lets you call Jira REST APIs from within a behaviour script:

// Look up the project lead and auto-assign
const response = await makeRequest('/rest/api/3/project/' + context.projectKey);
const lead = response.body.lead;

fields.assignee.setDefault(lead.accountId);
fields.assignee.setDescription(`Project lead: ${lead.displayName}`);

Parameters

Parameter Description
path Jira REST API path (e.g., /rest/api/3/issue/PROJ-123)
options Request options: { method: 'GET', headers: {...}, body: {...} }

Examples

Fetch user groups to conditionally show fields:

const me = await makeRequest('/rest/api/3/myself');
const groups = await makeRequest(`/rest/api/3/user/groups?accountId=${me.body.accountId}`);

const isManager = groups.body.some(g => g.name === 'managers');
if (isManager) {
  fields.getFieldById('customfield_10060').setVisible(true); // Budget field
}

Look up linked issues to set validation:

const links = await makeRequest(`/rest/api/3/issue/${context.issueKey}?fields=issuelinks`);
const hasBlocker = links.body.fields.issuelinks.some(
  link => link.type.name === 'Blocks' && link.inwardIssue
);

if (hasBlocker) {
  fields.getFieldById('customfield_10070').setRequired(true); // Dependency note
  fields.getFieldById('customfield_10070').setDescription('Blocked by another issue — explain the dependency');
}

Performance Considerations

  • makeRequest adds latency since it calls the Jira API. Keep calls minimal.
  • Cache results in the script if you need the same data multiple times.
  • Avoid calling makeRequest in onChange handlers for fields that change frequently (like free text) — use it for select fields or buttons.
  • The behaviour must complete quickly (sub-second user experience). If you need heavy processing, consider moving that logic to a listener instead.

Error Handling

If makeRequest fails, your script should handle it gracefully:

try {
  const response = await makeRequest('/rest/api/3/project/' + context.projectKey);
  fields.assignee.setDefault(response.body.lead.accountId);
} catch (err) {
  console.error('Failed to look up project lead:', err.message);
  // Don't crash — just skip the auto-assignment
}

Logging

Use console.log(), console.warn(), and console.error() for debugging. Output appears in the ScriptForge Execution History and can also be viewed in the browser's developer console (for the client-side portion).