A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
81
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix lint and unit tests

+41 -52
+6 -6
pkg/atproto/client.go
··· 104 104 pdsEndpoint: pdsEndpoint, 105 105 did: did, 106 106 clientProvider: NewBasicAuthClientProvider(pdsEndpoint, did, accessToken), 107 - httpClient: &http.Client{}, 107 + httpClient: &http.Client{Timeout: 30 * time.Second}, 108 108 } 109 109 } 110 110 ··· 121 121 pdsEndpoint: pdsEndpoint, 122 122 did: did, 123 123 clientProvider: NewOAuthClientProvider(sessionProvider), 124 - httpClient: &http.Client{}, 124 + httpClient: &http.Client{Timeout: 30 * time.Second}, 125 125 } 126 126 } 127 127 ··· 259 259 // Note: This is a sync endpoint that returns raw binary data 260 260 func (c *Client) GetBlob(ctx context.Context, cid string) ([]byte, error) { 261 261 // Public endpoint - no auth required 262 - client := &xrpc.Client{Host: c.pdsEndpoint} 262 + client := &xrpc.Client{Host: c.pdsEndpoint, Client: c.httpClient} 263 263 data, err := comatproto.SyncGetBlob(ctx, client, cid, c.did) 264 264 if err != nil { 265 265 var xrpcErr *xrpc.Error ··· 294 294 } 295 295 296 296 // Public endpoint - no auth required 297 - client := &xrpc.Client{Host: c.pdsEndpoint} 297 + client := &xrpc.Client{Host: c.pdsEndpoint, Client: c.httpClient} 298 298 var result ListReposByCollectionResult 299 299 err := client.LexDo(ctx, "GET", "", "com.atproto.sync.listReposByCollection", params, nil, &result) 300 300 if err != nil { ··· 318 318 } 319 319 320 320 // Public endpoint - no auth required 321 - client := &xrpc.Client{Host: c.pdsEndpoint} 321 + client := &xrpc.Client{Host: c.pdsEndpoint, Client: c.httpClient} 322 322 var result struct { 323 323 Records []Record `json:"records"` 324 324 Cursor string `json:"cursor,omitempty"` ··· 352 352 // The actor parameter can be a DID or handle 353 353 func (c *Client) GetActorProfile(ctx context.Context, actor string) (*ActorProfile, error) { 354 354 // Public endpoint - doesn't require auth 355 - client := &xrpc.Client{Host: c.pdsEndpoint} 355 + client := &xrpc.Client{Host: c.pdsEndpoint, Client: c.httpClient} 356 356 357 357 resp, err := appbsky.ActorGetProfile(ctx, client, actor) 358 358 if err != nil {
-16
pkg/hold/admin/auth.go
··· 112 112 http.Error(w, "Internal server error", http.StatusInternalServerError) 113 113 } 114 114 } 115 - 116 - // renderError renders an error page 117 - func (ui *AdminUI) renderError(w http.ResponseWriter, r *http.Request, message string, statusCode int) { 118 - w.Header().Set("Content-Type", "text/html; charset=utf-8") 119 - w.WriteHeader(statusCode) 120 - 121 - data := struct { 122 - PageData 123 - Error string 124 - }{ 125 - PageData: ui.newPageData(r, "Error", ""), 126 - Error: message, 127 - } 128 - 129 - ui.renderTemplate(w, "pages/error.html", data) 130 - }
+4 -1
pkg/hold/admin/handlers_crew_io.go
··· 67 67 68 68 enc := json.NewEncoder(w) 69 69 enc.SetIndent("", " ") 70 - enc.Encode(export) 70 + if err := enc.Encode(export); err != nil { 71 + slog.Error("Failed to encode crew export", "error", err) 72 + return 73 + } 71 74 72 75 session := getSessionFromContext(ctx) 73 76 slog.Info("Crew exported via admin panel",
-1
pkg/hold/config.go
··· 292 292 293 293 return storageCfg 294 294 } 295 -
+6
pkg/hold/config_test.go
··· 8 8 "time" 9 9 ) 10 10 11 + func init() { 12 + // Point metadata endpoint to a closed listener so it fails instantly instead of 13 + // waiting 2s for the real 169.254.169.254 to timeout on non-cloud machines. 14 + metadataEndpoint = "http://127.0.0.1:1" 15 + } 16 + 11 17 // setupEnv sets environment variables for testing and returns a cleanup function 12 18 func setupEnv(t *testing.T, vars map[string]string) func() { 13 19 // Save original env
+4 -1
pkg/hold/metadata.go
··· 13 13 Region string 14 14 } 15 15 16 + // metadataEndpoint is the cloud metadata service URL. Package-level var for test override. 17 + var metadataEndpoint = "http://169.254.169.254" 18 + 16 19 // DetectCloudMetadata queries the instance metadata service (169.254.169.254) 17 20 // Currently supports UpCloud. Others can be added via PR. 18 21 func DetectCloudMetadata(ctx context.Context) (*CloudMetadata, error) { ··· 32 35 33 36 // detectUpCloud queries UpCloud's metadata service 34 37 func detectUpCloud(ctx context.Context) (*CloudMetadata, error) { 35 - req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/metadata/v1.json", nil) 38 + req, err := http.NewRequestWithContext(ctx, "GET", metadataEndpoint+"/metadata/v1.json", nil) 36 39 if err != nil { 37 40 return nil, err 38 41 }
+1
pkg/hold/pds/captain_test.go
··· 40 40 t.Fatalf("Failed to initialize test repo: %v", err) 41 41 } 42 42 43 + t.Cleanup(func() { pds.Close() }) 43 44 return pds, ctx 44 45 } 45 46
+4 -8
pkg/hold/pds/delete_test.go
··· 150 150 151 151 func TestDeleteBlueskyPosts_NoPosts(t *testing.T) { 152 152 // Create a test PDS with records index 153 - pds, cleanup := setupTestPDSWithIndex(t, "did:plc:testowner") 154 - defer cleanup() 153 + pds := setupTestPDSWithIndex(t, "did:plc:testowner") 155 154 156 155 ctx := sharedCtx 157 156 ··· 168 167 169 168 func TestListBlueskyPostsForUser_NoPosts(t *testing.T) { 170 169 // Create a test PDS with records index 171 - pds, cleanup := setupTestPDSWithIndex(t, "did:plc:testowner") 172 - defer cleanup() 170 + pds := setupTestPDSWithIndex(t, "did:plc:testowner") 173 171 174 172 ctx := sharedCtx 175 173 ··· 186 184 187 185 func TestDeleteAndListBlueskyPosts_WithPosts(t *testing.T) { 188 186 // Create a test PDS with records index 189 - pds, cleanup := setupTestPDSWithIndex(t, "did:plc:testowner") 190 - defer cleanup() 187 + pds := setupTestPDSWithIndex(t, "did:plc:testowner") 191 188 192 189 ctx := sharedCtx 193 190 ··· 276 273 277 274 func TestDeleteUserData_IncludesPosts(t *testing.T) { 278 275 // Create a test PDS with records index 279 - pds, cleanup := setupTestPDSWithIndex(t, "did:plc:testowner") 280 - defer cleanup() 276 + pds := setupTestPDSWithIndex(t, "did:plc:testowner") 281 277 282 278 ctx := sharedCtx 283 279
+9 -18
pkg/hold/pds/layer_test.go
··· 287 287 288 288 // setupTestPDSWithIndex creates a PDS with file-based database (enables RecordsIndex) 289 289 // and bootstraps it with the given owner. Required for quota tests. 290 - func setupTestPDSWithIndex(t *testing.T, ownerDID string) (*HoldPDS, func()) { 290 + func setupTestPDSWithIndex(t *testing.T, ownerDID string) *HoldPDS { 291 291 t.Helper() 292 292 293 293 ctx := sharedCtx ··· 321 321 t.Fatalf("Failed to backfill records index: %v", err) 322 322 } 323 323 324 - cleanup := func() { 325 - pds.Close() 326 - } 327 - 328 - return pds, cleanup 324 + t.Cleanup(func() { pds.Close() }) 325 + return pds 329 326 } 330 327 331 328 // addCrewMemberWithTier adds a crew member with a specific tier ··· 349 346 350 347 func TestGetQuotaForUserWithTier_OwnerUnlimited(t *testing.T) { 351 348 ownerDID := "did:plc:owner123" 352 - pds, cleanup := setupTestPDSWithIndex(t, ownerDID) 353 - defer cleanup() 349 + pds := setupTestPDSWithIndex(t, ownerDID) 354 350 355 351 ctx := sharedCtx 356 352 ··· 423 419 func TestGetQuotaForUserWithTier_CrewWithDefaultTier(t *testing.T) { 424 420 ownerDID := "did:plc:owner456" 425 421 crewDID := "did:plc:crew123" 426 - pds, cleanup := setupTestPDSWithIndex(t, ownerDID) 427 - defer cleanup() 422 + pds := setupTestPDSWithIndex(t, ownerDID) 428 423 429 424 ctx := sharedCtx 430 425 ··· 498 493 func TestGetQuotaForUserWithTier_CrewWithExplicitTier(t *testing.T) { 499 494 ownerDID := "did:plc:owner789" 500 495 crewDID := "did:plc:bosuncrew456" 501 - pds, cleanup := setupTestPDSWithIndex(t, ownerDID) 502 - defer cleanup() 496 + pds := setupTestPDSWithIndex(t, ownerDID) 503 497 504 498 ctx := sharedCtx 505 499 ··· 566 560 func TestGetQuotaForUserWithTier_NoQuotaManager(t *testing.T) { 567 561 ownerDID := "did:plc:ownerabc" 568 562 crewDID := "did:plc:crewabc" 569 - pds, cleanup := setupTestPDSWithIndex(t, ownerDID) 570 - defer cleanup() 563 + pds := setupTestPDSWithIndex(t, ownerDID) 571 564 572 565 ctx := sharedCtx 573 566 ··· 608 601 func TestGetQuotaForUserWithTier_DisabledQuotas(t *testing.T) { 609 602 ownerDID := "did:plc:ownerdef" 610 603 crewDID := "did:plc:crewdef" 611 - pds, cleanup := setupTestPDSWithIndex(t, ownerDID) 612 - defer cleanup() 604 + pds := setupTestPDSWithIndex(t, ownerDID) 613 605 614 606 ctx := sharedCtx 615 607 ··· 655 647 func TestGetQuotaForUserWithTier_DeduplicatesBlobs(t *testing.T) { 656 648 ownerDID := "did:plc:ownerghi" 657 649 crewDID := "did:plc:crewghi" 658 - pds, cleanup := setupTestPDSWithIndex(t, ownerDID) 659 - defer cleanup() 650 + pds := setupTestPDSWithIndex(t, ownerDID) 660 651 661 652 ctx := sharedCtx 662 653
+6
pkg/hold/pds/server.go
··· 4 4 "context" 5 5 "database/sql" 6 6 "fmt" 7 + "io" 7 8 "log/slog" 8 9 "os" 9 10 "path/filepath" ··· 386 387 if p.recordsIndex != nil { 387 388 if err := p.recordsIndex.Close(); err != nil { 388 389 return fmt.Errorf("failed to close records index: %w", err) 390 + } 391 + } 392 + if closer, ok := p.carstore.(io.Closer); ok { 393 + if err := closer.Close(); err != nil { 394 + return fmt.Errorf("failed to close carstore: %w", err) 389 395 } 390 396 } 391 397 return nil
+1 -1
pkg/hold/pds/status_test.go
··· 288 288 // Run tests 289 289 code := m.Run() 290 290 291 - // Cleanup is automatic with t.TempDir() 291 + sharedPDS.Close() 292 292 os.Exit(code) 293 293 }