Migration Helper – User Guide
Restores OSLC integration data after a Jira Data Center to Cloud migration.
The Atlassian Migration Assistant moves your Jira Data Center (DC) projects to Jira Cloud. While issues, attachments, and most project data are transferred correctly, the OSLC Connect for Jira integration data is not — links between Jira issues and external tools (requirements, test cases, architecture elements, etc.) still reference DC-specific internal IDs and URLs that no longer work in Cloud.
This tool finds all affected resources, looks up their new Cloud identifiers using the Atlassian mapping service, and restores the data so that the OSLC integration works again in Jira Cloud.
Links from Jira issues to external OSLC resources such as requirements, test cases, or architecture elements. After migration these links carry stale DC IDs and URLs which no longer resolve correctly.
Associations between Jira project versions and Global Configuration (GC) streams or baselines. These are completely lost during migration and need to be restored.
Connections between Jira projects and external OSLC project areas. These define which link types (e.g. "Implements Requirement") are available in a Jira project. They are also lost during migration.
Mappings between OSLC link types and Jira version fields (affects-version or fix-version). These control which Global Configuration is associated to a link, and are not migrated natively by JCMA.
The process follows a fixed sequence of steps. The Indexer and the Updater are the two main programs in this package.
Your Jira projects are migrated using Atlassian's tool. After the migration, the Atlassian mapping service is available and holds a complete table of DC resource IDs mapped to their new Cloud IDs. This is the starting point for this tool.
The Indexer connects to your Jira DC instance, reads all OSLC-related data, and resolves the corresponding Cloud IDs from the DC→Cloud ID mapping. It then writes one Excel file per project to a folder you specify. Each file contains one sheet per resource type.
Open the generated Excel files and inspect the results. Each row represents one resource and shows its current status. You can optionally mark rows to be skipped or reprocessed before moving on.
The Updater reads the Excel files and posts the corrected data to Jira Cloud and the OSLC Connect broker. The outcome of each row is written back into the same file.
Open Jira Cloud, navigate the migrated projects, and confirm that OSLC links, GC version associations, and project link types are all working correctly.
CHANGED so the Updater posts it again; rows where nothing changed are left
untouched, whatever their status. The Updater skips rows already UPDATED and retries
failed ones. If additional projects are migrated between 2 runs, they will be visible to the new
run scope (--all-projects or --projects).
| Component | Requirement | Notes |
|---|---|---|
| Java | Version 21 or later | The java executable must be available on the system PATH.
Run java -version to check. |
| Jira Data Center | Version 10 or 11 | The Atlassian Cloud Migration Assistant must have been used to migrate at least one
project. Unless a CSV mapping file is provided with --idmappings, the
ID mapping service endpoint
(/rest/migration/latest/report/id-mappings) must be accessible from the
machine running this tool. |
| Jira Cloud | Any current version | Projects must already have been migrated. A dedicated service account with project administration permissions is strongly recommended. |
| OSLC Connect for Jira Cloud (broker) | Any supported version | The broker must be running and reachable over the network from the machine executing this tool. |
project_associations, the remote OSLC applications (service providers) that
the Jira projects were associated with must already be registered as friend
applications in the OSLC Connect Cloud broker. If they are not registered, the POST
request will fail. Run the Updater with --verify first: it reports, per project,
the applications that are not registered.
When running the Indexer in database mode, the Jira DC database is accessed directly. The following engine is supported:
The machine running this tool must be able to reach all of the following:
*.atlassian.net and/or api.atlassian.com)Three properties files control how the tool connects to each system. Template files for all three are included in this package. Edit them with a plain text editor before running anything.
Configures access to your Jira Cloud tenant and the OSLC Connect broker.
| Property | What to enter |
|---|---|
rest.baseUrl |
Your Jira Cloud tenant URL, e.g. https://your-org.atlassian.net |
rest.username |
The email address of the Jira Cloud account used for API calls. A dedicated service account is recommended over a personal account. |
rest.token |
An API token generated from the Atlassian account settings of
the user above. API tokens are distinct from passwords and can be created at
id.atlassian.com.
Expiry: Atlassian API tokens expire after at most one year
(policy in effect since December 2024). Plan to rotate the token before it
expires to avoid service interruption.
|
cloud.cloudId |
(Recommended) Your Jira Cloud site ID. When provided, all
Cloud REST calls use the Atlassian API gateway
(https://api.atlassian.com/ex/jira/<cloudId>/...), which is
Atlassian's recommended approach for server-to-server integration.To find your Cloud ID, open a browser and fetch: https://your-org.atlassian.net/_edge/tenant_info — the
cloudId field in the JSON response is the value to enter here.If this property is left blank, rest.baseUrl is used as a fallback
and a warning is logged.
|
broker.baseUrl |
The base URL of the OSLC Connect for Jira broker application, including the
context path, e.g. https://broker.example.com/oslc-connect-jira.
Required by the Updater, which exits with code 2 if it is blank. |
rest.timeoutMs |
(Optional) Timeout of each HTTP request, in milliseconds. Defaults to
30000. |
rest.baseUrl, rest.username and rest.token are
required.
Configures access to the Jira DC REST API. This file is used in two situations:
--rest flag),
as an alternative to direct database access. The same configuration is also used
to reach the Atlassian ID mapping service, unless --idmappings is
provided with a CSV mapping file to override it.--db flag),
this properties file can be passed via --idmappings to fetch DC→Cloud ID
mappings from the Atlassian migration service. Alternatively,
--idmappings can point to a pre-downloaded CSV mapping file instead.| Property | What to enter |
|---|---|
rest.baseUrl |
Base URL of the Jira DC instance, including any application context path,
e.g. https://jira-dc.example.com/jira. |
rest.username |
Jira DC username. Must have read access to all projects being indexed. |
rest.password |
Password for the Jira DC user above. |
rest.timeoutMs |
(Optional) Timeout of each HTTP request, in milliseconds. Defaults to
30000. |
rest.batchSize |
(Optional) Number of issues fetched per page in REST mode. Defaults to
500. |
rest.baseUrl, rest.username and rest.password are
required.
Configures a direct JDBC connection to the Jira DC database. Only needed
when running the Indexer in database mode (--db flag). If you prefer to use
the REST API instead, this file is not required.
| Property | What to enter |
|---|---|
db.url |
JDBC connection URL, e.g. jdbc:postgresql://dbhost:5432/jiradb. |
db.username |
Database username. The same user Jira uses to connect is normally sufficient. Read-only access is enough for the Indexer. |
db.password |
Database password for the user above. |
db.dialect |
Database engine: postgresql (or postgres). |
db.batchSize |
(Optional) Maximum number of project IDs or keys per database query. Defaults to
100. |
db.url, db.username, db.password and
db.dialect are required.
config/cloud.properties and fill in your Jira Cloud tenant URL, service account
credentials, Cloud site ID, and broker URL.config/rest.properties and fill in your Jira DC base URL and credentials.
It is needed in REST mode, and in database mode unless you provide a CSV mapping file with
--idmappings.config/db.properties and fill in your Jira DC database connection details.Open a terminal in the folder where this package is installed and run one of the commands below. The Indexer will load the DC→Cloud ID mapping table first, then read OSLC data from Jira DC, and finally write one Excel file per project into the output folder you specify.
--projects). Projects the Cloud account cannot administer are skipped
with a warning too.
Connects directly to the Jira DC database. More efficient, no pagination.
Requires: config/db.properties +
--idmappings (REST properties file or CSV mapping file)
Uses the Jira DC REST API. Useful when direct database access is not
available. The same config/rest.properties file is used for both data
access and the ID mapping service, unless --idmappings is provided
with a CSV mapping file.
Requires: config/rest.properties only
.sh file for the first
time, grant the permission with:
chmod +x bin/index.sh bin/update.sh
Windows:
bin\index.bat --db config\db.properties --idmappings config\rest.properties --cloud config\cloud.properties --all-projects --dir output\
Linux:
bin/index.sh --db config/db.properties --idmappings config/rest.properties --cloud config/cloud.properties --all-projects --dir output/
bin\index.bat --db config\db.properties --idmappings path\to\mappings.csv --cloud config\cloud.properties --all-projects --dir output\
bin\index.bat --rest config\rest.properties --cloud config\cloud.properties --all-projects --dir output\
bin\index.bat --rest config\rest.properties --idmappings path\to\mappings.csv --cloud config\cloud.properties --all-projects --dir output\
bin\index.bat --db config\db.properties --idmappings config\rest.properties --cloud config\cloud.properties --projects PROJ1,PROJ2 --dir output\
| Option | Description |
|---|---|
--cloud <file> |
Path to config/cloud.properties. Always required. |
--db <file> |
Path to config/db.properties. Use for database mode. Cannot be combined
with --rest. |
--rest <file> |
Path to config/rest.properties. Use for REST mode. Cannot be combined
with --db. |
--idmappings <file> |
DC→Cloud ID mapping source: a REST properties file to fetch it from
the Atlassian migration service, or a CSV mapping file. Required when using
--db. When used with --rest, only CSV files are accepted
since the REST configuration is already provided. A file is read as CSV when its
first line starts with entityType,. |
--all-projects |
Process every Jira DC project that has been migrated to Cloud. Cannot be combined
with --projects. |
--projects <keys> |
Comma-separated list of project keys to process, e.g.
PROJ1,PROJ2. Cannot be combined with
--all-projects. |
--resource-types <types> |
Comma-separated list of resource types to index:
remote_links, gc_versions,
project_associations, linktype_deliverables. Defaults to all types.
Values are case-sensitive; an unknown value is ignored. |
--dir <path> |
Folder where Excel files are written. Defaults to the current directory. |
The projects of the migration files already in --dir are always indexed again, so
that a re-run keeps them up to date. --projects adds projects to those: with
--projects PROJ1 and an existing file for PROJ2, both are indexed.
When --dir already holds migration files, neither --all-projects nor
--projects is needed. To index a single project, use a --dir holding no
file of other projects.
Both the Indexer and the Updater exit with 0 on success, 1 when the run
fails, and 2 on invalid arguments.
After the Indexer finishes, you will find one Excel file per project in the output folder.
Projects with no migratable resources produce no file and are skipped and logged.
Each file is named jira$<PROJECT-KEY>$<DC-PROJECT-ID>$migration.xlsx.
output/ jira$PROJ1$10000$migration.xlsx jira$PROJ2$10001$migration.xlsx ...
Each file contains one worksheet per resource type:
remote_links, gc_versions, project_associations,
and linktype_deliverables.
The scripts are pre-configured to load config/logback.xml. By
default that file sends log output to two destinations simultaneously:
~/oslc-connect-jira-cloud-migration/logs/migration.log and rotated daily.
Up to 10 compressed daily archives are kept (total cap 2 GB).You can customize config/logback.xml with a text editor at any time:
level attribute on the
<root> element (e.g. INFO → DEBUG for
verbose output).LOG_LOCATION
property (default: ${user.home}/oslc-connect-jira-cloud-migration/logs).<appender-ref ref="FILE"/> inside <root>
to disable file logging and keep console output only.Open the generated Excel files and review the results before running the Updater. Each row
represents one resource and includes a status column that tells you the outcome of
the indexing step.
| Status | Meaning | What to do |
|---|---|---|
INDEXED |
Cloud ID found. This record is ready to be updated. | Nothing — the Updater will process it automatically. |
FAILED_INDEX |
An error occurred while reading from Jira DC or the mapping service. | Check the status_detail column for the error message. Resolve the issue
and re-run the Indexer. |
CHANGED |
The resource properties or its Cloud ID changed since the last Indexer run. | Nothing — the Updater will post it again. |
→ Full list of all status values in the Appendix
You can manually edit the status column of any row to control how the Updater
handles it:
OMIT to intentionally skip a record (e.g. a link that
should not be restored).REPROCESS to force the Updater to re-post a record even
if it was previously completed successfully.old_id, new_id, resource data
columns) — those values are used by the Updater to construct the API calls and must
remain intact.
The Updater reads the Excel files produced by the Indexer and sends most indexed data to Jira
Cloud and the OSLC Connect broker. If linktype_deliverables were indexed, there will
be a .properties file generated in the --dir folder per indexed project; this
file(s) must be deployed in the Tomcat server manually. See manual step below for details.
The outcome of each row is written back into the same files, so you always have a full audit trail.
Note: depending on the project size, this may be a long operation. It's been observed to
take up to 40 minutes when there are around 10K links to fix.
chmod +x bin/index.sh bin/update.sh
bin\update.bat --cloud config\cloud.properties --all-projects --dir input\
bin/update.sh --cloud config/cloud.properties --all-projects --dir input/
bin/update.sh --cloud config/cloud.properties --projects PROJ,DEMO --dir input/
Use --verify to parse and validate all input files without sending any update. It
also checks that the Cloud credentials can administer every project and that the remote
applications the projects are associated with are registered as friends in the broker; projects
failing a check are reported and skipped. Useful to check the state of the working directory
before committing updates. Note that:
--verify again..properties deliverable file is written: its content is logged instead.--verify does not make these checks.bin\update.bat --cloud config\cloud.properties --all-projects --dir input\ --verify
| Option | Description |
|---|---|
--cloud <file> |
Path to config/cloud.properties. Always required. |
--all-projects |
Process all migration files found in the --dir folder.
Mutually exclusive with --projects.
Either this or --projects is required. |
--projects <KEYS> |
Comma-separated list of project keys to update (e.g. PROJ,DEMO).
Only migration files matching the given keys are processed.
Mutually exclusive with --all-projects. |
--dir <path> |
Folder containing the Excel files produced by the Indexer. Defaults to the current directory. |
--verify |
Dry-run mode: parses and validates all input files, checks administrator rights and friend registrations, without sending any update. |
--idmappings <file> |
DC→Cloud ID mapping CSV file used by --verify to check administrator
rights. Defaults to the latest id-mappings_*.csv file in --dir. |
update,
copy the generated .properties file(s) to the directory designated
by the broker's oslc.broker.deliverable-type-mapping.location context parameter.
UPDATED, OMIT and
FAILED_INDEX rows are always skipped, as are rows with an empty or unknown status
(with a warning). FAILED_UPDATE rows are retried automatically with no data loss.
No special flags are needed to resume after a partial failure.
After the Updater finishes, verify that the migration was successful:
UPDATED. Any rows still showing
FAILED_UPDATE indicate records that could not be posted — check the
status_detail column for the error and consider re-running the Updater after
resolving it.linktype_deliverables were indexed/updated, verify issues using
a Global Configuration also resolve to the expected versioned remote artifact.
One way to quickly find issues having remote links is using the advanced (JQL)
search in Jira Cloud. Pick some issue ids from any of the Excel files (from the
issue_id column in the remote_links tab) and use them in the Jira
Cloud Search work items page. Select the JQL mode and type id in ()
in the input field putting the issue ids in the parenthesis separated by commas.UPDATED are
skipped; rows marked FAILED_UPDATE are retried automatically.
The tables below describe, for each resource type, exactly where the data is read from in Jira DC and where it is written to in Jira Cloud or the OSLC Connect broker.
| Database mode | REST mode | |
|---|---|---|
| Source in Jira DC |
Table: remotelinkScoped by: issueid IN (SELECT id FROM jiraissue WHERE project = :projectId)
|
GET /rest/api/2/search?jql=project=<id> (to list issues; when
ScriptRunner is installed, the query only returns issues having OSLC remote links)GET /rest/api/2/issue/<key>/remotelink (per issue)
|
| Destination in Cloud |
PUT /rest/api/3/issue/<cloudIssueId>/remotelink/<cloudRemoteLinkId>
|
|
| ID mappings used |
jira:remoteLink → Cloud remote link IDjira:issue → Cloud issue ID (owner of the link)
|
|
| Database mode | REST mode | |
|---|---|---|
| Source in Jira DC |
Table: AO_E78B5C_GCVERSION_ASS_ENTITYScoped by: versionId IN (SELECT id FROM projectversion WHERE project = :projectId)
|
GET /rest/oslc/1.0/internal/linking/version?projectId=<id>
|
| Destination in broker |
PUT <brokerBaseUrl>/process/project-area/<cloudProjectId>/gc/deliverable/<cloudVersionId>?saveLocallyOnly=true
Before the first version update, a separate PUT .../process/project-area/<cloudProjectId>/gc
is sent to enable Configuration Management on the project area (once per updater instance).
|
|
| ID mappings used |
jira/classic:project → Cloud project IDjira:projectVersion → Cloud version ID
|
|
| Database mode | REST mode | |
|---|---|---|
| Source in Jira DC |
JOIN of AO_E78B5C_ASSOCIATION_ENTITY and
AO_E78B5C_RMT_PROJECT_ENTITYFiltered by: PROJECT_ID = :projectId
|
GET /rest/oslc/1.0/internal/process/project-area/<projectId>/association
|
| Destination in broker |
POST <brokerBaseUrl>/process/project-area/<cloudProjectId>/associationAll the rows of a project are sent in a single POST, covering all link types for all remote projects. |
|
| ID mappings used |
jira/classic:project → Cloud project ID
|
|
| Database mode | REST mode | |
|---|---|---|
| Source in Jira DC |
Table: AO_E78B5C_LINK_FLD_ASS_ENTITYFiltered by: PROJECT = :projectId
|
GET /rest/oslc/1.0/internal/linking/version/fieldMapping?projectId=<id>
|
| Output |
No REST call is made. Instead, the Updater writes a properties file to the
--dir folder:linkType_<cloudProjectId>_deliverables.propertiesEach entry maps a link type name to a deliverable field identifier: FOUND_IN (affects-version) or
PLANNED_FOR (fix-version).
Manual step required: Do not forget to copy the generated
.properties file(s) to the directory defined by the broker's
oslc.broker.deliverable-type-mapping.location context parameter.
|
|
| ID mappings used |
jira/classic:project → Cloud project ID
|
|
The status column in each Excel sheet can hold the following values:
| Value | Set by | Meaning |
|---|---|---|
INDEXED |
Indexer | DC ID successfully mapped to a Cloud ID. Ready for the Updater. |
FAILED_INDEX |
Indexer | The resource could not be indexed, most often because no Cloud mapping was found
for its DC ID. Verify the correct id-mappings file was used or if the resource was
created after the migration ran. See the status_detail
column for the exact cause. The Updater skips rows with this status. |
CHANGED |
Indexer | The resource properties or its Cloud ID changed since the last Indexer run (e.g. after a Jira re-migration). The row will be re-posted on the next Updater run. |
UPDATED |
Updater | Successfully posted to Jira Cloud or the OSLC Connect broker. |
FAILED_UPDATE |
Updater | The post to Cloud or the broker failed. The row will be retried automatically on the next Updater run. |
OMIT |
User | Intentionally skipped. The Updater will not process this row. |
REPROCESS |
User | Force the Updater to re-post this row even if it was previously
UPDATED. |
Before any data is read from Jira DC, the Indexer loads the complete DC→Cloud ID
mapping table. By default it is fetched in a single call to the Atlassian mapping service
(part of the Atlassian Cloud Migration Assistant), but it can also be loaded from a
pre-downloaded CSV file via --idmappings.
Endpoint called:
GET <dcBaseUrl>/rest/migration/latest/report/id-mappings
?cloudSiteUrl=<cloudBaseUrl>&invalidateCache=false
The response is a CSV file with this format:
entityType,serverId,cloudId jira:remoteLink,11001,10665 jira/classic:project,10100,10198 ...
The following entity types are extracted and used by this tool. All others are silently ignored.
| Entity type in CSV | Used for |
|---|---|
jira/classic:project |
Identifies which DC projects have been migrated; provides the Cloud project ID used in GC version and association updates. |
jira:issue |
Resolves Cloud issue IDs — needed to build the remote link update URL. |
jira:remoteLink |
Resolves Cloud remote link IDs. |
jira:projectVersion |
Resolves Cloud project version IDs for GC version link updates. |
When fetched via REST and the mapping report is not yet ready, the call is retried up to 5 times with 10-second delays between attempts. HTTP or network errors are retried up to 3 times, with the same delay. If the report is still unavailable after all retries, the run aborts with a clear message and no files are written.
On success, the fetched CSV is saved to the output directory as
id-mappings_<timestamp>.csv (e.g.
id-mappings_20260612_143052.csv) for traceability and later reuse. The Updater's
--verify reads the latest of these files to check administrator rights.