Focalboard Jira 导入器实战:从 Jira XML 导出到 Focalboard 归档的完整迁移指南
2026/9/11 3:24:05 网站建设 项目流程

Focalboard Jira 导入器实战:从 Jira XML 导出到 Focalboard 归档的完整迁移指南

【免费下载链接】focalboardFocalboard is an open source, self-hosted alternative to Trello, Notion, and Asana.项目地址: https://gitcode.com/GitHub_Trending/fo/focalboard

导读

Focalboard 的import/jira目录下内置了一个基于 Node.js 的命令行导入器,它能把 Jira 通过"高级搜索 + XML 导出"得到的数据文件,转换成一个可在 Focalboard 中直接"导入归档"的.boardarchive文件,从而实现从 Jira 到 Focalboard 的自托管迁移。本文以仓库中的 import/jira/README.md 为主体,结合 importJira.ts、jiraImporter.ts 等源码,完整讲解环境准备、命令行用法、字段映射规则、归档格式原理与已知限制,让你读完即可独立完成一次 Jira 数据迁移。

一、迁移原理与整体流程

Jira 导入器是一个独立于 Focalboard 服务端与 WebApp 的 Node 命令行程序,核心入口为 importJira.ts。它不直接访问 Jira API,而是消费 Jira 官方"Export XML"功能生成的标准 RSS/XML 文件。

整条链路可以分为四个阶段:

  1. 导出:在 Jira 高级搜索(Advanced Search)中筛选出所有需要迁移的 Issue,通过Export → Export XML得到本地 XML 文件;
  2. 解析:导入器使用xml2js把 XML 解析为 JavaScript 对象,遍历<channel>下的每一个<item>(对应一条 Jira Issue);
  3. 转换:将每条 Issue 映射为 Focalboard 的 Card(卡片),并为整批数据创建一个 Board(看板)与一个 Board View(视图);
  4. 归档:通过ArchiveUtils.buildBlockArchive把 Board 与 Block 序列化为 Focalboard 的标准归档格式.boardarchive,最后在 Focalboard 界面执行"导入归档"即可。

从源码看,jiraImporter.ts 的run(inputFile, outputFile)函数完整实现了"读取输入 → 校验 → 解析 → 转换 → 写出"的主流程,其返回值为导出的 Block 数量,这也是 jiraImporter.test.ts 断言blockCount === 4的依据(2 张卡片 + 1 个视图 + 1 个文本块等)。

二、环境准备与依赖安装

导入器依赖仓库内两处npm install,缺一不可:

  • WebApp 依赖:导入器直接 import 了../../webapp/src/blocks/下的类型与工厂函数(如createBoardcreateCardcreateTextBlock),因此需要先在focalboard/webapp下安装依赖;
  • 导入器自身依赖import/jira/package.json声明了minimist(命令行参数解析)、xml2js(XML 解析)、turndown(HTML 转 Markdown)三个运行时依赖,以及ts-nodetypescriptjest等开发依赖。

安装命令(建议按顺序执行):

cd focalboard/webapp npm install cd focalboard/import/jira npm install

import/jira/tsconfig.json使用module: commonjstarget: es2019并开启strict严格模式,说明该工具按 CommonJS 模块体系在 Node 环境中运行,配合ts-node可以直接执行 TypeScript 源码,无需预先编译。

三、使用步骤与命令行参数

3.1 在 Jira 中导出 XML

  1. 打开 Jira 的高级搜索(Advanced Search),用 JQL 筛选出需要迁移的所有 Issue;
  2. 点击搜索结果页的Export,选择Export XML
  3. 将文件保存到本地,例如jira_export.xml

仓库中的测试样例 test/jira-export.xml 展示了 Jira XML 导出的真实结构:根节点为<rss version="0.92">,包含<channel>,其中每条 Issue 是一个<item>,内含<title><summary><type><priority><status><resolution><assignee><reporter><created><link><description><comments><attachments><customfields>等元素。文件头部的注释还提示:可以通过field=key&field=summary之类的参数限制导出字段。

3.2 执行导入命令

focalboard/import/jira目录下运行:

npx ts-node importJira.ts -i <path-to-jira.xml> -o archive.boardarchive

参数说明(对应 importJira.ts 的minimist解析逻辑):

参数含义默认值说明
-i输入 Jira XML 文件路径无(必填)缺失时打印用法并退出,文件不存在时以错误码 2 退出
-o输出归档文件路径archive.boardarchive可省略,默认写到当前目录

命令行帮助信息在 jiraImporter.ts 的showHelp()中定义为import -i <input.xml> -o [output.boardarchive]。若输入文件不存在或 XML 中缺少<rss><channel>结构,程序会打印File not foundNo channels in xml等错误并退出。

3.3 在 Focalboard 中导入归档

  1. 打开 Focalboard 应用;
  2. 点击Settings(设置);
  3. 选择Import archive(导入归档);
  4. 选中生成的archive.boardarchive文件。

导入后即可看到一个名为Jira import的看板,其中每条 Jira Issue 对应一张卡片。

3.4 测试与调试脚本

import/jira/package.json提供了两条便捷脚本,可用于验证环境与流程:

npm test # 运行 jest 测试,使用 test/jira-export.xml 执行完整导入 npm run testRun # ts-node importJira.ts -i test/jira_export.xml -o test/jira-import.focalboard

