Drone将VUE项目持续部署到阿里云OSS

1. 最终效果

前端自动构建持续集成效果

1.1 步骤简介

Drone 可以根据配置把过程切割成一个一个的操作管道任务。

clone 每次构建都会克隆一次代码、这是一个毛病但是暂时没别的办法

restore-cache 复制上次构建的node_modules缓存

build 构建的过程

rebuild-cache 缓存node_modules

deployment-to-oss 把dist/* 同步到阿里云OSS

notify 发送(邮件)通知

1.2 访问设置了两种类型

  • oss没有办法支持history路由模式
  • 只有根目录才自动寻找首页文件

1.2.1 https://{your-cdn-domain}/

├── 24
│   └── static
│       ├── css
│       │   ├── app.30790115300ab27614ce176899523b62.css
│       │   └── app.30790115300ab27614ce176899523b62.css.map
│       └── js
│           ├── app.b22ce679862c47a75225.js
│           ├── app.b22ce679862c47a75225.js.map
│           ├── manifest.cc150ee5e77c28d4c563.js
│           ├── manifest.cc150ee5e77c28d4c563.js.map
│           ├── vendor.7fed9fa7b7ba482410b7.js
│           └── vendor.7fed9fa7b7ba482410b7.js.map
├── 25
│   └── static
├── 26
│   └── static
└── index.html
  • 适合纯前后单分离的前端正式部署
  • 其中 24 25 26 是每次构建的ID 便于清理
  • 需要有一个域名+一个OSS
  • 不要试图使用oss自带的域名、已被微信封了

1.2.2 https://{your-cdn-domain}/{git-repo}/{git-branch}/index.html

e.g. https://domain.com/fe/vue/master/

其中 fe/vue 就是在你在git的项目

  • 适合测试
  • 适合非完全前后端分离的、还需要一个nginx代理下index.html
  • 设置代理一定要使用OSS提供的内网/VPC网络域名
  • 如果使用的路由模式是hash可以在动态程序内缓存一份index.html
frontend
└── frontend-deploy-to-aliyun-oss-with-drone
    ├── master
    │   ├── 24
    │   │   └── static
    │   ├── 25
    │   │   └── static
    │   ├── 26
    │   │   └── static
    │   └── index.html
    └── t1
        ├── 27
        │   └── static
        └── index.html

部署到OSS后的目录

server
    {
        location /project/ {
			proxy_pass http://{your-oss-vpc-domain}/{git-repo}/{git-branch}/index.html?from=target;
        }

    }
  • ?from=target 一定要加要不会出现错误
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchKey</Code>
  <Message>The specified key does not exist.</Message>
  <RequestId>5B322AC617EC1B481CD7CE67</RequestId>
  <HostId>xxx.oss-cn-beijing-internal.aliyuncs.com</HostId>
  <Key>{repo}/{branch}/index.html/checkin/configure</Key>
</Error>

2. 开启某仓库持续集成

2.1 登陆GOGS->给用户drone添加仓库只读权限

  • 因为GOGS不支持秘钥所以就只能建立个账号
  • 建议使用组织管理权限

2.2 使用你在GOGS的账号密码登陆Drone后台、打开这个repo选项

  • 账号/密码就是你 GOGS的账号密码

这时候 gogs 这个仓库会自动生成 web钩子

2.3 登陆Drone 勾选 Settings->Trusted

  • 缓存 node_modules 需要这个

2.4 Drone->Settings->{repo}->secrets 设置阿里云OSS秘钥

aliyun_oss_endpoint
aliyun_access_key_id
aliyun_access_key_secret
email_username
email_password
  • 每个项目都要加一遍…

2.5 如果没有生秘钥就到阿里云生成一个子秘钥

  • 这里自定义了一个授权策略、策略中限制了IP只允许drone内网主机才有权限使用
  • 并把授权策略赋给了没有任何权限的drone用户
{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "oss:List*",
        "oss:Get*",
        "oss:Put*",
        "oss:Post*"
      ],
      "Resource": [
        "acs:oss:*:*:{your-oss-bucket-name}",
        "acs:oss:*:*:{your-oss-bucket-name}/*",
      ],
      "Condition": {
        "IpAddress": {
          "acs:SourceIp": "172.17.77.51"
        }
      }
    }
  ]
}

2.6 设置OSS-CDN缓存自动刷新

  • 这样每次部署完成会自动刷新CDN

2.7 设置OSS静态托管

  • index.html 只针对根目录有效
  • 也就是说一个OSS仓库只能用于一个正式的前后端分离的站点

3. 配置 .drone.yml

3.1 Git仓库中加入.drone.yml

# 允许分支自动构建的分支
# 简历master分支为正式分支、t* 测试分支、pre*预发布分支
branches: [ master, t1, t2 ]

# 默认的workspace是 /drone/src/{git domin}/{repo}
# e.g. http://{your-get-domain}/frontend/test-to-oss.git
# e.g. /drone/src/{your-get-domain}/frontend/test-to-oss
# 前端构建基本上不要改、如果有更改的地方文档里会说明

pipeline:
  restore-cache:
    image: drillster/drone-volume-cache
    restore: true
    mount:
      - ./node_modules
    volumes:
      - /var/local/drone-cache:/cache
  build:
    image: node:8.11.1
    commands:
      # 出于一些不可告人的原因使用了淘宝npm镜像 你不要笑
      - npm config set registry http://registry.npm.taobao.org
      # 项目中使用了chromedriver 出于同样不可告人的原因使用了淘宝npm镜像 你也不要笑
      - export CHROMEDRIVER_CDNURL=https://npm.taobao.org/mirrors/chromedriver
      - npm install eslint-plugin-html -–save-dev
      - npm install -silent
      # 根据参数设置静态文件路径
      # @link http://{your-get-domain}:9531/frontend/frontend-deploy-to-aliyun-oss-with-drone/commit/16978db8bf1990140703c10ea20b9d28af3eeb7a
      - npm run build --commit-branch=${DRONE_COMMIT_BRANCH} --public-path=https://{your-cdn-domain}/${DRONE_REPO}/${DRONE_COMMIT_BRANCH}/${DRONE_BUILD_NUMBER}/
  rebuild-cache:
    image: drillster/drone-volume-cache
    rebuild: true
    mount:
      - ./node_modules
    volumes:
      - /var/local/drone-cache:/cache
  deployment-to-oss:
    # 简要的阿里云OSS的docker
    # 没有构建私有docker仓库的时候暂时就是这样、当然不能封任何秘钥进去
    # @link https://github.com/trylife/aliyun-ossutil/blob/master/Dockerfile
    # @link https://hub.docker.com/r/trylife/aliyun-ossutil/
    image: trylife/aliyun-ossutil:latest
    # 声明你要使用哪些秘钥
    # 设置秘钥的时候是小写、强制的
    # 获取的时候是大写
    secrets: [ aliyun_oss_endpoint,aliyun_access_key_id,aliyun_access_key_secret]
    commands:
      # drone->repo->settings->secrets-> 增加秘钥
      # 秘钥还不是那么安全可以随意的被打印出来
      # 所以秘钥的授权限制了IP,只能执行在Drone服务器上
      # 默认配置文件地址 ~/.ossutilconfig
      # 阿里云秘钥 建立规则统一授权给 drone用户
      # todo: trylife@qq.com 待封装为私有镜像服务

      # 设置ossutil本地秘钥
      - ossutil config  -L CH -e $${ALIYUN_OSS_ENDPOINT} -i $${ALIYUN_ACCESS_KEY_ID} -k $${ALIYUN_ACCESS_KEY_SECRET}

      # 开始根据不同的服务进程部署操作
      # 没有完全前后端分离的项目、没有独立域名解析到阿里云CDN->OSS中的部署方式如下
      # {repo}/{branch}
      # frontend/vue master分支 会部署到 https://{your-cdn-domain}/frontend/vue/master/
      # frontend/vue t1 会部署到 https://{your-cdn-domain}/frontend/vue/t1/
      # 完全前后端分离的项目 有自己的独立的CDN域名例如 https://trylife.cn/
      # ananas/ananas-vue master 部署到 https://trylife.cn/
      # ananas/ananas-vue t1 部署到 https://trylife.cn/t1/
      # 下面的规则请勿轻易更改、避免造成其他部署冲突

      # 一直在workspace里
      - pwd

      - ossutil cp -rf ./dist/static oss://{your-oss-bucket-name}/${DRONE_REPO}/${DRONE_COMMIT_BRANCH}/${DRONE_BUILD_NUMBER}/static
      - ossutil cp -rf ./dist/index.html oss://{your-oss-bucket-name}/${DRONE_REPO}/${DRONE_COMMIT_BRANCH}/
  notify:
    image: drillster/drone-email
    secrets: [ email_username, email_password]
    host: smtp.263.net
    username: ${EMAIL_USERNAME}
    password: ${EMAIL_PASSWORD}
    port: 465
    from: {your-email-address}
    when:
      status: [ changed, failure, success ]

TODO: Global Secrets