从 Jira 导出

导出会读取你指定的项目并写出一个导入包。先小规模试一下,检查结果没问题,再做正式导出。

试运行

--limit 20 只导出每个项目的前 20 个工作项(按工作项编号从旧到新)。这是检查凭据、权限以及文本和字段转换效果最快的方法。

specivo-jira-migration --project ACME --out trial-export --limit 20 --validate

--validate 会在导入包写完后检查它,所用的检查与 Specivo 导入时相同。工具会输出导入包的路径和一行写入内容的摘要,一切顺利时以 0 退出。

整站导出为一个包

列出你要导出的每个项目:

specivo-jira-migration --project ACME --project OPS --project SUP \
    --out jira-export --validate

(写成 --project ACME,OPS,SUP 效果相同。)结果是一个 目录,内含 manifest.json、lookups.json、每种记录各一个 .jsonl 文件,以及存放附件内容的 files/。加上 --zip,或者让 --out 以 .zip 结尾,就会改为写出单个压缩包。

按项目分批导出

大站点分批迁移更省事,各部分还可以在不同时间导出。对每个项目(或一组项目)各运行一次工具,每次使用 相同的站点名称:

specivo-jira-migration --project ACME --out exports/acme --validate
specivo-jira-migration --project OPS  --out exports/ops  --validate

分属不同导入包的项目之间的链接、父工作项和工作项提及,会写进持有其中一端的每个导入包里,另一端的工作项以其 Jira id 标识。无论先加载哪个包,Specivo 都会在两端的工作项都导入后再建立这些关系。要让这一机制生效:

  • 每个部分都用相同的 --instance 导出(默认值是站点主机名,本来就相同);
  • 把各部分依次加载到同一个 Specivo 中,从第二个起加上 --continue-import;
  • 每次加载都传入相同的 --links-file,或者把所有导入包放在同一个目录下,让默认位置共用。参见校验与加载。

--validate 会把这类跨包引用报告为 external_ref 警告。对分批导出的部分来说,这是正常现象。

选项

选项 含义
--url URL Jira 站点地址(默认:$JIRA_URL)。
--email、--api-token Jira Cloud 凭据(默认:$JIRA_EMAIL、$JIRA_API_TOKEN)。
--pat TOKEN Jira Data Center 个人访问令牌(默认:$JIRA_PAT)。
--project KEY 要导出的项目。可重复指定,也可用逗号分隔(默认:$JIRA_PROJECTS)。
--instance NAME 站点在导入包中的名称(默认:站点主机名)。
--out PATH 新目录或空目录,或者一个 .zip 路径。必填。
--zip 写出 .zip 而不是目录。
--status-category-map NAME=CATEGORY,... 把状态归入 Specivo 的 backlog / active / done / closed 四类。默认由 Jira 的状态类别决定:待办(To Do)归入 backlog,进行中(In Progress)归入 active,完成(Done)归入 closed。
--max-attachment-size SIZE 跳过大于此大小的附件,例如 500M 或 2G;0 表示不限制。默认 100M。被跳过的文件数会记录在 manifest 中。
--no-resolve-keys 不向 Jira 查询导入包之外的工作项编号(出现在文本和 Epic Link 字段中的)。它们保持为纯文本。
--limit N 每个项目最多导出 N 个工作项,按工作项编号从旧到新。用于试运行。
--page-size N 列表请求的每页条目数(默认 100)。
--keep-state 运行成功后保留状态目录。
--restart 丢弃上一次未完成运行的状态,重新开始。
--validate 导入包写完后按 Specivo 的方式检查它。
--quiet 只输出错误。进度信息写到 stderr,导入包路径写到 stdout。
--version 输出工具版本。

退出状态:成功为 0;导出失败或 --validate 发现问题为 1;用法错误(包括项目不存在)为 2。

映射状态

Specivo 把每个状态归入四个类别之一(backlog、active、done、closed),看板和报表都依据这些类别。工具默认沿用 Jira 自身的状态类别。可按名称覆盖单个状态:

specivo-jira-migration --project ACME --out jira-export \
    --status-category-map "In Review=active,Won't Do=closed"

运行中断时

工具从 Jira 读到的所有内容都会随到随存,放在输出路径旁的 状态目录 中(jira-export.jira-state/)。如果运行中断(网络故障、限流后放弃重试、Ctrl-C),再运行一次同样的命令 即可:

  • 已列出的项目不再重新列出,已读取的工作项不再重新读取;
  • 已获取的关注者不再重新请求;
  • 已下载且哈希值仍与记录一致的附件不再重新下载。正在下载的文件以临时名写入,运行中断时丢弃;
  • 用更大的 --max-attachment-size 再运行一次,会补下载之前因大小限制跳过的附件。

用其他选项(另一个站点、其他项目、不同的 --limit)生成的状态会被拒绝使用;传 --restart 可丢弃它。由本工具其他版本写入的状态同样会被拒绝。

导入包仅由状态生成,且顺序固定,因此同一状态总会产生逐字节相同的导入包。

状态目录保存的是 Jira 返回的原始内容

其中包括人员的电子邮件地址。该目录创建时只有你本人可读,导入包写完后会被删除,除非你传了 --keep-state。用完后请自行删除。

限流

Jira Cloud 会限制客户端的调用频率。工具请求过快时,Jira 会返回 429 Too Many Requests(有时是 503),且不一定带 Retry-After 头。工具对这类请求最多重试六次:至少等待 Retry-After 要求的时间(上限十分钟),没有该头时则按指数退避并加入随机抖动,每次等待都会记录日志。如果重试后请求仍然失败,运行会停止,可按上文所述续跑。

附件逐个下载,不并行。

附件与凭据

在 Jira Cloud 上,文件通过附件内容端点读取,该端点会重定向到一个媒体主机,地址中带有短期有效的令牌。工具自行逐跳跟随重定向,只向 --url 指定的站点(协议、主机和端口均相同)发送你的凭据。跳转到任何其他主机时,使用不带凭据、不带 cookie 的独立客户端;从 https 到 http 的重定向会被拒绝。媒体令牌不会写入日志。在 Data Center 上,如果附件地址在站点内,就直接使用附件自身的地址。

每个文件边下载边写入磁盘并计算哈希。大小限制会先根据 Jira 报告的大小检查,收到数据后再根据实际字节数检查一次。