jenkins-cron/v2/jenkins.go
2025-05-09 17:21:06 +08:00

155 lines
3.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"path"
"strings"
"time"
)
type Build struct {
Actions []Action `json:"actions"`
Number int `json:"number"`
URL string `json:"url"`
}
type Action struct {
Class string `json:"_class"`
Parameters []Parameter `json:"parameters,omitempty"`
}
type Parameter struct {
Name string `json:"name"`
Value interface{} `json:"value"`
}
type JenkinsClient struct {
Client *http.Client
Config *Jenkins
}
func NewJenkinsClient(cfg *Jenkins) *JenkinsClient {
return &JenkinsClient{
Client: &http.Client{Timeout: 10 * time.Second},
Config: cfg,
}
}
func (c *JenkinsClient) buildAPIURL(job string) string {
return fmt.Sprintf("%s://%s/job/%s/%s/api/json",
c.Config.Schema,
c.Config.URL,
job,
c.Config.Number,
)
}
func (c *JenkinsClient) FetchBuild(job string) (*Build, error) {
api := c.buildAPIURL(job)
req, err := http.NewRequest("GET", api, nil)
if err != nil {
log.Printf("[jenkins] Failed to create GET request %s: %v", job, err)
return nil, err
}
req.SetBasicAuth(c.Config.User, c.Config.Token)
resp, err := c.Client.Do(req)
if err != nil {
log.Printf("[jenkins] Failed to fetch build %s: %v", job, err)
return nil, fmt.Errorf("request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Printf("[jenkins] Failed to fetch build %s: %s", job, resp.Status)
return nil, fmt.Errorf("unexpected status: %s", resp.Status)
}
// io限制1m
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
log.Printf("[jenkins] Failed to read response body: %v", err)
return nil, fmt.Errorf("failed to read response body: %w", err)
}
var build Build
if err := json.Unmarshal(body, &build); err != nil {
log.Printf("[jenkins] Failed to unmarshal build %s: %v", job, err)
return nil, fmt.Errorf("failed to unmarshal response body: %w", err)
}
return &build, nil
}
// 构建构建触发 URL带参数
func (c *JenkinsClient) GenerateBuildURL(build *Build) string {
values := url.Values{}
// 取出构建参数
for _, action := range build.Actions {
if action.Class == "hudson.model.ParametersAction" {
for _, param := range action.Parameters {
values.Set(param.Name, fmt.Sprintf("%v", param.Value))
}
}
}
// 加入默认参数
for _, param := range c.Config.DefaultParameters {
for k, v := range param {
values.Set(k, fmt.Sprintf("%v", v))
}
}
// 构建新的构建路径
u, err := url.Parse(build.URL)
if err != nil {
log.Printf("[jenkins] Failed to parse build URL: %v", err)
return ""
}
u.Path = getBuildWithParametersPath(u.Path)
u.RawQuery = values.Encode()
return u.String()
}
// 替换为 buildWithParameters 路径
func getBuildWithParametersPath(p string) string {
parts := strings.Split(strings.TrimSuffix(p, "/"), "/")
if len(parts) > 0 {
return path.Join(parts[:len(parts)-1]...) + "/buildWithParameters"
}
return p
}
// 触发构建
func (c *JenkinsClient) TriggerBuild(build *Build) error {
triggerURL := c.GenerateBuildURL(build)
if triggerURL == "" {
return fmt.Errorf("failed to generate trigger URL")
}
req, err := http.NewRequest("POST", triggerURL, nil)
if err != nil {
log.Printf("[jenkins] Failed to create POST request: %v", err)
return fmt.Errorf("created trigger request failed: %w", err)
}
req.SetBasicAuth(c.Config.User, c.Config.Token)
resp, err := c.Client.Do(req)
if err != nil {
log.Printf("[jenkins] Failed to trigger build %s: %v", triggerURL, err)
return fmt.Errorf("trigger request failed: %w", err)
}
defer resp.Body.Close()
log.Printf("[jenkins] Triggered build %s: %s", triggerURL, resp.Status)
return nil
}