Skip to content
quarry Artifact [9fbbb167c6]
Login

Artifact [9fbbb167c6]

Artifact 9fbbb167c641e343b14fe6f3c213ac44eca32862e4c7bb22424b91d8c90d41b5:


package runner

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
)

// ForgeBranch asks the forge which branch a check-in is on
// (GET /api/v1/r/<repo>/checkin/<hash>), for a runner that runs one
// branch only. The task's own input is not asked: it came from a
// pipeline the check-in under test may have written.
type ForgeBranch struct {
	API string // https://forge/api/v1/r/<repo>
	// User and Password, for a private repository, as ArchiveCheckout.
	User, Password string
	Client         *http.Client
}

func (f ForgeBranch) BranchOf(ctx context.Context, checkin string) (string, error) {
	req, err := http.NewRequestWithContext(ctx, "GET", strings.TrimSuffix(f.API, "/")+"/checkin/"+url.PathEscape(checkin), nil)
	if err != nil {
		return "", err
	}
	if f.User != "" {
		req.SetBasicAuth(f.User, f.Password)
	}
	c := f.Client
	if c == nil {
		c = http.DefaultClient
	}
	resp, err := c.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("the forge answered %d for check-in %.12s", resp.StatusCode, checkin)
	}
	var body struct {
		Hash   string `json:"hash"`
		Branch string `json:"branch"`
	}
	if err := json.NewDecoder(io.LimitReader(resp.Body, 4<<20)).Decode(&body); err != nil {
		return "", fmt.Errorf("check-in %.12s: %v", checkin, err)
	}
	if body.Hash != checkin {
		// A prefix the forge resolved, or another check-in: either way
		// not an answer about the one this task names.
		return "", fmt.Errorf("the forge answered for %.12s when asked about %.12s", body.Hash, checkin)
	}
	return body.Branch, nil
}