real init

This commit is contained in:
2026-07-29 01:36:09 +01:00
parent bb8c94f06e
commit 0accff3e19
55 changed files with 3806 additions and 0 deletions
+198
View File
@@ -0,0 +1,198 @@
package handlers
import (
"encoding/json"
"fmt"
"net/http"
"sort"
"strings"
"time"
"git.dcntrlized.org/Dcntrlized/Maestro/lib/consts"
"git.dcntrlized.org/Dcntrlized/Maestro/lib/logger"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"golang.org/x/mod/semver"
)
// RegistryContainer represents a clean API payload specifically for container registry items.
type RegistryContainer struct {
Name string `json:"name"`
Version string `json:"version"`
Image string `json:"image"`
Title string `json:"title,omitempty"`
Vendor string `json:"vendor,omitempty"`
Author string `json:"author,omitempty"`
Description string `json:"description,omitempty"`
Source string `json:"source,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
}
type RawPackage struct {
Name string `json:"name"`
Version string `json:"version"`
CreatedAt string `json:"created_at"`
HTMLURL string `json:"html_url"`
Repository *struct {
HTMLURL string `json:"html_url"`
} `json:"repository"`
}
func GetRegistry(w http.ResponseWriter, r *http.Request) {
// 1. Query Gitea REST API using the exact Org name
apiURL := fmt.Sprintf("https://git.dcntrlized.org/api/v1/packages/%s?type=container", consts.GITEA_ORG)
req, err := http.NewRequestWithContext(r.Context(), http.MethodGet, apiURL, nil)
if err != nil {
logger.Error("Failed to create request: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
req.Header.Set("Authorization", "token "+consts.GITEA_RW_PACKAGE_TOKEN)
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
logger.Error("Failed to reach Gitea package API: %v", err)
http.Error(w, "Failed to connect to upstream registry", http.StatusBadGateway)
return
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
logger.Error("Registry API returned non-200 status code: %d", resp.StatusCode)
http.Error(w, fmt.Sprintf("Registry API error: %s", resp.Status), resp.StatusCode)
return
}
var rawPackages []RawPackage
if err := json.NewDecoder(resp.Body).Decode(&rawPackages); err != nil {
logger.Error("Failed to decode registry response: %v", err)
http.Error(w, "Failed to decode registry response", http.StatusInternalServerError)
return
}
// 2. Group by Name and filter out "latest" & "sha256:"
groupedPackages := make(map[string][]RawPackage)
for _, pkg := range rawPackages {
if pkg.Version == "latest" || strings.HasPrefix(pkg.Version, "sha256:") {
continue
}
groupedPackages[pkg.Name] = append(groupedPackages[pkg.Name], pkg)
}
// Helper function to normalize version strings for semver package (requires 'v' prefix)
formatSemver := func(v string) string {
if !strings.HasPrefix(v, "v") {
return "v" + v
}
return v
}
// 3. For each container name, find the package entry with the highest semver
var latestPackages []RawPackage
for _, pkgs := range groupedPackages {
if len(pkgs) == 0 {
continue
}
sort.Slice(pkgs, func(i, j int) bool {
vI := formatSemver(pkgs[i].Version)
vJ := formatSemver(pkgs[j].Version)
// Compare using semver package
if semver.IsValid(vI) && semver.IsValid(vJ) {
return semver.Compare(vI, vJ) > 0
}
// Fall back to string comparison if not valid semver
return pkgs[i].Version > pkgs[j].Version
})
// First item after descending sort is the highest version
latestPackages = append(latestPackages, pkgs[0])
}
ociAuth := remote.WithAuth(&authn.Basic{
Username: consts.GITEA_USER,
Password: consts.GITEA_RW_PACKAGE_TOKEN,
})
ociOrg := strings.ToLower(consts.GITEA_ORG)
var registryItems []RegistryContainer
// 4. Fetch OCI metadata only for the highest version of each package
for _, pkg := range latestPackages {
pkgNameLower := strings.ToLower(pkg.Name)
imageRef := fmt.Sprintf("git.dcntrlized.org/%s/%s:%s", ociOrg, pkgNameLower, pkg.Version)
source := pkg.HTMLURL
if pkg.Repository != nil && pkg.Repository.HTMLURL != "" {
source = pkg.Repository.HTMLURL
}
item := RegistryContainer{
Name: pkg.Name,
Version: pkg.Version,
Image: imageRef,
Source: source,
CreatedAt: pkg.CreatedAt,
}
ref, err := name.ParseReference(imageRef)
if err != nil {
logger.Error("Failed to parse image reference %s: %v", imageRef, err)
registryItems = append(registryItems, item)
continue
}
img, err := remote.Image(ref, ociAuth, remote.WithContext(r.Context()))
if err != nil {
logger.Error("Failed to fetch OCI metadata for %s: %v", imageRef, err)
registryItems = append(registryItems, item)
continue
}
// Extract annotations from OCI manifest
if manifest, err := img.Manifest(); err == nil && manifest != nil {
if title, ok := manifest.Annotations["org.opencontainers.image.title"]; ok {
item.Title = title
}
if vendor, ok := manifest.Annotations["org.opencontainers.image.vendor"]; ok {
item.Vendor = vendor
}
if author, ok := manifest.Annotations["org.opencontainers.image.authors"]; ok {
item.Author = author
}
if desc, ok := manifest.Annotations["org.opencontainers.image.description"]; ok {
item.Description = desc
}
}
// Fallback to Image Config labels
if configFile, err := img.ConfigFile(); err == nil && configFile != nil {
labels := configFile.Config.Labels
if item.Title == "" {
item.Title = labels["org.opencontainers.image.title"]
}
if item.Vendor == "" {
item.Vendor = labels["org.opencontainers.image.vendor"]
}
if item.Author == "" {
item.Author = labels["org.opencontainers.image.authors"]
}
if item.Description == "" {
item.Description = labels["org.opencontainers.image.description"]
}
}
registryItems = append(registryItems, item)
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(registryItems); err != nil {
logger.Error("Failed to write response: %v", err)
}
}