用最少的钱,实现工程效率实践

介绍

研发团队的工程效率实践,现在越来越多的人开始谈论这个话题,但是真真能实操的还本场 Chat 侧重于实践,不会有抽象的概念和理论知识。

我会拟一个场景来实战-《如何通过Gitlab+七牛云存储来构建在线产品需求文档》,一步一步的带领大家构建属于你自己或者你们团队的工程效率实践。

了解 Axure 产品原型工具

RP 是一个专业的快速原型设计工具。Axure(发音:Ack-sure),代表美国 Axure 公司;RP 则是 Rapid Prototyping(快速原型)的缩写。

Axure RP 是美国 Axure Software Solution 公司旗舰产品,是一个专业的快速原型设计工具,让负责定义需求和规格、设计功能和界面的专家能够快速创建应用软件或 Web 网站的线框图、流程图、原型和规格说明文档。

作为专业的原型设计工具,它能快速、高效的创建原型,同时支持多人协作设计和版本控制管理。

Axure RP 的使用者主要包括商业分析师、信息架构师、产品经理、IT 咨询师、用户体验设计师、交互设计师、UI 设计师等,另外,架构师、程序员也在使用 Axure。

摘自百度百科:

Axure 是一个极其简单的软件,如果你不需要做交互,那么你不看教程,也只要 10 分钟就可以掌握个大概。因为你所做的就是拖部件,打字,拖部件,打字,最多加个对齐。

了解 Gitlab Webhook

Webhook 是什么?:

Webhooks 是“用户定义的 HTTP 回调”,它们通常由一些事件触发,例如将代码推送到仓库或一个博客的评论。 发生该事件时,源应用程序将向 webhook 配置的 URI 发出一个 HTTP 请求,这个请求可以做任何事情。通常是用于触发构建持续集成系统,或者去通知错误跟踪系统。-维基百科

了解七牛云存储

首先,我们要进行七牛云账户注册,在个人账户和企业账户中选择一个,按照你自己的实际情况来选择就好了。

  • 实名认证后可以享受到更多免费福利;
  • 个人用户可以升级为企业用户,但企业用户不能降级为个人用户;

注册和实名认证都很简单,这里就不做介绍了。如果大家在注册过程中遇到了问题,请在读者圈中给我留言。

重点:对于认证用户,七牛云存储提供免费的存储空间 10GB,每月下载流量 10GB,每月 PUT/DELETE 10 万次请求,每月 GET 100 万次请求。

咱们即将要做的在线产品需求文档就是基于七牛云存储来对外发布的,对于个人来说免费 10GB 的存储空间足够了。

如何设计一个工程效率实践的产品

场景回顾

研发团队里面产品和开发的对接方式无外乎以下几种:

  1. 原型图/交互图+prd(需求文档描述);
  2. Gitlab + Markdown(编写的prd+原型图);
  3. 禅道的需求管理:prd+原型图;
  4. Axure 做的产品需求文档,导出html页面 熟悉 Axure 的人可能会说,Axure 就可以生成在线预览地址的,但是由于众所周知的原因,这个地址可能你无法访问;
  5. Axure(HTML) + Gitlab(版本管理以及自动化流程)的在线需求文档;

以上是我们的一些尝试,不知道大家是哪一种呢?如果你们有其他更好的方式,还请大家留言,目前我们使用的是第 5 种。

在正式开始之前,我把产品经理的基本流程概述一下(有一些环节我隐掉了):

  1. 首先,产品经理撰写需求文档(可能采用的工具:word, markdown,axure,禅道,墨刀等);
  2. 产品将需求文档发给开发(方式:直接给文件,svn/git 上传,共享文件等);
  3. 产品变更需求,重新再发送(可能发生多次);

从上面的流程中,我们可以看出产品人员需要做很多的沟通和操作,一点都不高效。

每一次变更你都必须重新更新上传,然后通知每个人。

针对以上场景的优化版本

  • 产品经理撰写需求文档
  • 提交到 Gitlab
  • 触发 Gitlab Webhook
  • pg:生成在线需求文档【包括:拉取需求文档到服务器使用 qshell 上传需求文档到七牛云得到在线需求文档地址 URL】
  • 通过钉钉/Slack 机器人通知相关人。

整个过程中,产品经理只需要做一件事:撰写需求文档,其他所有的工作都自动化了(这就是我们的工程效率实践)。

说了那么多,咱们进入正题吧!

构建产品需求在线文档

目标

  1. 快速将 HTML 页面生成一个可预览的在线地址;
  2. HTML 页面也需要版本管理(Gitlab, Github, Coding, 码云等);
  • 每一次改动都有迹可循,别以为你偷偷改产品文档我们就不知道了;
  1. 基于钉钉/Slack 机器人能够及时同步新增和变更;

