Wagtail 项目多环境 migrations 管理方案

Wagtail 项目多环境 migrations 管理方案

一、项目框架背景介绍

Wagtail 是一款基于 Django 开发的 CMS 应用框架,其数据交互依赖于 Django ORM 方法,该方法要求开发者在每次发生数据库改动时,需要依次通过 makemigrations 和 migrate 指令使数据库改动生效。而 makemigrations 指令,会依据项目各 app 模块中的 models 和 migrations 文件夹中数据库迁移脚本的变化,生成初始化或变更的数据库迁移脚本(如:0001_initial.py)。这些数据库迁移脚本,是 Wagtail 项目初始化和改动当前数据库所依赖的必要指导文件。最后,migrate 指令会比对 django_migrations 数据表中已执行数据库迁移脚本和 migrations 文件夹中脚本的差异,将未执行的脚本进行执行,并将执行成功的文件信息存入数据表。

二、问题产生背景

因此,在进行团队项目开发,同时涉及多环境部署的情况下,这种数据库初始化和变更方式会对代码仓的管理有如下的要求:

  • 团队中开发者,在进行开发时,数据库必须使用本地数据库。

  • 线上不同环境(dev、sit、uat、prod),存在数据库不同的步进情况(一般dev的更新是最频繁的,sit、uat 和 prod 依次减缓),同时,线上发布环境通常在集群发布,容器都是一次性的,所以本地存储不是持久存储,这就需要将服务每次启动初始化产生的 migrations 文件分别进行远程仓库的存储。

为了使代码仓库的管理满足以上要求,则需要:

  • 开发者不能将自己本地代码中的 migrations 文件上传到远程仓库,这个可以通过向 .gitignore 中添加目录正则来忽略所有 migrations 文件,不同步到远程仓库。

  • 线上的四个不同环境的 migrations 文件需要通过远程仓库进行隔离储存和管理,这意味着,线上发布的代码中,需要包含 migrations 文件,要同步到远程仓库。

三、问题产生

此时,如果简单地通过一个仓库多分支来实施上述需求操作,就会出现一个矛盾,开发者的开发分支(如 dev)不可以上传 migrations 文件,但是向线上 dev 环境发布时又需要上传 migrations 文件到仓库进行存储。

四、问题解决思路

既然 migrations 的存在给项目代码仓库带来了如此不便,那消除它的方式,就是将它抽离出来,单独建仓进行管理。这样项目代码仓永不包含 migrations 文件,只作为程序本身的代码载体,就不会影响到开发人员代码到线上环境代码的合并流程,消除了由于项目代码仓是否包含 migrations 文件产生的矛盾。

五、方案设计

(一)条件准备

  • 拥有可以被线上环境访问到的远程仓库。

  • 拥有可以执行 git 指令和 bash 脚本的容器环境。

  • 容器的 entrypoint 依据环境分别执行代码仓中的 bash 脚本(如 start-dev.sh 等)。

(二)流程设计

img

(三)实施流程

1. 搭建 migrations 仓库

在 gitlab 上创建 yourproject-wagtail-migrations 仓库,并用 Readme 自述文件进行初始化,再为仓库创建 4 个环境的分支,分别命名为:dev、sit、uat、prod。

migrations 仓库的目录结构,应该保持和项目代码仓一致,类似如下:

/yourproject-wagtail-migrations (690.73KB)
├── app1 (1.91KB)
│   └── migrations (1.91KB)
│       ├── 0001_initial.py (901b)
│       ├── __init__.py (0b)
│       └── __pycache__ (1.03KB)
│           ├── 0001_initial.cpython-38.pyc (905b)
│           └── __init__.cpython-38.pyc (154b)
├── app2 (3.98KB)
│   └── migrations (3.98KB)
│       ├── 0001_initial.py (2.01KB)
│       ├── __init__.py (0b)
│       └── __pycache__ (1.98KB)
│           ├── 0001_initial.cpython-38.pyc (1.83KB)
│           └── __init__.cpython-38.pyc (154b)
└── app3 (13.21KB)
    └── migrations (13.21KB)
        ├── 0003_alter_xxxxx.py (973b)
        ├── 0001_initial.py (3.94KB)
        ├── __init__.py (1.42KB)
        ├── __pycache__ (5.8KB)
        │   ├── 0003_alter_xxxxx.cpython-38.pyc (1.11KB)
        │   ├── 0002_alter_xxxxx.cpython-38.pyc (801b)
        │   ├── 0001_initial.cpython-38.pyc (3.09KB)
        │   ├── __init__.cpython-38.pyc (151b)
        │   └── 0004_alter_xxxxx.cpython-38.pyc (684b)
        ├── 0004_alter_xxxxx.py (538b)
        └── 0002_alter_xxxxx.py (585b)

