# Groovy migration

> Moving ScriptRunner for Jira Cloud Groovy scripts to Oktul Code Studio: the Rovo translator converts each to TypeScript, and what it cannot convert.
>
> Documentation for Oktul Code Studio, for Jira Cloud and Confluence Cloud, by Oktul: https://oktul.com/docs/plugins/code-studio/groovy-migration/

**Code Studio does not run Groovy.** A ScriptRunner Groovy script is imported as source, kept
read-only beside its conversion, and converted to TypeScript by the
[Code Studio translator](../rovo/), a Rovo agent. The TypeScript runs; the Groovy never does.
**ScriptRunner Connect scripts**, which are already TypeScript, run unchanged.

<Steps
  items={[
    {
      title: 'Import the Groovy file into a space',
      body: 'It is stored and shown read-only. In place of a run button it offers Script with Rovo.',
    },
    {
      title: 'Convert it with the translator',
      body: 'Script with Rovo, then convert. The draft is written beside the original: sync.groovy becomes sync.ts.',
    },
    {
      title: 'Read what it could not convert',
      body: 'The translator checks the draft, runs it in the sandbox and reports what it would change and what it left out.',
    },
    {
      title: 'Review and publish',
      body: 'A person reads the draft, runs it in the sandbox again if needed, and an administrator publishes it.',
    },
  ]}
/>

## How calls are converted

| In Groovy | In the conversion |
|---|---|
| ScriptRunner's HAPI (`Issues.getByKey`, `issue.update { }`, `Users.getByAccountId`) | The REST call each makes, through `jira`. HAPI is not recreated |
| `get`, `post`, `put` to this site | `jira`, `confluence` or `assets`, with no token request, since they reach this site directly |
| A token request to `auth.atlassian.com` for another site | A connection of kind Atlassian with a service account |
| Unirest calls to another system | `http` through a connection |
| Script variables | `context.environment.vars` |
| `logger` | `log` |
| `java.time`, `JsonSlurper`, Jackson | Milliseconds and `Date`, `JSON.parse`, plain objects |
| `CompletableFuture`, thread pools | `Promise.all` in chunks within the request budget |
| A listener's `issue`, `changelog`, `comment` bindings | `event.issue`, `event.changelog`, `event.comment` |

The translator writes for cost as well as correctness: the fewest requests, bulk and search
endpoints over one call per item, requests in parallel within the budget, and
`context.checkpoint(state)` in long write loops so a continuation replays little.

## What it cannot convert, or converts differently

- **A fragment is not converted.** Code that is not a whole script, such as a constructor with no
  class around it, is reported as not convertible as written, with what is missing.
- **Nested maps are built explicitly.** Groovy's map constructor fills nested typed properties
  from nested maps; the conversion builds each nested object.
- **Whom it runs as can differ.** A ScriptRunner script runs as ScriptRunner's app user; a Code
  Studio listener runs as the app or the person who caused the event, as the listener says, and
  field and space permissions can differ between the two.
- **A listener sees more.** Code Studio fetches the whole work item before the script runs, so a
  conversion needs no extra read for fields the event left out.
- **A large attachment** that does not fit in a run is marked `// Not converted:` in the draft.
- **Anything the translator could not map** is reported, never guessed silently.

<Aside type="caution" title="Every conversion is a draft">
A conversion is checked and run in the sandbox before anyone sees it, and still needs a person to
read it and an administrator to publish it. Production never runs a draft.
</Aside>

## Common questions

**Does Code Studio run ScriptRunner Groovy scripts?**

No. A Rovo agent converts each Groovy script to TypeScript as a draft, and the TypeScript runs.

**Do ScriptRunner Connect scripts need converting?**

No. They are already TypeScript and run unchanged.

**What happens to ScriptRunner's HAPI calls?**

Each becomes the REST call it makes, through `jira`. HAPI is not recreated.

**Can a converted script go straight to production?**

No. Every conversion is a draft: it runs in the sandbox first, a person reads it and an administrator publishes it.

## Related

- [Rovo agents](../rovo/)
- [Scripts](../scripts/)
- [Connections and variables](../connections-and-variables/)

---

A problem or a question? Write to [support@oktul.com](mailto:support@oktul.com) or open a request in the [Help Center](https://oktul.atlassian.net/servicedesk/customer/portals). Both open a request with a reference and an SLA.
