给鲁班造工具,为Azure DevOps编写插件

由于团队人比较懒,不是经常关注TFS的Web门户,CI/CD设置了邮件通知但也不会经常去看邮件。

最近看到企业微信上开放了一个群聊机器人API,挺简单的不用获取Token,觉得可以做个通知插件,于是便动手了。

企业微信机器人API:https://work.weixin.qq.com/api/doc?notreplace=true#90000/90135/91760

前期准备

VSCode、NodeJS、TypeScript

以上的东西码农们基本都有

然后就是要装一个 TFS Cross Platform Command Line Interface (tfx-cli) 

npm i -g tfx-cli

开始动手

首先新建文件夹,再到文件夹下执行

npm init

初始化一个npm项目

接着添加一下引用库和相关的TypeScript定义,顺便初始化tsc

#添加库
npm install azure-pipelines-task-lib --save

#添加TypeScript定义
npm install @types/node --save-dev
npm install @types/q --save-dev

#初始化tsc
tsc --init

之后注意把 tsconfig.json 的 es5 改为 es6

定义一个任务

task.json

{
    "id": "dd3a7ed0-5a5e-446a-8617-e463af51e3ff",
    "name": "往企业微信发送消息",
    "friendlyName": "通过Webhook机器人往企业微信群发送消息",
    "description": "通过Webhook机器人往企业微信群发送文本消息",
    "helpMarkDown": "",
    "category": "Utility",
    "author": "算神",
    "version": {
        "Major": 0,
        "Minor": 1,
        "Patch": 0
    },
    "instanceNameFormat": "通过Bot往企业微信群发送 $(content)",
    "inputs": [
        {
            "name": "key",
            "type": "string",
            "label": "Key",
            "defaultValue": "",
            "required": true,
            "helpMarkDown": "企业微信机器人Key"
        },
        {
            "name": "content",
            "type": "string",
            "label": "Content",
            "defaultValue": "",
            "required": true,
            "helpMarkDown": "文本内容"
        }
    ],
    "execution": {
        "Node": {
            "target": "index.js"
        }
    }
}

其中 inputs 节点下的 key 和 content 就是 两个可输入的参数

撸码

准备工作完成后,可以开始撸码了。代码也很简单,就是一段NodeJS的Post Json代码,新建 index.ts

import tl = require('azure-pipelines-task-lib/task');
import https = require('https');

async function run() {
    try {
        const key: string = tl.getInput('key', true);
        const content: string = tl.getInput('content', true);

        var data = {
            msgtype: "text",
            text: {
                content: content
            }
        };

        var json = JSON.stringify(data);

        var options = {
            host: 'qyapi.weixin.qq.com',
            port: 443,
            path: '/cgi-bin/webhook/send?key=' + key,
            method: 'POST',
            json: true,
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': Buffer.byteLength(json)
            }
        }

        var req = https.request(options, res => {
            res.setEncoding('utf8');
        });

        req.on('error', e => {
            console.log('problem with request: ' + e.message);
            tl.setResult(tl.TaskResult.Failed, e.message);
        });

        req.write(json, 'utf8');
        req.end();
    }
    catch (err) {
        tl.setResult(tl.TaskResult.Failed, err.message);
    }
}

run();

由于上面task.json配置了参数,所以这里可以通过 tl.getInput() 把参数读进来

编译

执行

tsc

可把 index.ts 编译为 index.js

发布

新建一个插件的元数据文件,vss-extension.json

{
    "manifestVersion": 1,
    "id": "wechat4work",
    "name": "WeChat Of Work",
    "version": "0.1.3",
    "publisher": "lishewen",
    "targets": [
        {
            "id": "Microsoft.VisualStudio.Services"
        }
    ],
    "description": "往企业微信发送消息",
    "categories": [
        "Azure Pipelines"
    ],
    "icons": {
        "default": "images/wechatofwork.png"
    },
    "files": [
        {
            "path": "wechat4work"
        }
    ],
    "contributions": [
        {
            "id": "custom-wechat4work-task",
            "type": "ms.vss-distributed-task.task",
            "targets": [
                "ms.vss-distributed-task.tasks"
            ],
            "properties": {
                "name": "wechat4work"
            }
        }
    ],
    "galleryFlags": [
        "Public"
    ],
    "content": {
        "details": {
            "path": "overview.md"
        }
    },
    "screenshots": [
        {
            "path": "screenshots/screen1.png"
        },
        {
            "path": "screenshots/screen2.png"
        },
        {
            "path": "screenshots/screen3.png"
        }
    ],
    "links": {
        "home": {
            "uri": "http://blog.lishewen.com/"
        },
        "repository": {
            "uri": "https://github.com/lishewen/WeChat4Work-VSS-Extension"
        },
        "issues": {
            "uri": "https://github.com/lishewen/WeChat4Work-VSS-Extension/issues"
        }
    },
    "repository": {
        "type": "git",
        "uri": "https://github.com/lishewen/WeChat4Work-VSS-Extension"
    }
}

然后执行指令

tfx extension create --manifest-globs vss-extension.json

便可把撸的代码打包为vsix,上传发布

成果展示

项目成品地址:https://marketplace.visualstudio.com/items?itemName=lishewen.wechat4work

项目开源地址:https://github.com/lishewen/WeChat4Work-VSS-Extension