# 微信云托管如何实现一套代码对应多个环境

## 前言

在项目开发时，通常具有多种环境，用来在开发的各个流程阶段进行作用，比如开发/测试，预发/生产。

环境的不同，对应的数据库等配置信息就有所不同，就必须要针对配置信息的变更，对应创建单独的代码仓库，流水线对应一个代码仓库，这样维护成本太大。

在这里主要是配置信息的变化，本篇主要介绍如何在项目代码中动态感知所处的微信云托管环境，进而给予正确的配置信息。

## 一、环境变量

微信云托管在运行项目服务过程中，带入了一个环境变量，名称为 `CBR_ENV_ID`，意义是当前运行服务所处的 `微信云托管环境ID`

所以在项目内部，可以通过获取 `CBR_ENV_ID` 变量，来感知当前项目在哪个环境运行。

## 二、划分环境

微信云托管的环境可以建立多个，单个环境下可以有多个服务，和单独的数据库以及对象存储，在客观条件上做了隔离。

所以可以用 `微信云托管环境` 为维度进行隔离，创建项目开发的各个环境（预发、生产）

最终我们可以得到一个清单，样式如下：

```bash
werun—id1 = '预发'
werun—id2 = '生产'
```

其中 `werun—id` 为微信云托管的环境 ID

## 三、配置代码

接下来将上述清单的配置写到项目代码中，以 `nodejs` 为例：

假设一开始我们的配置 `config.js` 是这样的：

```js
module.exports = {
  "text":"开发环境"
}
```

为了简化在这里只有一个 text，实际应用中，应该是数据库、存储、网络通信的配置信息，也就是需要根据环境区分的信息都要写到一块。

接下来，加上 `CBR_ENV_ID` 变量，来进行改造，代码如下：

```js
const config = {
  'werun—id1': {
    text:'预发环境'
  },
  'werun—id2': {
    text:'生产环境'
  },
  NO: {
    text: '本地环境'
  }
}

module.exports = function(env=null){
  const key = env || process.env.CBR_ENV_ID
  if(config[key] != null){
    return config[key]
  } else {
    return config.NO
  }
}
```

以上代码，将各个环境的配置信息统一囊括，然后根据 `CBR_ENV_ID` 变量来进行分发，如果没有预设的环境配置，则返回本地测试配置。

整体示例项目代码，可以[在此下载](https://7a7a-zzirali-7gjlfmcv2e2df47f-1258016615.tcb.qcloud.la/cloudbase-cms/upload/2021-09-27/58LQK8wjo9iBYSgOCIRwW31nzw93SqYz_.zip)

以上就已经做完了项目的动态配置改造，接下来我们开始配置流水线。

## 四、配置流水线

开发/测试环境更新频繁，且部署的代码分支可能不是最新或稳定的，使用的也都是测试数据。

预发/生产环境采用稳定分支与真实用户数据。

根据自己的业务需求，配置一个或若干个服务，选配数据库或对象存储等。

进入**服务设置 > 流水线**，接下来我们重点来讲流水线的配置差异：

1）开发/测试环境和预发/生产环境，应该使用同样的代码源、代码仓库、目标目录、端口；
2）开发/测试环境建议绑定代码仓库的 dev 或 test 分支（需要开发者自行创建），预发/生产环境绑定代码仓库的 master/main 分支。
3）开发/测试环境可以开启推送触发，只要代码分支更新即自动部署生效；
4）预发/生产环境一般不建议开启推送触发，会直接改变线上业务。建议采用手动触发流水线+灰度发布，控制对现网用户的影响。
5）开发/测试环境，建议在**服务设置 > 基础信息**中，采用更小的实例副本数和容器规格，节约成本；
6）特殊情况下，开发/测试环境的服务，除了“服务设置”中的值（容器规格、实例副本数、环境变量等）与预发/生产环境不一致外，Dockerfile 有时也需要区分。此时注意在流水线设置中填写不一样的“Dockerfile 名称”。

## 五、环境流程建议

每个团队都有自己的开发测试流程和环境，请根据自身情况合理理解本篇内容。

传统开发模式下的开发测试流程在转移到微信云托管时需要有些变通，以下是一些建议：

1）开发环境：团队开发人员产出代码自测的环境，一般可以在本地 PC 开一个 Docker 容器挂载项目代码开发。容器镜像保证团队统一性，将极大的减少因为环境问题导致的联调失败。
2）测试、联调、回归环境：需要项目整体性的测试体验，在这里分形态来建议，项目形态上有 `单一服务型` 和 `微服务` 两种形态：
   - 单一服务型：不管项目有多大，就一个服务运行，更新需要全部替换；这种情况下不建议将其放在微信云托管环境中联调测试，直接在本地测试和联调开发的效率会更高一些。因为只有内部业务互相调用，不涉及其他的服务（API 接口、数据库、对象存储除外，本身属于外联通性）
   - 微服务形态：项目被拆分成不同的模块，每个模块服务独立运行，共同作用，更新只需要替换变更的；这种情况下建议放在微信云托管中测试，也就是变更的模块在经过测试，表现稳定的情况下，将其部署到微信云托管中，和其他服务一起做整体测试。
3）预发、生产环境：微信云托管中开单独的环境，如果需要预发环境连接生产环境数据库，可以设置两个环境内网联通，然后内网连接对应的数据库。
