mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-20 01:04:15 +00:00
add labels to the manifest annotations
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package atproto
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -15,18 +16,20 @@ import (
|
||||
type ManifestStore struct {
|
||||
client *Client
|
||||
repository string
|
||||
holdEndpoint string // Hold service endpoint where blobs are stored (for push)
|
||||
did string // User's DID for cache key
|
||||
lastFetchedHoldEndpoint string // Hold endpoint from most recently fetched manifest (for pull)
|
||||
holdEndpoint string // Hold service endpoint where blobs are stored (for push)
|
||||
did string // User's DID for cache key
|
||||
lastFetchedHoldEndpoint string // Hold endpoint from most recently fetched manifest (for pull)
|
||||
blobStore distribution.BlobStore // Blob store for fetching config during push
|
||||
}
|
||||
|
||||
// NewManifestStore creates a new ATProto-backed manifest store
|
||||
func NewManifestStore(client *Client, repository string, holdEndpoint string, did string) *ManifestStore {
|
||||
func NewManifestStore(client *Client, repository string, holdEndpoint string, did string, blobStore distribution.BlobStore) *ManifestStore {
|
||||
return &ManifestStore{
|
||||
client: client,
|
||||
repository: repository,
|
||||
holdEndpoint: holdEndpoint,
|
||||
did: did,
|
||||
blobStore: blobStore,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +119,25 @@ func (s *ManifestStore) Put(ctx context.Context, manifest distribution.Manifest,
|
||||
manifestRecord.ManifestBlob = blobRef
|
||||
manifestRecord.HoldEndpoint = s.holdEndpoint
|
||||
|
||||
// Extract Dockerfile labels from config blob and add to annotations
|
||||
if s.blobStore != nil && manifestRecord.Config.Digest != "" {
|
||||
labels, err := s.extractConfigLabels(ctx, manifestRecord.Config.Digest)
|
||||
if err != nil {
|
||||
// Log error but don't fail the push - labels are optional
|
||||
fmt.Printf("WARNING: Failed to extract config labels: %v\n", err)
|
||||
} else {
|
||||
// Initialize annotations map if needed
|
||||
if manifestRecord.Annotations == nil {
|
||||
manifestRecord.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
// Copy labels to annotations (Dockerfile LABELs → manifest annotations)
|
||||
maps.Copy(manifestRecord.Annotations, labels)
|
||||
|
||||
fmt.Printf("DEBUG: Extracted %d labels from config blob\n", len(labels))
|
||||
}
|
||||
}
|
||||
|
||||
// Store manifest record in ATProto
|
||||
rkey := digestToRKey(dgst)
|
||||
_, err = s.client.PutRecord(ctx, ManifestCollection, rkey, manifestRecord)
|
||||
@@ -185,3 +207,31 @@ func (m *rawManifest) References() []distribution.Descriptor {
|
||||
func (m *rawManifest) Payload() (string, []byte, error) {
|
||||
return m.mediaType, m.payload, nil
|
||||
}
|
||||
|
||||
// extractConfigLabels fetches the image config blob and extracts Dockerfile LABELs
|
||||
func (s *ManifestStore) extractConfigLabels(ctx context.Context, configDigestStr string) (map[string]string, error) {
|
||||
// Parse digest string
|
||||
configDigest, err := digest.Parse(configDigestStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid config digest: %w", err)
|
||||
}
|
||||
|
||||
// Fetch config blob from storage
|
||||
configData, err := s.blobStore.Get(ctx, configDigest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch config blob: %w", err)
|
||||
}
|
||||
|
||||
// Parse config JSON
|
||||
var configJSON struct {
|
||||
Config struct {
|
||||
Labels map[string]string `json:"Labels"`
|
||||
} `json:"config"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(configData, &configJSON); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config JSON: %w", err)
|
||||
}
|
||||
|
||||
return configJSON.Config.Labels, nil
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@ func NewRoutingRepository(
|
||||
func (r *RoutingRepository) Manifests(ctx context.Context, options ...distribution.ManifestServiceOption) (distribution.ManifestService, error) {
|
||||
// Create or return cached manifest store
|
||||
if r.manifestStore == nil {
|
||||
r.manifestStore = atproto.NewManifestStore(r.atprotoClient, r.repositoryName, r.storageEndpoint, r.did)
|
||||
// Ensure blob store is created first (needed for label extraction during push)
|
||||
blobStore := r.Blobs(ctx)
|
||||
|
||||
r.manifestStore = atproto.NewManifestStore(r.atprotoClient, r.repositoryName, r.storageEndpoint, r.did, blobStore)
|
||||
}
|
||||
|
||||
// After any manifest operation, cache the hold endpoint for blob fetches
|
||||
|
||||
Reference in New Issue
Block a user