はじめに
GoのLambdaで構成に図示したような形でBacklogの課題情報を取ってきたり、課題情報を更新する実装を行ったのでその備忘録を残す。
※Lambda関数(Go)でSlack通知やAWS ChatbotでSlackからLambda関数(Go)を呼び出すの記事の続きの関連で、DevOps導入に関係して行った事。
構成
Code BuildのBuildを実行するLambda(Go)を呼び出した時に、Backlogの課題のステータスを確認してあるステータスならそのままBuildを続行しそうでないなら中断。
また、Build完了時にBacklogの課題のステータスをあるステータスに更新する。
GoでWeb APIをCallする
GET
Backlogの課題のステータスを確認してあるステータスならそのままBuildを続行を判断するための、Backlogの課題ステータスをチェックする関数は以下。
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type Issue struct {
Status Status `json:"status"`
}
type Status struct {
Id int
ProjectId int
Name string
}
func checkIssueStatus(issueKey string) string {
reqUrl := "https://" + os.Getenv("BACKLOG_DOMEIN") + ".backlog.com/api/v2/issues/" + issueKey + "?apiKey=" + os.Getenv("BACKLOG_API_KEY")
resp, err := http.Get(reqUrl)
if err != nil {
fmt.Println("Request Error:", err)
return "Request Error:" + err.Error()
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
fmt.Println("Response Error:", resp.Status)
return "Response Error:" + resp.Status
}
body, err := io.ReadAll(resp.Body)
fmt.Println(string(body))
var issue Issue
json.Unmarshal(body, &issue)
fmt.Println("issue.Status.name : ", issue.Status.Name)
fmt.Println("issue.Status.id : ", issue.Status.Id)
if issue.Status.Name != os.Getenv("BACKLOG_ISSUE_STATUS") {
fmt.Println("Status Error:", issue.Status.Name)
return "Status Error:" + issue.Status.Name
}
return "ok"
}
- ※注意点①
公式にもThe client must close the response body when finished with it:(クライアントは、応答が終了したら、応答本文を閉じる必要があります。)
と書かれている通り、defer resp.Body.Close()
とする事。これをしないとTCPコネクションが開きっぱなしになる。 - ※注意点②
私はハマったが、構造体のフィールド名は大文字から始める必要があるので注意
・参考:Backlog 課題情報の取得
・参考:Go の net/http を使って Web API にリクエストを行う:CData API Server
・参考:構造体フィールド名小文字にした場合
PATCH(Content-Type:application/x-www-form-urlencoded)
Backlogの課題のステータスをあるステータスに更新する関数は以下。
import (
"fmt"
"io"
"net/http"
"os"
)
func updateIssueStatus(issueKey string) string {
reqUrl := "https://" + os.Getenv("BACKLOG_DOMEIN") + ".backlog.com/api/v2/issues/" + issueKey + "?apiKey=" + os.Getenv("BACKLOG_API_KEY")
values := url.Values{}
values.Set("statusId", os.Getenv("BACKLOG_STATUS_ID"))
req, err := http.NewRequest(
"PATCH",
reqUrl,
strings.NewReader(values.Encode()),
)
if err != nil {
fmt.Println("NewRequest Error:", err)
return "NewRequest Error:" + err.Error()
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := new(http.Client)
resp, err := client.Do(req)
if err != nil {
fmt.Println("Request Error:", err)
return "Request Error:" + err.Error()
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
fmt.Println("Response Error:", resp.Status)
return "Response Error:" + resp.Status
}
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
return "ok"
}
・参考:Backlog 課題情報の更新
・参考:■パラメータをURLエンコードする場合
ソースコード全体
以下のリポジトリにある。