package main import ( "encoding/json" "fmt" "io" "log" "net/http" "net/url" "path" "strings" "time" ) type Build struct { Actions []Action `json:"actions"` Number interface{} `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"` } var client = &http.Client{ Timeout: 10 * time.Second, } func FetchBuild(cfg *Config, job string) (*Build, error) { buildID := cfg.Jenkins.Number api := fmt.Sprintf("%s://%s/job/%s/%s/api/json", cfg.Jenkins.Schema, cfg.Jenkins.URL, job, buildID, ) req, err := http.NewRequest("GET", api, nil) if err != nil { log.Printf("failed to create GET request %s: %v", job, err) return nil, err } req.SetBasicAuth(cfg.Jenkins.User, cfg.Jenkins.Token) resp, err := client.Do(req) if err != nil { log.Printf("failed to fetch build %s: %v", job, err) return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { log.Printf("failed to fetch build %s: %s", job, resp.Status) return nil, fmt.Errorf("failed to fetch build: %s", resp.Status) } // io限制,1m body, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) var build Build if err := json.Unmarshal(body, &build); err != nil { log.Printf("failed to unmarshal build %s: %v", job, err) return nil, err } return &build, nil } func GenerateBuildURL(cfg *Config, 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 cfg.Jenkins.DefaultParameters { for k, v := range param { values.Set(k, fmt.Sprintf("%v", v)) } } u, err := url.Parse(build.URL) if err != nil { log.Fatalf("failed to parse build URL: %v", err) } parts := strings.Split(strings.TrimSuffix(u.Path, "/"), "/") if len(parts) > 0 { u.Path = path.Join(parts[:len(parts)-1]...) + "/buildWithParameters" } u.RawQuery = values.Encode() return u.String() } func TriggerBuild(cfg *Config, build *Build) error { url := GenerateBuildURL(cfg, build) req, err := http.NewRequest("POST", url, nil) if err != nil { log.Printf("failed to create POST request: %v", err) return err } req.SetBasicAuth(cfg.Jenkins.User, cfg.Jenkins.Token) resp, err := client.Do(req) if err != nil { log.Printf("failed to trigger build %s: %v", url, err) return err } defer resp.Body.Close() log.Printf("triggered build %s: %s", url, resp.Status) return nil }