跳至主要内容

使用 GitHub Actions Importer 从 GitLab 迁移

了解如何使用 GitHub Actions Importer 自动将您的 GitLab 管道迁移到 GitHub Actions。

法律声明

关于使用 GitHub Actions Importer 从 GitLab 迁移

以下说明将指导您配置环境以使用 GitHub Actions Importer 将 GitLab 管道迁移到 GitHub Actions。

先决条件

  • 一个 GitLab 帐户或组织,其中包含您要转换为 GitHub Actions 工作流的管道和作业。

  • 访问权限,以便为您的帐户或组织创建 GitLab 个人访问令牌。

  • 一个可以运行基于 Linux 的容器的环境,并且可以安装必要的工具。

    注意:GitHub Actions 导入器容器和 CLI 不需要安装在与您的 CI 平台相同的服务器上。

限制

使用 GitHub Actions 导入器将 GitLab 管道自动迁移到 GitHub Actions 存在一些限制。

  • 不支持不同工作流作业之间的自动缓存。
  • audit 命令仅在使用组织帐户时受支持。但是,dry-runmigrate 命令可以使用组织或用户帐户。

手动任务

某些 GitLab 结构必须手动迁移。这些包括

  • 屏蔽的项目或组变量值
  • 工件报告

有关手动迁移的更多信息,请参阅“从 GitLab CI/CD 迁移到 GitHub Actions”。

安装 GitHub Actions 导入器 CLI 扩展

  1. 安装 GitHub Actions 导入器 CLI 扩展

    Bash
    gh extension install github/gh-actions-importer
    
  2. 验证扩展是否已安装

    $ gh actions-importer -h
    Options:
      -?, -h, --help  Show help and usage information
    
    Commands:
      update     Update to the latest version of GitHub Actions Importer.
      version    Display the version of GitHub Actions Importer.
      configure  Start an interactive prompt to configure credentials used to authenticate with your CI server(s).
      audit      Plan your CI/CD migration by analyzing your current CI/CD footprint.
      forecast   Forecast GitHub Actions usage from historical pipeline utilization.
      dry-run    Convert a pipeline to a GitHub Actions workflow and output its yaml file.
      migrate    Convert a pipeline to a GitHub Actions workflow and open a pull request with the changes.
    

配置凭据

