喵♂呜 的博客

一个刚毕业就当爹的程序猿 正在迷雾中寻找道路...

如何从 Gogs 升级到 Gitea

最近需要更新 GogsGitea 但是官方表示 只能升级老版本的 折腾了一下 升级成功了 这里做个记录

准备工作

  • 做好数据库和Git仓库的备份
  • 做好数据库和Git仓库的备份
  • 做好数据库和Git仓库的备份
  • 准备一个Docker环境 用于快速切换版本
  • 一双明亮的双眼 仔细阅读升级指南
  • 前置数据准备
    • 找到 GogsRepo 目录 仓库数据
    • 找到 GogsData 目录 头像等自定义数据

迁移数据到Gitea1.0.2版本

  • 找一个你要保存数据的目录 (本案例指定为 /data/gitea)
  • 通过 Docker 容器安装 1.0.2 的 Gitea
  • 执行下列命令 启动一个容器
    1
    docker run --rm -p 3000:3000 -v /data/gitea:/data --name gitea gitea/gitea:1.0.2
  • 打开 http://主机IP:3000 完成安装流程
  • Ctrl + C 关闭容器
  • 复制 repo 数据 到 /data/gitea/git/repositories 注意原有目录结构
  • 复制 data 数据 到 /data/gitea/gitea 注意原有目录结构
  • 修改 /data/gitea/gitea/conf/app.ini 文件配置
  • 复制原有配置文件的密钥到 /data/gitea/gitea/conf/app.ini
    1
    2
    3
    [security]
    INSTALL_LOCK = true
    SECRET_KEY = xxxx
  • 设置之前复制目录的权限为 git 执行 chown git:git /data/gitea -R
  • 修改数据库 version 表的 version 记录值为 13
    1
    UPDATE `version` SET `version` = 13 WHERE `id` = 1
  • 再次启动容器 访问 http://主机IP:3000 查看是否存在问题

逐步升级到最新版

  • 尝试使用新版本的镜像启动 执行下列命令
    1
    docker run --rm -p 3000:3000 -v $(pwd):/data --name gitea gitea/gitea:1.1.4
  • 启动后 数据库会开始自动迁移 看到 Listen: http://0.0.0.0:3000 的时候 关闭容器
  • 按照步骤 依次完成下列版本升级 1.0.2 > 1.1.4 > 1.2.3(这次应该从这里开始) > 1.3.3 > 1.4.3 > 1.5.3 > 1.6.4 > 1.7.6 > 1.8.3 > 1.9.6 > 1.10.2
  • 最后一个版本可以运行之后 使用下列命令运行 保证自动重启
    1
    docker run -p 3000:3000 -v /data/gitea:/data --restart=always --name gitea gitea/gitea:1.10.2

异常问题解决

Failed to initialize ORM engine: migrate: do migrate: Avatar user is not exist

  • 此问题应该存在 1.0.2 => 1.1.4 的时候发生
  • 检查了一下 1.1.4 的源代码 https://github.com/go-gitea/gitea/blob/34182c87ec50f647fc6f5b97ba201c3bd42f0728/models/migrations/v20.go#L22
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    names, err := d.Readdirnames(0)
    if err != nil {
    return err
    }

    type User struct {
    ID int64 `xorm:"pk autoincr"`
    Avatar string
    UseCustomAvatar bool
    }

    for _, name := range names {
    ... 省略
    var user User
    if has, err := x.ID(userID).Get(&user); err != nil {
    return err
    } else if !has {
    // 问题在这里 主要是 有对应的头像文件 但是没找到数据库对应的ID
    return errors.New("Avatar user is not exist")
    }
    }
  • 发现是 通过数据头像目录获取头像 检查数据库数据的时候报错
  • 先把 /data/avatar(/data/gitea/gitea/avatar) 目录

ORM engine initialization failed: migrate: do migrate: Repository 464 is not exist

  • 此问题应该存在 1.7.6 => 1.8.4 的时候发生
  • 检查 1.8.4 的源代码 https://github.com/go-gitea/gitea/blob/11f6ed4f83/models/migrations/v82.go#L71
  • 发现问题在这里
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    releases := make([]*Release, 0, batchSize)
    if err = sess.Limit(batchSize, start).Asc("id").Where("is_tag=?", false).Find(&releases); err != nil {
    return err
    }
    if len(releases) == 0 {
    break
    }

    for _, release := range releases {
    gitRepo, ok := gitRepoCache[release.RepoID]
    if !ok {
    repo, ok := repoCache[release.RepoID]
    if !ok {
    repo = new(Repository)
    has, err := sess.ID(release.RepoID).Get(repo)
    if err != nil {
    return err
    } else if !has {
    // 问题在这里 主要是 有Release相关数据 但是没有找到对应的仓库
    return fmt.Errorf("Repository %d is not exist", release.RepoID)
    }

    repoCache[release.RepoID] = repo
    }
    }
    }
  • 先去检查 releases 表 搜索 RepoID 等于对应报错的记录
  • 备份相关记录数据
  • 删除有问题的数据 然后重启

404 问题解决

方案一

  • 使用 API 更新 配置
  • 去个人管理页面 生成一个 Token
  • 通过API 更新仓库信息 curl -X PATCH "https://{{host}}/api/v1/repos/{{user}}/{{repo}}?access_token={{token}}" -H "accept: application/json" -H "Content-Type: application/json" -d "{}"
  • 此方案需要一个项目一个项目修复

方案二

  • 数据库批量解决此问题
    1
    2
    3
    4
    5
    6
    INSERT INTO repo_unit ( "repo_id", "type", "config" )
    SELECT repository.id, types.*, '{}' FROM repository
    LEFT JOIN repo_unit ON repository.id = repo_id
    LEFT JOIN ( SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 ) AS types ON ( 1 = 1 )
    WHERE
    repo_id IS NULL;
  • 此方案有可能导致部分项目配置重置

推送代码时提示钩子异常

  • 提示类似下列错误
    1
    2
    3
    4
    remote: ./hooks/pre-receive.d/pre-receive: line 2: /opt/gogs/gogs: No such file or directory
    To https://gitea.xxx.xxx/xxx/xxx.git
    ! [remote rejected] master -> master (pre-receive hook declined)
    error: failed to push some refs to 'https://gitea.xxx.xxx/xxx/xxx.git'
  • 执行删除钩子 find repositories -path \*-receive.d/\*-receive | xargs rm -r

欢迎关注我的其它发布渠道