mirror of
https://github.com/clem109/drone-wechat.git
synced 2026-06-04 10:23:45 +08:00
first big commit
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# drone-wechat
|
||||
# drone-wechat (WORK IN PROGRESS)
|
||||
|
||||
Drone plugin to send build status notifications via WeChat for Work. For usage
|
||||
information please look at [the docs](DOCS.md).
|
||||
@@ -18,18 +18,21 @@ go build
|
||||
Build the Docker image with the following commands:
|
||||
|
||||
```
|
||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -a -tags netgo -o release/linux/amd64/drone-webhook
|
||||
docker build --rm -t plugins/webhook .
|
||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -a -tags netgo -o release/linux/amd64/drone-wechat
|
||||
docker build --rm -t plugins/drone-wechat .
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```
|
||||
docker run --rm \
|
||||
-e PLUGIN_URLS=https://bbc.com/... \
|
||||
-e PLUGIN_HEADERS="HEADER1=value1" \
|
||||
-e PLUGIN_USERNAME=drone \
|
||||
-e PLUGIN_PASSWORD=password \
|
||||
-e PLUGIN_ACCESS_TOKEN=accesstoken \
|
||||
-e PLUGIN_AGENT_ID=agentid \
|
||||
-e PLUGIN_DEBUG=true \
|
||||
-e PLUGIN_MSG_URL=url \
|
||||
-e PLUGIN_BTN_TXT=true \
|
||||
-e PLUGIN_TITLE=title \
|
||||
-e PLUGIN_DESCRIPTION=description \
|
||||
-e DRONE_REPO_OWNER=octocat \
|
||||
-e DRONE_REPO_NAME=hello-world \
|
||||
-e DRONE_COMMIT_SHA=7fd1a60b01f91b314f59955a4e4d4e80d8edf11d \
|
||||
@@ -39,5 +42,5 @@ docker run --rm \
|
||||
-e DRONE_BUILD_STATUS=success \
|
||||
-e DRONE_BUILD_LINK=http://github.com/octocat/hello-world \
|
||||
-e DRONE_TAG=1.0.0 \
|
||||
plugins/webhook
|
||||
plugins/drone-wechat
|
||||
```
|
||||
|
||||
Binary file not shown.
@@ -23,15 +23,27 @@ func main() {
|
||||
EnvVar: "PLUGIN_METHOD",
|
||||
Value: "POST",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "url",
|
||||
Usage: "wechat work url",
|
||||
EnvVar: "PLUGIN_URL",
|
||||
Value: "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "access-token",
|
||||
Usage: "The access token for authorization",
|
||||
EnvVar: "PLUGIN_ACCESS_TOKEN,WEBHOOK_ACCESS_TOKEN",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "agentid",
|
||||
Usage: "Agent ID",
|
||||
EnvVar: "PLUGIN_AGENT_ID,WEBHOOK_AGENT_ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "msgtype",
|
||||
Usage: "The type of message, either text, textcard",
|
||||
EnvVar: "PLUGIN_MSGTYPE,WEBHOOK_MSGTYPE",
|
||||
Value: "textcard",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "content-type",
|
||||
@@ -50,22 +62,32 @@ func main() {
|
||||
Usage: "Party ID to send messages to",
|
||||
EnvVar: "PLUGIN_TO_PARTY",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "title",
|
||||
Usage: "Message title",
|
||||
EnvVar: "PLUGIN_TITLE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "description",
|
||||
Usage: "Description ",
|
||||
EnvVar: "PLUGIN_DESCRIPTION",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "msgurl",
|
||||
Usage: "message url ",
|
||||
EnvVar: "PLUGIN_MSG_URL",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "btntxt",
|
||||
Usage: "Button text ",
|
||||
EnvVar: "PLUGIN_BTN_TXT",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "safe",
|
||||
Usage: "Whether to make this message confidential or not, 0 is false, 1 is true. Defaults to false",
|
||||
EnvVar: "PLUGIN_SAFE",
|
||||
Value: "0",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "content",
|
||||
Usage: "custom template for webhook",
|
||||
EnvVar: "PLUGIN_CONTENT",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "headers",
|
||||
Usage: "custom headers key map",
|
||||
EnvVar: "PLUGIN_HEADERS",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "enable debug information",
|
||||
@@ -191,14 +213,17 @@ func run(c *cli.Context) error {
|
||||
Config: Config{
|
||||
Method: c.String("method"),
|
||||
AccessToken: c.String("access-token"),
|
||||
Agentid: c.Int("agentid"),
|
||||
MsgType: c.String("msgtype"),
|
||||
ToUser: c.StringSlice("touser"),
|
||||
ToParty: c.StringSlice("toparty"),
|
||||
URL: c.String("url"),
|
||||
MsgURL: c.String("msgurl"),
|
||||
BtnTxt: c.String("btntxt"),
|
||||
ToUser: c.String("touser"),
|
||||
ToParty: c.String("toparty"),
|
||||
Title: c.String("title"),
|
||||
Description: c.String("description"),
|
||||
Safe: c.Bool("safe"),
|
||||
Content: c.String("content"),
|
||||
ContentType: c.String("content-type"),
|
||||
Template: c.String("template"),
|
||||
Headers: c.StringSlice("headers"),
|
||||
Debug: c.Bool("debug"),
|
||||
SkipVerify: c.Bool("skip-verify"),
|
||||
},
|
||||
|
||||
@@ -7,9 +7,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,16 +38,19 @@ type (
|
||||
Config struct {
|
||||
Method string
|
||||
AccessToken string
|
||||
MsgType string
|
||||
ToUser []string
|
||||
ToParty []string
|
||||
Agentid int `json:"agentid"`
|
||||
MsgType string `json:"msgtype"`
|
||||
URL string
|
||||
MsgURL string
|
||||
BtnTxt string
|
||||
ToUser string `json:"touser"`
|
||||
ToParty string `json:"toparty"`
|
||||
Safe bool
|
||||
Content string
|
||||
ContentType string
|
||||
Template string
|
||||
Headers []string
|
||||
Debug bool
|
||||
SkipVerify bool
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
Job struct {
|
||||
@@ -69,7 +69,7 @@ func (p Plugin) Exec() error {
|
||||
var buf bytes.Buffer
|
||||
var b []byte
|
||||
|
||||
if p.Config.Content == "" {
|
||||
if p.Config.Title == "" {
|
||||
data := struct {
|
||||
Repo Repo `json:"repo"`
|
||||
Build Build `json:"build"`
|
||||
@@ -81,12 +81,25 @@ func (p Plugin) Exec() error {
|
||||
}
|
||||
b = buf.Bytes()
|
||||
} else {
|
||||
txt, err := RenderTrim(p.Config.Template, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
text := txt
|
||||
b = []byte(text)
|
||||
textCard := struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
MsgURL string `json:"url"`
|
||||
BtnTxt string `json:"btntext"`
|
||||
}{p.Config.Title, p.Config.Description, p.Config.MsgURL, p.Config.BtnTxt}
|
||||
data := struct {
|
||||
ToUser string `json:"touser"`
|
||||
MsgType string `json:"msgtype"`
|
||||
Agentid int `json:"agentid"`
|
||||
TextCard struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
MsgURL string `json:"url"`
|
||||
BtnTxt string `json:"btntext"`
|
||||
} `json:"textcard"`
|
||||
}{p.Config.ToUser, p.Config.MsgType, p.Config.Agentid, textCard}
|
||||
|
||||
b, _ = json.Marshal(data) // []byte(data)
|
||||
|
||||
}
|
||||
|
||||
@@ -95,80 +108,61 @@ func (p Plugin) Exec() error {
|
||||
// and content_type values will be applied to
|
||||
// every webhook request.
|
||||
|
||||
// TODO: Construct URL for WeChat work
|
||||
url := p.Config.URL + p.Config.AccessToken
|
||||
fmt.Println("URL:>", url)
|
||||
|
||||
for i, rawurl := range p.Config.URLs {
|
||||
uri, err := url.Parse(rawurl)
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(b))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
// client := &http.Client{}
|
||||
|
||||
client := http.DefaultClient
|
||||
if p.Config.SkipVerify {
|
||||
client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Failed to execute the HTTP request. %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
fmt.Println("response Status:", resp.Status)
|
||||
fmt.Println("response Headers:", resp.Header)
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response Body:", string(body))
|
||||
|
||||
if p.Config.Debug || resp.StatusCode >= http.StatusBadRequest {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Failed to parse the hook URL. %s\n", err)
|
||||
os.Exit(1)
|
||||
fmt.Printf("Error: Failed to read the HTTP response body. %s\n", err)
|
||||
}
|
||||
|
||||
r := bytes.NewReader(b)
|
||||
|
||||
req, err := http.NewRequest(p.Config.Method, uri.String(), r)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Failed to create the HTTP request. %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", p.Config.ContentType)
|
||||
|
||||
for _, value := range p.Config.Headers {
|
||||
header := strings.Split(value, "=")
|
||||
req.Header.Set(header[0], header[1])
|
||||
}
|
||||
|
||||
if p.Config.Username != "" && p.Config.Password != "" {
|
||||
req.SetBasicAuth(p.Config.Username, p.Config.Password)
|
||||
}
|
||||
|
||||
client := http.DefaultClient
|
||||
if p.Config.SkipVerify {
|
||||
client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Failed to execute the HTTP request. %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if p.Config.Debug || resp.StatusCode >= http.StatusBadRequest {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Error: Failed to read the HTTP response body. %s\n", err)
|
||||
}
|
||||
|
||||
if p.Config.Debug {
|
||||
fmt.Printf(
|
||||
debugRespFormat,
|
||||
i+1,
|
||||
req.URL,
|
||||
req.Method,
|
||||
req.Header,
|
||||
string(b),
|
||||
resp.Status,
|
||||
string(body),
|
||||
)
|
||||
} else {
|
||||
fmt.Printf(
|
||||
respFormat,
|
||||
i+1,
|
||||
req.URL,
|
||||
resp.Status,
|
||||
string(body),
|
||||
)
|
||||
}
|
||||
if p.Config.Debug {
|
||||
fmt.Printf(
|
||||
debugRespFormat,
|
||||
req.URL,
|
||||
req.Method,
|
||||
req.Header,
|
||||
string(b),
|
||||
resp.Status,
|
||||
string(body),
|
||||
)
|
||||
} else {
|
||||
fmt.Printf(
|
||||
respFormat,
|
||||
req.URL,
|
||||
resp.Status,
|
||||
string(body),
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
Binary file not shown.
Vendored
+35
-35
@@ -1,37 +1,37 @@
|
||||
{
|
||||
"comment": "",
|
||||
"ignore": "test",
|
||||
"package": [
|
||||
{
|
||||
"checksumSHA1": "PZ4KJai7DnuJ2YNJ2v2l2BseB1g=",
|
||||
"path": "github.com/aymerick/raymond",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Rvn+RH9pwFno1w6W+mhWsj/PxlA=",
|
||||
"path": "github.com/aymerick/raymond/ast",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "5SJwPK0MYtJt5YiE1BNc9Wl3+S0=",
|
||||
"path": "github.com/aymerick/raymond/lexer",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "TCu/8QBP8TApLjSt13a7Qjnyxrs=",
|
||||
"path": "github.com/aymerick/raymond/parser",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "9LeR7BH4PSu8LRDZ8bY7QY1HXJE=",
|
||||
"path": "github.com/urfave/cli",
|
||||
"revision": "4b90d79a682b4bf685762c7452db20f2a676ecb2",
|
||||
"revisionTime": "2017-07-06T19:46:25Z"
|
||||
}
|
||||
],
|
||||
"rootPath": "github.com/drone-plugins/drone-webhook"
|
||||
"comment": "",
|
||||
"ignore": "test",
|
||||
"package": [
|
||||
{
|
||||
"checksumSHA1": "PZ4KJai7DnuJ2YNJ2v2l2BseB1g=",
|
||||
"path": "github.com/aymerick/raymond",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Rvn+RH9pwFno1w6W+mhWsj/PxlA=",
|
||||
"path": "github.com/aymerick/raymond/ast",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "5SJwPK0MYtJt5YiE1BNc9Wl3+S0=",
|
||||
"path": "github.com/aymerick/raymond/lexer",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "TCu/8QBP8TApLjSt13a7Qjnyxrs=",
|
||||
"path": "github.com/aymerick/raymond/parser",
|
||||
"revision": "72acac2207479d21dd45898c2a4264246c818148",
|
||||
"revisionTime": "2016-12-09T22:07:24Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "9LeR7BH4PSu8LRDZ8bY7QY1HXJE=",
|
||||
"path": "github.com/urfave/cli",
|
||||
"revision": "4b90d79a682b4bf685762c7452db20f2a676ecb2",
|
||||
"revisionTime": "2017-07-06T19:46:25Z"
|
||||
}
|
||||
],
|
||||
"rootPath": "github.com/clem109/drone-wechat"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user