configure CLI 命令用于在使用 GitLab 和 GitHub 时设置 GitHub Actions 导入器所需的凭据和选项。

  1. 创建一个 GitHub 个人访问令牌(经典)。有关更多信息,请参阅“管理您的个人访问令牌”。

    您的令牌必须具有 workflow 范围。

    创建令牌后,将其复制并保存在安全位置以备后用。

  2. 创建一个 GitLab 个人访问令牌。有关更多信息,请参阅 GitLab 文档中的 个人访问令牌

    您的令牌必须具有 read_api 范围。

    创建令牌后,将其复制并保存在安全位置以备后用。

  3. 在您的终端中,运行 GitHub Actions 导入器 configure CLI 命令

    gh actions-importer configure
    

    configure 命令将提示您输入以下信息

    • 对于“您要配置哪些 CI 提供商?”,使用箭头键选择GitLab,按 空格键 选择它,然后按 回车键
    • 对于“GitHub 的个人访问令牌”,输入您之前创建的个人访问令牌(经典)的值,然后按 回车键
    • 对于“GitHub 实例的基准 URL”,按 回车键 接受默认值(https://github.com)。
    • 对于“GitLab 的私有令牌”,输入您之前创建的 GitLab 个人访问令牌的值,然后按 回车键
    • 对于“GitLab 实例的基准 URL”,输入您的 GitLab 实例的 URL,然后按 回车键

    下面显示了configure 命令输出的示例。

    $ gh actions-importer configure
    ✔ Which CI providers are you configuring?: GitLab
    Enter the following values (leave empty to omit):
    ✔ Personal access token for GitHub: ***************
    ✔ Base url of the GitHub instance: https://github.com
    ✔ Private token for GitLab: ***************
    ✔ Base url of the GitLab instance: https://127.0.0.1
    Environment variables successfully updated.
    
  4. 在您的终端中,运行 GitHub Actions Importer update CLI 命令以连接到 GitHub Packages 容器注册表并确保容器镜像更新到最新版本

    gh actions-importer update
    

    命令的输出应类似于以下内容

    Updating ghcr.io/actions-importer/cli:latest...
    ghcr.io/actions-importer/cli:latest up-to-date
    

执行 GitLab 的审计

您可以使用audit 命令来获取 GitLab 服务器中所有管道的概览。

audit 命令执行以下步骤

  1. 获取 GitLab 服务器中定义的所有项目。
  2. 将每个管道转换为等效的 GitHub Actions 工作流程。
  3. 生成一份报告,总结使用 GitHub Actions Importer 可以实现的迁移的完整性和复杂程度。

审计命令的先决条件

为了使用audit 命令,您必须配置一个与 GitLab 组织帐户关联的个人访问令牌。

运行审计命令

要执行 GitLab 服务器的审计,请在您的终端中运行以下命令,将my-gitlab-namespace 替换为您要审计的命名空间或组

gh actions-importer audit gitlab --output-dir tmp/audit --namespace my-gitlab-namespace

检查审计结果

指定输出目录中的文件包含审计结果。请参阅audit_summary.md 文件以获取审计结果的摘要。

审计摘要包含以下部分。

管道

“管道”部分包含有关 GitHub Actions Importer 完成的转换率的概况统计信息。

下面列出了一些可能出现在“管道”部分中的关键术语

  • 成功的管道已将 100% 的管道结构和单个项目自动转换为等效的 GitHub Actions。
  • 部分成功 的管道已将所有管道结构转换为 GitHub Actions 等效项,但是,某些单独的项目未自动转换为 GitHub Actions 等效项。
  • 不支持 的管道是 GitHub Actions 导入器不支持的定义类型。
  • 失败 的管道在转换时遇到致命错误。这可能由于以下三种原因之一而发生
    • 管道配置错误,在 Bamboo 中无效。
    • GitHub Actions 导入器在转换时遇到内部错误。
    • 网络响应不成功,导致管道无法访问,这通常是由于凭据无效所致。

构建步骤

"构建步骤" 部分概述了所有管道中使用的各个构建步骤,以及 GitHub Actions 导入器自动转换了多少个步骤。

以下是“构建步骤”部分中可能出现的一些关键术语

  • 已知 构建步骤是已自动转换为等效操作的步骤。
  • 未知 构建步骤是未自动转换为等效操作的步骤。
  • 不支持 的构建步骤是以下两种情况之一
    • GitHub Actions 从根本上不支持。
    • 配置方式与 GitHub Actions 不兼容。
  • 操作 是已在转换的工作流程中使用的操作列表。这对于以下情况可能很重要
    • 如果您使用的是 GitHub Enterprise Server,则收集要同步到您的实例的操作列表。
    • 定义组织级允许的操作列表。此操作列表是安全或合规团队可能需要审查的操作的综合列表。

手动任务

"手动任务" 部分概述了 GitHub Actions 导入器无法自动完成的任务,您必须手动完成这些任务。

以下是“手动任务”部分中可能出现的一些关键术语

  • 秘密 是在转换的管道中使用的存储库或组织级秘密。必须在 GitHub Actions 中手动创建这些秘密,才能使这些管道正常运行。有关更多信息,请参阅 "在 GitHub Actions 中使用秘密。"。
  • **自托管运行器**指的是在转换后的管道中引用但不是 GitHub 托管运行器的运行器标签。您需要手动定义这些运行器才能使这些管道正常运行。

文件

审计报告的最后一部分提供了在审计期间写入磁盘的所有文件的清单。

每个管道文件都包含审计中包含的各种文件,包括

  • 在 GitHub 中定义的原始管道。
  • 用于转换管道的任何网络响应。
  • 转换后的工作流程文件。
  • 可用于排查管道转换失败的堆栈跟踪。

此外,workflow_usage.csv 文件包含每个成功转换的管道使用的所有操作、秘密和运行器的逗号分隔列表。这对于确定哪些工作流程使用哪些操作、秘密或运行器很有用,并且可以用于执行安全审查。

预测潜在的构建运行器使用情况

您可以使用 forecast 命令通过计算 GitLab 服务器中已完成的管道运行的指标来预测潜在的 GitHub Actions 使用情况。

运行预测命令

要执行潜在 GitHub Actions 使用情况的预测,请在您的终端中运行以下命令,将 my-gitlab-namespace 替换为您要预测的命名空间或组。默认情况下,GitHub Actions Importer 会在预测报告中包含前七天。

gh actions-importer forecast gitlab --output-dir tmp/forecast --namespace my-gitlab-namespace

预测整个命名空间

要预测整个命名空间及其所有子组,您必须在 --namespace 参数或 NAMESPACE 环境变量中指定每个子组。

例如

gh actions-importer forecast gitlab --namespace my-gitlab-namespace my-gitlab-namespace/subgroup-one my-gitlab-namespace/subgroup-two ...

检查预测报告

指定输出目录中的 forecast_report.md 文件包含预测结果。

以下是预测报告中可能出现的一些关键术语

  • **作业数**是已完成作业的总数。
  • **管道数**是使用的唯一管道的数量。
  • **执行时间**描述了运行器在作业上花费的时间。此指标可用于帮助规划 GitHub 托管运行器的成本。
    • 此指标与您在 GitHub Actions 中预计的支出相关。这将根据用于这些分钟的硬件而有所不同。您可以使用 GitHub Actions 定价计算器 来估算成本。
  • 队列时间指标描述了作业等待运行器可用以执行其所花费的时间。
  • 并发作业指标描述了在任何给定时间运行的作业数量。此指标可用于定义应配置的运行器数量。

此外,这些指标针对 GitLab 中的每个运行器队列进行定义。如果存在托管或自托管运行器,或高规格或低规格机器的混合,这将特别有用,因此您可以查看特定于不同类型运行器的指标。

执行 GitLab 管道的干运行迁移

您可以使用 dry-run 命令将 GitLab 管道转换为等效的 GitHub Actions 工作流程。

运行干运行命令

您可以使用 dry-run 命令将 GitLab 管道转换为等效的 GitHub Actions 工作流程。干运行会在指定目录中创建输出文件,但不会打开拉取请求以迁移管道。

要执行将 GitLab 管道迁移到 GitHub Actions 的干运行,请在您的终端中运行以下命令,将 my-gitlab-project 替换为您的 GitLab 项目的 URL,将 my-gitlab-namespace 替换为您正在执行干运行的命名空间或组。

gh actions-importer dry-run gitlab --output-dir tmp/dry-run --namespace my-gitlab-namespace --project my-gitlab-project

检查转换后的工作流程

您可以在指定的输出目录中查看干运行的日志和转换后的工作流程文件。

如果 GitHub Actions Importer 无法自动转换任何内容,例如未知构建步骤或部分成功的管道,您可能需要创建自定义转换器以进一步自定义转换过程。有关更多信息,请参阅 "使用自定义转换器扩展 GitHub Actions Importer。"。

执行 GitLab 管道的生产迁移

您可以使用 migrate 命令转换 GitLab 管道并使用等效的 GitHub Actions 工作流程打开拉取请求。

运行迁移命令

要将 GitLab 管道迁移到 GitHub Actions,请在您的终端中运行以下命令,替换以下值

  • target-url 值为您的 GitHub 存储库的 URL
  • my-gitlab-project 为您的 GitLab 项目的 URL
  • my-gitlab-namespace 为您正在迁移的命名空间或组
gh actions-importer migrate gitlab --target-url https://github.com/:owner/:repo --output-dir tmp/migrate --namespace my-gitlab-namespace --project my-gitlab-project

命令的输出包括将转换后的工作流程添加到您的存储库的拉取请求的 URL。成功输出的示例类似于以下内容

$ gh actions-importer migrate gitlab --target-url https://github.com/octo-org/octo-repo --output-dir tmp/migrate --namespace octo-org --project monas-project
[2022-08-20 22:08:20] Logs: 'tmp/migrate/log/actions-importer-20220916-014033.log'
[2022-08-20 22:08:20] Pull request: 'https://github.com/octo-org/octo-repo/pull/1'

检查拉取请求

成功运行 migrate 命令后输出的内容包含一个链接,指向将转换后的工作流添加到您的仓库的新拉取请求。

拉取请求中的一些重要元素包括

  • 在拉取请求描述中,有一个名为 手动步骤 的部分,其中列出了您在完成将管道迁移到 GitHub Actions 之前必须手动完成的步骤。例如,此部分可能会告诉您创建工作流中使用的任何密钥。
  • 转换后的工作流文件。在拉取请求中选择 已更改的文件 选项卡以查看将添加到您的 GitHub 仓库的工作流文件。

完成检查拉取请求后,您可以合并它以将工作流添加到您的 GitHub 仓库。

参考

本节包含使用 GitHub Actions Importer 从 GitLab 迁移时的环境变量、可选参数和支持的语法的参考信息。

使用环境变量

GitHub Actions Importer 使用环境变量进行身份验证配置。这些变量在使用 configure 命令遵循配置过程时设置。有关更多信息,请参阅“配置凭据”部分。

GitHub Actions Importer 使用以下环境变量连接到您的 GitLab 实例

  • GITHUB_ACCESS_TOKEN:用于使用转换后的工作流创建拉取请求的个人访问令牌(经典)(需要 workflow 范围)。
  • GITHUB_INSTANCE_URL:目标 GitHub 实例的 URL(例如,https://github.com)。
  • GITLAB_ACCESS_TOKEN:用于查看 GitLab 资源的 GitLab 个人访问令牌。
  • GITLAB_INSTANCE_URL:GitLab 实例的 URL。
  • NAMESPACE:包含 GitLab 管道的命名空间或组。

这些环境变量可以在 .env.local 文件中指定,该文件在运行 GitHub Actions Importer 时由其加载。

使用可选参数

您可以使用 GitHub Actions Importer 子命令的可选参数来自定义迁移。

--source-file-path

您可以将 --source-file-path 参数与 forecastdry-runmigrate 子命令一起使用。

默认情况下,GitHub Actions Importer 会从源代码管理中获取管道内容。--source-file-path 参数告诉 GitHub Actions Importer 使用指定的源文件路径。

例如

gh actions-importer dry-run gitlab --output-dir output/ --namespace my-gitlab-namespace --project my-gitlab-project --source-file-path path/to/.gitlab-ci.yml

如果你想在运行 forecast 子命令时提供多个源文件,你可以在文件路径值中使用模式匹配。以下示例为 GitHub Actions Importer 提供了与 ./tmp/previous_forecast/jobs/*.json 文件路径匹配的任何源文件。

gh actions-importer forecast gitlab --output-dir output/ --namespace my-gitlab-namespace --project my-gitlab-project --source-file-path ./tmp/previous_forecast/jobs/*.json

--config-file-path

你可以将 --config-file-path 参数与 auditdry-runmigrate 子命令一起使用。

默认情况下,GitHub Actions Importer 会从源代码管理中获取管道内容。--config-file-path 参数告诉 GitHub Actions Importer 使用指定的源文件。

--config-file-path 参数也可以用来指定将转换后的可重用工作流迁移到的仓库。

审计示例

在本例中,GitHub Actions Importer 使用指定的 YAML 配置文件执行审计。

gh actions-importer audit gitlab --output-dir path/to/output/ --namespace my-gitlab-namespace --config-file-path path/to/gitlab/config.yml

要使用配置文件审计 GitLab 实例,该文件必须采用以下格式,并且每个 repository_slug 值必须是唯一的

source_files:
  - repository_slug: namespace/project-name
    path: path/to/.gitlab-ci.yml
  - repository_slug: namespace/some-other-project-name
    path: path/to/.gitlab-ci.yml
试运行示例

在本例中,GitHub Actions Importer 使用指定的 YAML 配置文件作为源文件执行试运行。

管道是通过将配置文件中的 repository_slug--namespace--project 选项的值进行匹配来选择的。然后使用 path 拉取指定的源文件。

gh actions-importer dry-run gitlab --namespace my-gitlab-namespace --project my-gitlab-project-name --output-dir ./output/ --config-file-path ./path/to/gitlab/config.yml
指定转换后的可重用工作流的仓库

GitHub Actions Importer 使用提供给 --config-file-path 参数的 YAML 文件来确定将转换后的可重用工作流迁移到的仓库。

首先,你应该在没有 --config-file-path 参数的情况下运行审计

gh actions-importer audit gitlab --output-dir ./output/

该命令的输出将包含一个名为 config.yml 的文件,其中包含 GitHub Actions Importer 转换的所有复合操作的列表。例如,config.yml 文件可能包含以下内容

reusable_workflows:
  - name: my-reusable-workflow.yml
    target_url: https://github.com/octo-org/octo-repo
    ref: main

你可以使用此文件来指定应将可重用工作流或复合操作添加到哪个仓库和 ref。然后,你可以使用 --config-file-path 参数为 GitHub Actions Importer 提供 config.yml 文件。例如,你可以在运行 migrate 命令时使用此文件,为配置文件中定义的每个唯一仓库打开一个拉取请求

gh actions-importer migrate gitlab --project my-project-name --output-dir output/ --config-file-path config.yml --target-url https://github.com/my-org/my-repo

支持的 GitLab 管道语法

下表显示了 GitHub Actions Importer 当前能够转换的属性类型。有关 GitLab 管道语法如何与 GitHub Actions 对齐的更多详细信息,请参阅 "从 GitLab CI/CD 迁移到 GitHub Actions"。

GitLab 管道GitHub Actions状态
after_scriptjobs.<job_id>.steps支持
auto_cancel_pending_pipelines并发支持
before_scriptjobs.<job_id>.steps支持
build_timeouttimeoutjobs.<job_id>.timeout-minutes支持
默认不适用支持
镜像jobs.<job_id>.container支持
作业jobs.<job_id>支持
需要jobs.<job_id>.needs支持
only_allow_merge_if_pipeline_succeedson.pull_request支持
资源组jobs.<job_id>.concurrency支持
调度on.schedule支持
脚本jobs.<job_id>.steps支持
阶段作业支持
标签jobs.<job_id>.runs-on支持
变量env, jobs.<job_id>.env支持
为新提交运行管道on.push支持
手动运行管道on.workflow_dispatch支持
环境jobs.<job_id>.environment部分支持
包含include 语句中引用的文件在转换为单个作业图之前被合并。部分支持
onlyexceptjobs.<job_id>.if部分支持
并行jobs.<job_id>.strategy部分支持
规则jobs.<job_id>.if部分支持
服务jobs.<job_id>.services部分支持
工作流如果部分支持

有关支持的 GitLab 结构的信息,请参阅 github/gh-actions-importer 存储库

环境变量语法

GitHub Actions Importer 使用下表中的映射将默认的 GitLab 环境变量转换为 GitHub Actions 中最接近的等效项。

GitLabGitHub Actions
CI_API_V4_URL${{ github.api_url }}
CI_BUILDS_DIR${{ github.workspace }}
CI_COMMIT_BRANCH${{ github.ref }}
CI_COMMIT_REF_NAME${{ github.ref }}
CI_COMMIT_REF_SLUG${{ github.ref }}
CI_COMMIT_SHA${{ github.sha }}
CI_COMMIT_SHORT_SHA${{ github.sha }}
CI_COMMIT_TAG${{ github.ref }}
CI_JOB_ID${{ github.job }}
CI_JOB_MANUAL${{ github.event_name == 'workflow_dispatch' }}
CI_JOB_NAME${{ github.job }}
CI_JOB_STATUS${{ job.status }}
CI_JOB_URL${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
CI_JOB_TOKEN${{ github.token }}
CI_NODE_INDEX${{ strategy.job-index }}
CI_NODE_TOTAL${{ strategy.job-total }}
CI_PIPELINE_ID${{ github.repository}}/${{ github.workflow }}
CI_PIPELINE_IID${{ github.workflow }}
CI_PIPELINE_SOURCE${{ github.event_name }}
CI_PIPELINE_TRIGGERED${{ github.actions }}
CI_PIPELINE_URL${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
CI_PROJECT_DIR${{ github.workspace }}
CI_PROJECT_ID${{ github.repository }}
CI_PROJECT_NAME${{ github.event.repository.name }}
CI_PROJECT_NAMESPACE${{ github.repository_owner }}
CI_PROJECT_PATH_SLUG${{ github.repository }}
CI_PROJECT_PATH${{ github.repository }}
CI_PROJECT_ROOT_NAMESPACE${{ github.repository_owner }}
CI_PROJECT_TITLE${{ github.event.repository.full_name }}
CI_PROJECT_URL${{ github.server_url }}/${{ github.repository }}
CI_REPOSITORY_URL${{ github.event.repository.clone_url }}
CI_RUNNER_EXECUTABLE_ARCH${{ runner.os }}
CI_SERVER_HOST${{ github.server_url }}
CI_SERVER_URL${{ github.server_url }}
CI_SERVER${{ github.actions }}
GITLAB_CI${{ github.actions }}
GITLAB_USER_EMAIL${{ github.actor }}
GITLAB_USER_ID${{ github.actor }}
GITLAB_USER_LOGIN${{ github.actor }}
GITLAB_USER_NAME${{ github.actor }}
TRIGGER_PAYLOAD${{ github.event_path }}
CI_MERGE_REQUEST_ASSIGNEES${{ github.event.pull_request.assignees }}
CI_MERGE_REQUEST_ID${{ github.event.pull_request.number }}
CI_MERGE_REQUEST_IID${{ github.event.pull_request.number }}
CI_MERGE_REQUEST_LABELS${{ github.event.pull_request.labels }}
CI_MERGE_REQUEST_MILESTONE${{ github.event.pull_request.milestone }}
CI_MERGE_REQUEST_PROJECT_ID${{ github.repository }}
CI_MERGE_REQUEST_PROJECT_PATH${{ github.repository }}
CI_MERGE_REQUEST_PROJECT_URL${{ github.server_url }}/${{ github.repository }}
CI_MERGE_REQUEST_REF_PATH${{ github.ref }}
CI_MERGE_REQUEST_SOURCE_BRANCH_NAME${{ github.event.pull_request.head.ref }}
CI_MERGE_REQUEST_SOURCE_BRANCH_SHA${{ github.event.pull_request.head.sha}}
CI_MERGE_REQUEST_SOURCE_PROJECT_ID${{ github.event.pull_request.head.repo.full_name }}
CI_MERGE_REQUEST_SOURCE_PROJECT_PATH${{ github.event.pull_request.head.repo.full_name }}
CI_MERGE_REQUEST_SOURCE_PROJECT_URL${{ github.event.pull_request.head.repo.url }}
CI_MERGE_REQUEST_TARGET_BRANCH_NAME${{ github.event.pull_request.base.ref }}
CI_MERGE_REQUEST_TARGET_BRANCH_SHA${{ github.event.pull_request.base.sha }}
CI_MERGE_REQUEST_TITLE${{ github.event.pull_request.title }}
CI_EXTERNAL_PULL_REQUEST_IID${{ github.event.pull_request.number }}
CI_EXTERNAL_PULL_REQUEST_SOURCE_REPOSITORY${{ github.event.pull_request.head.repo.full_name }}
CI_EXTERNAL_PULL_REQUEST_TARGET_REPOSITORY${{ github.event.pull_request.base.repo.full_name }}
CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME${{ github.event.pull_request.head.ref }}
CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA${{ github.event.pull_request.head.sha }}
CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME${{ github.event.pull_request.base.ref }}
CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA${{ github.event.pull_request.base.sha }}

部分内容改编自 https://github.com/github/gh-actions-importer/,根据 MIT 许可证授权

MIT License

Copyright (c) 2022 GitHub

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.