2. 编写项目启动脚本 start.sh

编写 start.sh 脚本并放在项目代码仓中,并在 CI/CD 构建镜像时,将该脚本作为 entrypoint 的执行脚本,并在运行容器时执行。

2.1 start.sh 脚本
# 脚本中的 [对应环境] 可由以下关键字替换:dev、sit、uat、prod
#!/bin/bash
service nginx start
# 配置 git
git config --global user.email "公司邮箱"
git config --global user.name "公司域账号"
# 拉取 migrations
git clone -b [对应环境] https://公司域账号:密码@gitlab.yoursite.com/yourgroup/yourproject-wagtail-migrations.git /home/yourproject-wagtail-migrations
# 拷贝 migrations
cp -r /home/yourproject-wagtail-migrations/* /home/yourproject-wagtail-server/
# 执行 migrations
python3.8 manage.py makemigrations --settings zopwagtail.settings.[对应环境]
python3.8 manage.py migrate --settings zopwagtail.settings.[对应环境]
# 备份 migrations
find -name migrations | while read line; do
    cp -r $line/* /home/yourproject-wagtail-migrations/$line
done
cd /home/yourproject-wagtail-migrations
git add .
git commit -m "Synchronize migrations: $(date +%Y)-$(date +%m%d)-$(date +%H%M)"
git push
# 初始化服务
cd /home/yourproject-wagtail-server
python3.8 manage.py collectstatic --noinput --settings zopwagtail.settings.[对应环境]
python3.8 manage.py runserver --settings zopwagtail.settings.[对应环境]

(三)补充说明

1. 关于 prod 环境的处理

一般情况,prod 环境出于安全考虑是无法直接访问公司 GitLab 的,所以无法在容器启动时做 migrations 仓库的同步。因此,在CI/CD 构建镜像时,就需要同时拉取 migrations 仓库合并至项目仓库中,执行 makemigrations 指令,并将产生的 migrations 文件变化同步到 migrations 仓库中。

这种情况下,需要对上述流程进行优化,优化结果如下:

img

在这种流程设计下,CI/CD构建时的脚本可以编写如下:

# 脚本中的 [对应环境] 可由以下关键字替换:dev、sit、uat、prod
git clone -b [对应环境] https://gitlab.yoursite.com/yourgroup/yourproject-wagtail-migrations.git

cd /workspace
mkdir yourproject-wagtail-migrations-prepare
cp -r yourproject-wagtail-migrations/* zop-wagtail-migrations-prepare
​
# 拷贝 migrations
cd /workspace
​
cd yourproject-wagtail-migrations-prepare && ls
​
# 只拷贝项目仓库存在的 migrations 目录
cd /workspace/yourproject-wagtail-server
find -name migrations | while read line; do
    if [ -d '/workspace/yourproject-wagtail-migrations-prepare/'$line ]; then
        cp -r /workspace/yourproject-wagtail-migrations-prepare/$line/* /workspace/yourproject-wagtail-server/$line
    fi
done
cd ..
​
# 执行 migrations
cd yourproject-wagtail-server && pwd && ls
python3.8 manage.py makemigrations --settings yourprojectwagtail.settings.makemigrations_helper
# 这里的 makemigrations_helper 配置专门用于在构建环境中执行 makemigration 用,内容可以和对应环境的配置文件保持一致
​
# 删除 migrations 仓库的文件
mkdir -p /workspace/gitbak
mv /workspace/yourproject-wagtail-migrations/.git /workspace/gitbak
rm -r /workspace/yourproject-wagtail-migrations/*
mv /workspace/gitbak/.git /workspace/yourproject-wagtail-migrations
​
# 备份 migrations
find -name migrations | while read line; do
    mkdir -p /workspace/yourproject-wagtail-migrations/$line
    cp -r $line/* /workspace/yourproject-wagtail-migrations/$line
done
​
# 提交代码
cd /workspace/yourproject-wagtail-migrations
​
git add .
git commit -m "Synchronize migrations: $(date +%Y)-$(date +%m%d)-$(date +%H%M)"
​
git push

此时,所有环境的 start.sh 脚本可改为如下:

# 脚本中的 [对应环境] 可由以下关键字替换:dev、sit、uat、prod
#!/bin/bash
service nginx start
​
# 初始化数据库
python3.8 manage.py migrate --settings zopwagtail.settings.[对应环境]
​
# 初始化服务
python3.8 manage.py collectstatic --noinput --settings zopwagtail.settings.[对应环境]
python3.8 manage.py runserver --settings zopwagtail.settings.[对应环境]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值