其中npm run debug:test会以node --inspect=5858的方式启动调试端口,方便在 IDE 中逐步跟踪转换逻辑。

四、字段映射规则:Jira Issue → Focalboard Card

转换的核心逻辑集中在 jiraImporter.ts 的convert()函数中。迁移后看板名为Jira import,并创建一个名为Board View的看板视图(boardView.ts 中定义,viewType: 'board')。

4.1 标准属性映射

导入器为看板预置了 8 个卡片属性,其中 6 个为 Select(单选)类型,2 个为 URL / 日期类型:

Jira XML 字段Focalboard 属性名属性类型说明
<priority>Priorityselect优先级,如 Medium
<status>Statusselect状态,如 In Progress、To Do
<resolution>Resolutionselect解决结果,如 Unresolved
<type>Typeselect问题类型,如 Task、Epic
<assignee>Assigneeselect经办人
<reporter>Reporterselect报告人
<link>Original URLurl原始 Issue 链接
<created>Created Datedate创建时间(毫秒时间戳)

Select 属性的选项(Option)由buildCardPropertyFromValues动态生成:先对全部 Issue 的取值去重,再为每个取值生成一个带颜色的 Option。颜色取自optionColors数组(propColorGraypropColorRed共 9 色循环分配),见 jiraImporter.ts 与 board.ts 中IPropertyOption的定义。设置卡片属性值时,setSelectProperty通过optionForPropertyValue按值查找对应 Option 的 ID 写入卡片;Created Date则由Date.parse转换为毫秒时间戳后存储。

4.2 描述文本转换

Jira 的<description>字段会通过turndownService.turndown()从 HTML 转换为 Markdown,然后创建一个text类型的文本块挂在卡片下,并通过card.fields.contentOrder指定其在卡片内容区的顺序(对应 card.ts 中CardFields.contentOrder字段)。转换后的描述文本会同步打印到控制台,便于核对。

4.3 未导入的内容

按 README.md 的说明与源码中的// TODO: Map custom properties注释,以下内容当前不会被导入:

  • 自定义属性(Custom properties)<customfields>下的 Development、Sprint、Rank、Start date 等自定义字段均被忽略;
  • 评论(Comments)<comments>元素不会被转换;
  • 内嵌文件(Embedded files)<attachments>附件不会被转换。

此外,README 明确提醒:Jira 的 XML 导出单次上限为 1000 条 Issue,超过后需要分批导出再分别导入。从实现看,jiraImporter.ts 中buildCardPropertyFromValues只读取了prioritystatus等标准元素,确实未解析<customfields>子节点,与文档所述限制一致。

五、输出归档格式:.boardarchive 的结构原理

导出的.boardarchive并非二进制,而是一种基于 JSON Lines 的文本归档格式,由 import/util/archive.ts 中的ArchiveUtils.buildBlockArchive生成:

  1. 首行为版本头:{"version":1,"date":<时间戳>}
  2. 后续每行是一条记录,格式为{"type":"board"|"block","data":{...}},其中board行承载看板定义(含cardProperties),block行承载视图、卡片、文本块等;
  3. 行与行之间以换行符分隔,末尾空行会被忽略。

对应的ArchiveUtils.parseBlockArchive负责反向解析,它要求首行版本号>= 1且包含date,否则抛出ERROR parsing header;解析时按line.type分发,目前仅处理block类型。正是这套格式保证了导入器生成的归档可以被 Focalboard 的"导入归档"功能无缝识别。

六、验证方式与测试用例

仓库提供了可独立运行的 Jest 测试 jiraImporter.test.ts,它使用test/jira-export.xml作为输入、test/jira.focalboard作为输出,完成两件事:

  1. 数量断言expect(blockCount === 4),验证导入生成了 4 个 Block;
  2. 内容断言:通过ArchiveUtils.parseBlockArchive读回归档,断言其中包含Board View(类型view)、Investigate feature areaInvestigate feature(类型card)。

运行npm test即可复现这一验证流程。测试还展示了run()返回 Block 数量这一返回值契约,以及归档文件可被parseBlockArchive完整读回的特性。

七、已知限制与扩展方向

综合 README 与源码,当前版本的导入器存在以下边界,规划迁移前应提前评估:

  • 单看板迁移:所有 Issue 被导入到名为Jira import的单个看板,不会按项目(Project)或 Epic 拆分多个看板;
  • 1000 条上限:Jira XML 导出单次最多 1000 条 Issue,大数据量需分批导出、多次导入;
  • 用户以文本形式呈现:Assignee、Reporter 仅作为 Select 属性选项存在,不映射为 Focalboard 的成员(Person)属性;
  • 三类内容缺失:自定义属性、评论、附件当前不在导入范围内;
  • 描述仅限单文本块:每条 Issue 的多个描述段落会合并进一个 text 块,不会按段落拆分成多个内容块。

对于自定义属性等缺口,源码在convert()中预留了// TODO: Map custom properties的扩展点,buildCardPropertyFromValues也提供了"从取值集合自动生成 Select 属性"的通用模式,可作为自行扩展 Jira 导入能力的参考起点。

【免费下载链接】focalboardFocalboard is an open source, self-hosted alternative to Trello, Notion, and Asana.项目地址: https://gitcode.com/GitHub_Trending/fo/focalboard

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询