CreateJob queues a new job using the v1 Jobs API. It may or may not return Pull Request information. If Pull Request information is required following up by polling GetJob with the job ID is necessary.
(ctx context.Context, owner, repo, problemStatement, baseBranch, customAgent string)
| 59 | // return Pull Request information. If Pull Request information is required |
| 60 | // following up by polling GetJob with the job ID is necessary. |
| 61 | func (c *CAPIClient) CreateJob(ctx context.Context, owner, repo, problemStatement, baseBranch, customAgent string) (*Job, error) { |
| 62 | if owner == "" || repo == "" { |
| 63 | return nil, errors.New("owner and repo are required") |
| 64 | } |
| 65 | if problemStatement == "" { |
| 66 | return nil, errors.New("problem statement is required") |
| 67 | } |
| 68 | |
| 69 | url := fmt.Sprintf("%s/%s/%s", c.jobsBasePathV1(), url.PathEscape(owner), url.PathEscape(repo)) |
| 70 | |
| 71 | prOpts := JobPullRequest{} |
| 72 | if baseBranch != "" { |
| 73 | prOpts.BaseRef = "refs/heads/" + baseBranch |
| 74 | } |
| 75 | |
| 76 | payload := &Job{ |
| 77 | ProblemStatement: problemStatement, |
| 78 | CustomAgent: customAgent, |
| 79 | EventType: defaultEventType, |
| 80 | PullRequest: &prOpts, |
| 81 | } |
| 82 | |
| 83 | b, _ := json.Marshal(payload) |
| 84 | |
| 85 | req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(b)) |
| 86 | if err != nil { |
| 87 | return nil, err |
| 88 | } |
| 89 | req.Header.Set("Content-Type", "application/json") |
| 90 | res, err := c.httpClient.Do(req) |
| 91 | if err != nil { |
| 92 | return nil, err |
| 93 | } |
| 94 | defer res.Body.Close() |
| 95 | |
| 96 | body, _ := io.ReadAll(res.Body) |
| 97 | |
| 98 | var j Job |
| 99 | if err := json.NewDecoder(bytes.NewReader(body)).Decode(&j); err != nil { |
| 100 | if res.StatusCode != http.StatusCreated && res.StatusCode != http.StatusOK { // accept 201 or 200 |
| 101 | // This happens when there's an error like unauthorized (401). |
| 102 | statusText := fmt.Sprintf("%d %s", res.StatusCode, http.StatusText(res.StatusCode)) |
| 103 | return nil, fmt.Errorf("failed to create job: %s", statusText) |
| 104 | } |
| 105 | return nil, fmt.Errorf("failed to decode create job response: %w", err) |
| 106 | } |
| 107 | |
| 108 | if res.StatusCode != http.StatusCreated && res.StatusCode != http.StatusOK { // accept 201 or 200 |
| 109 | statusText := fmt.Sprintf("%d %s", res.StatusCode, http.StatusText(res.StatusCode)) |
| 110 | |
| 111 | // If the response has error embeded, we can use that. |
| 112 | // TODO: Does this really ever happen? |
| 113 | if j.ErrorInfo != nil { |
| 114 | return nil, fmt.Errorf("failed to create job: %s: %s", statusText, j.ErrorInfo.Message) |
| 115 | } |
| 116 | |
| 117 | // If the response doesn't have error embedded, |
| 118 | // try to decode the response itself as a jobError. |