在线地址规则

  1. 七牛云存储 CDN 分发会给每一个空间分配一个域名 http://xxx.bkt.clouddn.com;
  2. 文件格式: http://xxx.bkt.clouddn.com/pg_v1.0/index.html,实际对照 Gitlab :https://xxx.gitlab.com/pg_group/pg_project/pg_v1.0/index.html;
  3. 自定义域名(七牛云分配的域名可以备自定义为自己的域名-DNS 配置域名解析);

项目结构

  ├── pg_group
  │----├── pg_project1
  │----│----├── pg_v1.0  
  │----│----├── pg_v1.1  
  │----│----└── pg_v2.0  
  │----└── pg_project2

详细操作步骤

新增产品需求文档

  1. 登录进入 Gitlab 网站(可以是自建 Gitlab,Github,Coding,码云等);
  2. 点击 New Group (https://xxx.gitlab.com/groups/new),填写 pg_group 信息,点击创建即可;
  3. 点击 New Project (https://xxx.gitlab.com/projects/new) ,选择 pg_group ,然后填写:pg_project和基本描述,点击创建即可;
  4. 进入 pg_project 项目;
  5. 点击 Settings->Integrations ,配置该项目的 Webhook,在 URL 填写 https://ip:port/v1/webhook/process?dingAccessToken=xxxxxxx (此 token 为钉钉机器人的 token,如果不需要可以不加此参数),在 Secret Token 填写 xxx,Trigger 勾选 Push events,点击 Add webhook 即可完成 Webhook 的添加;
  6. git clone git@xxx.gitlab.com:pg_group/pg_project.git 到你本地~/develop/workspace/xxx.gitlab.com/pg_group/pg_project;
  7. 在 pg_project 目录下创建产品需求版本目录 pg_v1.0;
  8. 将 Axure 导出的 HTML 文件拷贝到 pg_project/pg_v1.0 目录;
  9. 提交 pg_project 项目到 gitlab。
  10. 触发 Webhook,执行自动化处理流程(这里不做阐述了);

增加产品需求文档的小版本

  1. 在 pg_project 目录下创建产品需求版本目录 pg_v1.1 或者 pg_v2.0 ;
  2. 将 Axure 导出的 HTML 文件拷贝到 pg_project/pg_v1.1 目录;
  3. 提交 pg_project 项目到 gitlab。
  4. 触发 Webhook,执行自动化处理流程(这里不做阐述了);

产品需求文档变更

  1. 将 Axure 导出的 HTML 文件拷贝到 pg_project/pg_v1.0 目录;
  2. 提交 pg_project 项目到 gitlab。
  3. 触发 Webhook,执行自动化处理流程(这里不做阐述了);

技术点

  • Webhook 如何监听对应的变更(新增或者更新);
  • 上传七牛 CDN,如何封装 qshell 的调用;
  • 钉钉机器人通知相关群组(推送信息包括:在线文档的 URL 地址)

核心代码

Gitlab Webhook PushEvents 推送的结构体:

// PushEvents 请求对应的实体
type PushEvents struct {
  After       string `json:"after"`
  Before      string `json:"before"`
  CheckoutSha string `json:"checkout_sha"`
  Commits     []struct {
    Added  []string `json:"added"`
    Author struct {
      Email string `json:"email"`
      Name  string `json:"name"`
    } `json:"author"`
    ID        string   `json:"id"`
    Message   string   `json:"message"`
    Modified  []string `json:"modified"`
    Removed   []string `json:"removed"`
    Timestamp string   `json:"timestamp"`
    URL       string   `json:"url"`
  } `json:"commits"`
  EventName  string `json:"event_name"`
  Message    string `json:"message"`
  ObjectKind string `json:"object_kind"`
  Project    struct {
    AvatarURL         string `json:"avatar_url"`
    CiConfigPath      string `json:"ci_config_path"`
    DefaultBranch     string `json:"default_branch"`
    Description       string `json:"description"`
    GitHTTPURL        string `json:"git_http_url"`
    GitSSHURL         string `json:"git_ssh_url"`
    Homepage          string `json:"homepage"`
    HTTPURL           string `json:"http_url"`
    Name              string `json:"name"`
    Namespace         string `json:"namespace"`
    PathWithNamespace string `json:"path_with_namespace"`
    SSHURL            string `json:"ssh_url"`
    URL               string `json:"url"`
    VisibilityLevel   int64  `json:"visibility_level"`
    WebURL            string `json:"web_url"`
  } `json:"project"`
  ProjectID  int64  `json:"project_id"`
  Ref        string `json:"ref"`
  Repository struct {
    Description     string `json:"description"`
    GitHTTPURL      string `json:"git_http_url"`
    GitSSHURL       string `json:"git_ssh_url"`
    Homepage        string `json:"homepage"`
    Name            string `json:"name"`
    URL             string `json:"url"`
    VisibilityLevel int64  `json:"visibility_level"`
  } `json:"repository"`
  TotalCommitsCount int64  `json:"total_commits_count"`
  UserAvatar        string `json:"user_avatar"`
  UserEmail         string `json:"user_email"`
  UserID            int64  `json:"user_id"`
  UserName          string `json:"user_name"`
  UserUsername      string `json:"user_username"`
}
// quploadRun 执行 qshell 的 qupload 命令,将产品文档的文件同步到七牛
func quploadRun(prdJSONPath string) error {
  cmd := exec.Command(cfg.QshellPath, "qupload", "4", prdJSONPath)
  _, err := cmd.CombinedOutput()
  return err
}

给你的产品赋予生命力

整合钉钉/Slack 等机器人

简单的机器人其实就是你给它指令,它去执行罢了。当我们的流程执行完成之后,发送一条消息到指定的钉钉讨论组(群)即可,还可以附加一些消息。

// SendDinghook 钉钉发送信息
func SendDinghook(dingAccessToken string, title string, content string) {
  ding := dinghook.Ding{AccessToken: dingAccessToken}
  markdown := dinghook.Markdown{Title: title, Content: content}
  ding.Send(markdown)
}

未来?

  • 增加一个统一的产品需求展示页面(URL 链接需要增加时间戳鉴权处理,防止泄露)
  • 增加一个可以方便配置 Webhook 的管理控制台;

遇到的问题/坑

  • Open account file error, open ~/.qshell/account.json: no such file or directory, please use account to set AccessKey and SecretKey first

需要提前在你本地或者服务器上执行qshell account AccessKeyXxx SecretKeyXxx

参考资料

  1. https://github.com/yangwenmai/pg
  2. https://www.zhihu.com/question/19892861/answer/31059703
  3. https://en.wikipedia.org/wiki/Webhook

原文发布于微信公众号 - GitChat精品课(CSDN_Tech)

原文发表时间:2018-05-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏美图数据技术团队

美图离线ETL实践

感谢阅读「美图数据技术团队」的第 13 篇文章,关注我们持续获取美图最新数据技术动态。

28700
来自专栏xingoo, 一个梦想做发明家的程序员

【插件开发】—— 1 Eclipse插件开发导盲

在真正接触eclipse插件开发一个月后,对插件的开发过程以及技术要求,也有了一定的了解。遥想之前像无头苍蝇一样乱撞乱学,真心觉得浪费了不少时间。这里就总结...

43290
来自专栏大数据-Hadoop、Spark

大数据权限与安全

权限的管控,历来是大数据平台中最让人头疼的问题之一。管得严了,业务不流畅,用户不开心,放得宽了,安全没有底,你能放心?而且大数据平台组件,服务众多;架构,流程复...

92740
来自专栏程序你好

Monolithic架构到微服务

这种应用程序不是说只负责单个任务,但它们需要几个任务来完成特定的职责。在单体应用程序中,所有服务都打包成一个包,并作为一个进程运行。在单个应用程序中,用户界面、...

24020
来自专栏Android 开发者

Android UI 及 API 优化指南|Android 开发者 FAQ Vol.10

18640
来自专栏开源项目

优质推荐 | 看 3 月新增1k+ Star 及 GVP 项目如何将你俘获

16820
来自专栏Linyb极客之路

为什么要使用服务网格Service Mesh?

对于实现生产环境的构建和部署的人来说,这是一场噩梦。并且假设它们共享相同的操作系统但需要隔离,或者出于可移植性原因将它们打包到单独的VM镜像中。为每个服务实...

16630
来自专栏FreeBuf

沙盒逃逸:谷歌应用引擎(GAE)中存在30+个沙盒绕过漏洞

安全研究人员在谷歌应用引擎(Google App Engine)的Java环境中发现了大量高危漏洞,攻击者可以利用这些漏洞绕过谷歌安全沙盒的保护。 谷歌应用引擎...

24370
来自专栏程序员宝库

看吧,这就是现代化 PHP 该有的样子

这是一篇社区协同翻译的文章,已完成翻译,更多信息请点击 协同翻译介绍 。 讨论请前往:https://laravel-china.org/topics/8690...

53060
来自专栏Forrest随想录

XXOps实践:持续发布和部署

上周分享了一篇文章《有了CMDB,为什么还要应用配置管理》,主要讲了基础层面应该怎么做,那基础的东西做好了,如果用不起来,就没有价值,那我们今天就来看看在此基础...

14040

扫码关注云+社区

领取腾讯云代金券