blob: d20da12d4b11da90a06935460ab1dbe4bf040d86 [file] [log] [blame]
package dockerimg
import (
"crypto/sha256"
_ "embed" // Using underscore import to keep embed package for go:embed directive
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
)
// DefaultImage is intended to ONLY be used by the pushdockerimg.go script.
func DefaultImage() (name, dockerfile, tag string) {
return dockerImgName, dockerfileBase, dockerfileBaseHash()
}
const (
dockerImgRepo = "boldsoftware/sketch"
dockerImgName = "ghcr.io/" + dockerImgRepo
)
func dockerfileBaseHash() string {
h := sha256.New()
io.WriteString(h, dockerfileBase)
return hex.EncodeToString(h.Sum(nil))[:32]
}
//go:embed Dockerfile.base
var dockerfileBaseData []byte
// dockerfileBase is the content of the base Dockerfile
var dockerfileBase = string(dockerfileBaseData)
func readPublishedTags() ([]string, error) {
req, err := http.NewRequest("GET", "https://ghcr.io/token?service=ghcr.io&scope=repository:"+dockerImgRepo+":pull", nil)
if err != nil {
return nil, fmt.Errorf("token: %w", err)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("token: %w", err)
}
body, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil || res.StatusCode != 200 {
return nil, fmt.Errorf("token: %d: %s: %w", res.StatusCode, body, err)
}
var tokenBody struct {
Token string `json:"token"`
}
if err := json.Unmarshal(body, &tokenBody); err != nil {
return nil, fmt.Errorf("token: %w: %s", err, body)
}
req, err = http.NewRequest("GET", "https://ghcr.io/v2/"+dockerImgRepo+"/tags/list", nil)
if err != nil {
return nil, fmt.Errorf("tags: %w", err)
}
req.Header.Set("Authorization", "Bearer "+tokenBody.Token)
res, err = http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("tags: %w", err)
}
body, err = io.ReadAll(res.Body)
res.Body.Close()
if err != nil || res.StatusCode != 200 {
return nil, fmt.Errorf("tags: %d: %s: %w", res.StatusCode, body, err)
}
var tags struct {
Tags []string `json:"tags"`
}
if err := json.Unmarshal(body, &tags); err != nil {
return nil, fmt.Errorf("tags: %w: %s", err, body)
}
return tags.Tags, nil
}
func checkTagExists(tag string) error {
tags, err := readPublishedTags()
if err != nil {
return fmt.Errorf("check tag exists: %w", err)
}
for _, t := range tags {
if t == tag {
return nil // found it
}
}
return fmt.Errorf("check tag exists: %q not found in %v", tag, tags)
}