From 9eb69e2ea74f0e685c66b9fe6b9557bd7e6dfa93 Mon Sep 17 00:00:00 2001 From: Evan Jarrett Date: Fri, 24 Oct 2025 01:05:19 -0500 Subject: [PATCH] more linting fixes --- .golangci.yml | 26 ++++++++++++++++++++ pkg/appview/config.go | 5 ++++ pkg/appview/db/schema.go | 4 +++ pkg/appview/handlers/home.go | 3 +++ pkg/appview/holdhealth/checker.go | 3 +++ pkg/appview/holdhealth/checker_test.go | 3 +++ pkg/appview/jetstream/worker.go | 3 +++ pkg/appview/licenses/licenses.go | 4 +++ pkg/appview/middleware/auth.go | 4 +++ pkg/appview/readme/cache.go | 4 +++ pkg/appview/storage/proxy_blob_store.go | 2 +- pkg/appview/storage/proxy_blob_store_test.go | 2 +- pkg/appview/storage/routing_repository.go | 4 +++ pkg/atproto/endpoints.go | 6 ++--- pkg/atproto/profile.go | 2 +- pkg/auth/oauth/client.go | 4 +++ pkg/auth/session.go | 6 ++++- pkg/auth/token/cache.go | 4 +++ pkg/hold/config.go | 5 ++++ pkg/hold/oci/http_helpers.go | 3 +++ pkg/hold/oci/multipart.go | 2 +- pkg/hold/oci/xrpc.go | 6 ++--- pkg/hold/oci/xrpc_test.go | 12 ++++----- pkg/hold/pds/repomgr.go | 2 +- pkg/hold/pds/xrpc.go | 2 +- pkg/s3/types.go | 12 ++++++--- 26 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..5ad280e --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,26 @@ +# golangci-lint configuration for ATCR +# See: https://golangci-lint.run/usage/configuration/ +version: "2" +linters: + settings: + staticcheck: + checks: + - "all" + - "-SA1019" # Ignore deprecated package warnings for github.com/ipfs/go-ipfs-blockstore + # Cannot upgrade to github.com/ipfs/boxo/blockstore due to opentelemetry + # dependency conflicts with distribution/distribution + errcheck: + exclude-functions: + - (github.com/distribution/distribution/v3/registry/storage/driver.FileWriter).Cancel + - (github.com/distribution/distribution/v3.BlobWriter).Cancel + - (*database/sql.Tx).Rollback + - (*database/sql.Rows).Close + - (*net/http.Server).Shutdown + + exclusions: + presets: + - std-error-handling +formatters: + enable: + - gofmt + - goimports \ No newline at end of file diff --git a/pkg/appview/config.go b/pkg/appview/config.go index 8d0615e..83e01e8 100644 --- a/pkg/appview/config.go +++ b/pkg/appview/config.go @@ -1,3 +1,8 @@ +// Package appview implements the ATCR AppView component, which serves as the main +// OCI Distribution API server. It resolves identities (handle/DID to PDS endpoint), +// routes manifests to user's PDS, routes blobs to hold services, validates OAuth tokens, +// and issues registry JWTs. This package provides environment-based configuration, +// middleware registration, and HTTP server setup for the AppView service. package appview import ( diff --git a/pkg/appview/db/schema.go b/pkg/appview/db/schema.go index 0f01904..37aab14 100644 --- a/pkg/appview/db/schema.go +++ b/pkg/appview/db/schema.go @@ -1,3 +1,7 @@ +// Package db provides the database layer for the AppView web UI, including +// SQLite schema initialization, migrations, and query functions for OAuth +// sessions, device flows, repository metadata, stars, pull counts, and +// user profiles. package db import ( diff --git a/pkg/appview/handlers/home.go b/pkg/appview/handlers/home.go index 585837e..9394106 100644 --- a/pkg/appview/handlers/home.go +++ b/pkg/appview/handlers/home.go @@ -1,3 +1,6 @@ +// Package handlers provides HTTP handlers for the AppView web UI, including +// home page, repository browsing, search, user authentication, settings, +// device management, and API endpoints for the web interface. package handlers import ( diff --git a/pkg/appview/holdhealth/checker.go b/pkg/appview/holdhealth/checker.go index 81eae66..1e10382 100644 --- a/pkg/appview/holdhealth/checker.go +++ b/pkg/appview/holdhealth/checker.go @@ -1,3 +1,6 @@ +// Package holdhealth provides health checking for hold service endpoints. +// It periodically checks hold availability and caches health status with +// configurable TTL to avoid excessive health check requests. package holdhealth import ( diff --git a/pkg/appview/holdhealth/checker_test.go b/pkg/appview/holdhealth/checker_test.go index fe6f04e..78fbc5c 100644 --- a/pkg/appview/holdhealth/checker_test.go +++ b/pkg/appview/holdhealth/checker_test.go @@ -131,6 +131,7 @@ func TestGetStatus_CacheHit(t *testing.T) { status := checker.GetStatus(context.Background(), endpoint) if status == nil { t.Fatal("GetStatus returned nil") + return } if !status.Reachable { @@ -155,6 +156,7 @@ func TestGetStatus_CacheMiss(t *testing.T) { status := checker.GetStatus(context.Background(), server.URL) if status == nil { t.Fatal("GetStatus returned nil") + return } if !status.Reachable { @@ -191,6 +193,7 @@ func TestSetStatus(t *testing.T) { status := checker.GetCachedStatus(endpoint) if status == nil { t.Fatal("Status not found in cache") + return } if !status.Reachable { diff --git a/pkg/appview/jetstream/worker.go b/pkg/appview/jetstream/worker.go index 6cfe778..ff9f930 100644 --- a/pkg/appview/jetstream/worker.go +++ b/pkg/appview/jetstream/worker.go @@ -1,3 +1,6 @@ +// Package jetstream provides an ATProto Jetstream consumer for real-time updates. +// It connects to the Bluesky Jetstream WebSocket, processes repository events, +// indexes manifests and tags, and populates the AppView database for the web UI. package jetstream import ( diff --git a/pkg/appview/licenses/licenses.go b/pkg/appview/licenses/licenses.go index 59aacfd..aaa7d2a 100644 --- a/pkg/appview/licenses/licenses.go +++ b/pkg/appview/licenses/licenses.go @@ -1,3 +1,7 @@ +// Package licenses provides SPDX license validation and parsing for container +// image annotations. It embeds the official SPDX license list and provides +// functions to look up license identifiers, validate them, and parse +// multi-license strings with fuzzy matching support. package licenses //go:generate curl -fsSL -o spdx-licenses.json https://spdx.org/licenses/licenses.json diff --git a/pkg/appview/middleware/auth.go b/pkg/appview/middleware/auth.go index e840f1a..786624a 100644 --- a/pkg/appview/middleware/auth.go +++ b/pkg/appview/middleware/auth.go @@ -1,3 +1,7 @@ +// Package middleware provides HTTP middleware for AppView, including +// authentication (session-based for web UI, token-based for registry), +// identity resolution (handle/DID to PDS endpoint), and hold discovery +// for routing blobs to storage endpoints. package middleware import ( diff --git a/pkg/appview/readme/cache.go b/pkg/appview/readme/cache.go index bb12753..59b73c5 100644 --- a/pkg/appview/readme/cache.go +++ b/pkg/appview/readme/cache.go @@ -1,3 +1,7 @@ +// Package readme provides README fetching, rendering, and caching functionality +// for container repositories. It fetches markdown content from URLs, renders it +// to sanitized HTML using GitHub-flavored markdown, and caches the results in +// a database with configurable TTL. package readme import ( diff --git a/pkg/appview/storage/proxy_blob_store.go b/pkg/appview/storage/proxy_blob_store.go index a3bbb5e..048aa0f 100644 --- a/pkg/appview/storage/proxy_blob_store.go +++ b/pkg/appview/storage/proxy_blob_store.go @@ -451,7 +451,7 @@ func (p *ProxyBlobStore) getPartUploadInfo(ctx context.Context, digest, uploadID return nil, err } - url := fmt.Sprintf("%s%s", p.holdURL, atproto.HoldGetPartUploadUrl) + url := fmt.Sprintf("%s%s", p.holdURL, atproto.HoldGetPartUploadURL) req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(body)) if err != nil { return nil, err diff --git a/pkg/appview/storage/proxy_blob_store_test.go b/pkg/appview/storage/proxy_blob_store_test.go index 82cf401..c95f706 100644 --- a/pkg/appview/storage/proxy_blob_store_test.go +++ b/pkg/appview/storage/proxy_blob_store_test.go @@ -551,7 +551,7 @@ func TestMultipartEndpoints_CorrectURLs(t *testing.T) { _, err := store.getPartUploadInfo(context.Background(), "sha256:test", "upload-123", 1) return err }, - expectedPath: atproto.HoldGetPartUploadUrl, + expectedPath: atproto.HoldGetPartUploadURL, }, { name: "completeMultipartUpload", diff --git a/pkg/appview/storage/routing_repository.go b/pkg/appview/storage/routing_repository.go index 5b8a0c4..978b37f 100644 --- a/pkg/appview/storage/routing_repository.go +++ b/pkg/appview/storage/routing_repository.go @@ -1,3 +1,7 @@ +// Package storage implements the storage routing layer for AppView. +// It routes manifests to ATProto PDS (as io.atcr.manifest records) and +// blobs to hold services via XRPC, with hold DID caching for efficient pulls. +// All storage operations are proxied - AppView stores nothing locally. package storage import ( diff --git a/pkg/atproto/endpoints.go b/pkg/atproto/endpoints.go index 6184421..7c57327 100644 --- a/pkg/atproto/endpoints.go +++ b/pkg/atproto/endpoints.go @@ -1,4 +1,4 @@ -// Package xrpc provides constants for XRPC endpoint paths used throughout ATCR. +// Package atproto provides constants for XRPC endpoint paths used throughout ATCR. // // This package serves as a single source of truth for all XRPC endpoint URLs, // preventing typos and making refactoring easier. All endpoint paths follow the @@ -15,11 +15,11 @@ const ( // Response: {"uploadId": "..."} HoldInitiateUpload = "/xrpc/io.atcr.hold.initiateUpload" - // HoldGetPartUploadUrl gets a presigned URL or endpoint info for uploading a specific part. + // HoldGetPartUploadURL gets a presigned URL or endpoint info for uploading a specific part. // Method: POST // Request: {"uploadId": "...", "partNumber": 1} // Response: {"url": "...", "method": "PUT", "headers": {...}} - HoldGetPartUploadUrl = "/xrpc/io.atcr.hold.getPartUploadUrl" + HoldGetPartUploadURL = "/xrpc/io.atcr.hold.getPartUploadUrl" // HoldUploadPart handles direct buffered part uploads (alternative to presigned URLs). // Method: PUT diff --git a/pkg/atproto/profile.go b/pkg/atproto/profile.go index cfa18b7..b8ef8d4 100644 --- a/pkg/atproto/profile.go +++ b/pkg/atproto/profile.go @@ -9,7 +9,7 @@ import ( "time" ) -// Profile record key is always "self" per lexicon +// ProfileRKey is always "self" per lexicon const ProfileRKey = "self" // Global map to track in-flight profile migrations (DID -> true) diff --git a/pkg/auth/oauth/client.go b/pkg/auth/oauth/client.go index 1289329..9f1c774 100644 --- a/pkg/auth/oauth/client.go +++ b/pkg/auth/oauth/client.go @@ -1,3 +1,7 @@ +// Package oauth provides OAuth client and flow implementation for ATCR. +// It wraps indigo's OAuth library with ATCR-specific configuration, +// including default scopes, client metadata, token refreshing, and +// interactive browser-based authentication flows. package oauth import ( diff --git a/pkg/auth/session.go b/pkg/auth/session.go index 9365165..2f6fb81 100644 --- a/pkg/auth/session.go +++ b/pkg/auth/session.go @@ -1,7 +1,9 @@ +// Package auth provides authentication and authorization for ATCR, including +// ATProto session validation, hold authorization (captain/crew membership), +// scope parsing, and token caching for OAuth and service tokens. package auth import ( - "atcr.io/pkg/atproto" "bytes" "context" "crypto/sha256" @@ -13,6 +15,8 @@ import ( "sync" "time" + "atcr.io/pkg/atproto" + "github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/atproto/syntax" ) diff --git a/pkg/auth/token/cache.go b/pkg/auth/token/cache.go index 3e75bfe..7461c16 100644 --- a/pkg/auth/token/cache.go +++ b/pkg/auth/token/cache.go @@ -1,3 +1,7 @@ +// Package token provides service token caching and management for AppView. +// Service tokens are JWTs issued by a user's PDS to authorize AppView to +// act on their behalf when communicating with hold services. Tokens are +// cached with automatic expiry parsing and 10-second safety margins. package token import ( diff --git a/pkg/hold/config.go b/pkg/hold/config.go index 95cd58c..e993379 100644 --- a/pkg/hold/config.go +++ b/pkg/hold/config.go @@ -1,3 +1,8 @@ +// Package hold implements the ATCR hold service, which provides BYOS +// (Bring Your Own Storage) functionality. It includes an embedded PDS for +// storing captain and crew records, generates presigned URLs for blob storage, +// and handles authorization based on crew membership. Configuration is loaded +// entirely from environment variables. package hold import ( diff --git a/pkg/hold/oci/http_helpers.go b/pkg/hold/oci/http_helpers.go index efb54e6..637bfd4 100644 --- a/pkg/hold/oci/http_helpers.go +++ b/pkg/hold/oci/http_helpers.go @@ -1,3 +1,6 @@ +// Package oci provides HTTP helpers for OCI registry endpoints in the hold service. +// It includes utilities for JSON encoding/decoding of request/response bodies +// and standardized error responses for XRPC endpoints. package oci import ( diff --git a/pkg/hold/oci/multipart.go b/pkg/hold/oci/multipart.go index ada56e1..fd49160 100644 --- a/pkg/hold/oci/multipart.go +++ b/pkg/hold/oci/multipart.go @@ -26,7 +26,7 @@ const ( Buffered ) -// CompletedPart represents an uploaded part with its ETag +// PartInfo represents an uploaded part with its ETag type PartInfo struct { PartNumber int `json:"part_number"` ETag string `json:"etag"` diff --git a/pkg/hold/oci/xrpc.go b/pkg/hold/oci/xrpc.go index 021a7e9..daaba9c 100644 --- a/pkg/hold/oci/xrpc.go +++ b/pkg/hold/oci/xrpc.go @@ -44,7 +44,7 @@ func (h *XRPCHandler) RegisterHandlers(r chi.Router) { r.Use(h.requireBlobWriteAccess) r.Post(atproto.HoldInitiateUpload, h.HandleInitiateUpload) - r.Post(atproto.HoldGetPartUploadUrl, h.HandleGetPartUploadUrl) + r.Post(atproto.HoldGetPartUploadURL, h.HandleGetPartUploadURL) r.Put(atproto.HoldUploadPart, h.HandleUploadPart) r.Post(atproto.HoldCompleteUpload, h.HandleCompleteUpload) r.Post(atproto.HoldAbortUpload, h.HandleAbortUpload) @@ -80,9 +80,9 @@ func (h *XRPCHandler) HandleInitiateUpload(w http.ResponseWriter, r *http.Reques }) } -// HandleGetPartUploadUrl returns a presigned URL or endpoint info for uploading a part +// HandleGetPartUploadURL returns a presigned URL or endpoint info for uploading a part // Replaces the old "action: part" pattern -func (h *XRPCHandler) HandleGetPartUploadUrl(w http.ResponseWriter, r *http.Request) { +func (h *XRPCHandler) HandleGetPartUploadURL(w http.ResponseWriter, r *http.Request) { var req struct { UploadID string `json:"uploadId"` PartNumber int `json:"partNumber"` diff --git a/pkg/hold/oci/xrpc_test.go b/pkg/hold/oci/xrpc_test.go index d675526..62fe078 100644 --- a/pkg/hold/oci/xrpc_test.go +++ b/pkg/hold/oci/xrpc_test.go @@ -218,14 +218,14 @@ func TestHandleGetPartUploadUrl_Buffered(t *testing.T) { uploadID := initResp["uploadId"].(string) // Now get part upload URL - req := makeJSONRequest("POST", atproto.HoldGetPartUploadUrl, map[string]any{ + req := makeJSONRequest("POST", atproto.HoldGetPartUploadURL, map[string]any{ "uploadId": uploadID, "partNumber": 1, }) addMockAuth(req) w := httptest.NewRecorder() - handler.HandleGetPartUploadUrl(w, req) + handler.HandleGetPartUploadURL(w, req) if w.Code != http.StatusOK { t.Errorf("Expected status 200, got %d: %s", w.Code, w.Body.String()) @@ -246,14 +246,14 @@ func TestHandleGetPartUploadUrl_Buffered(t *testing.T) { func TestHandleGetPartUploadUrl_InvalidSession(t *testing.T) { handler, _ := setupTestOCIHandler(t) - req := makeJSONRequest("POST", atproto.HoldGetPartUploadUrl, map[string]any{ + req := makeJSONRequest("POST", atproto.HoldGetPartUploadURL, map[string]any{ "uploadId": "invalid-upload-id", "partNumber": 1, }) addMockAuth(req) w := httptest.NewRecorder() - handler.HandleGetPartUploadUrl(w, req) + handler.HandleGetPartUploadURL(w, req) if w.Code != http.StatusInternalServerError { t.Errorf("Expected status 500, got %d", w.Code) @@ -274,11 +274,11 @@ func TestHandleGetPartUploadUrl_MissingParams(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - req := makeJSONRequest("POST", atproto.HoldGetPartUploadUrl, tt.body) + req := makeJSONRequest("POST", atproto.HoldGetPartUploadURL, tt.body) addMockAuth(req) w := httptest.NewRecorder() - handler.HandleGetPartUploadUrl(w, req) + handler.HandleGetPartUploadURL(w, req) if w.Code != http.StatusBadRequest { t.Errorf("Expected status 400, got %d", w.Code) diff --git a/pkg/hold/pds/repomgr.go b/pkg/hold/pds/repomgr.go index 85d1260..77e5a60 100644 --- a/pkg/hold/pds/repomgr.go +++ b/pkg/hold/pds/repomgr.go @@ -1250,7 +1250,7 @@ func (rm *RepoManager) TakeDownRepo(ctx context.Context, uid models.Uid) error { return rm.cs.WipeUserData(ctx, uid) } -// technically identical to TakeDownRepo, for now +// ResetRepo is technically identical to TakeDownRepo, for now func (rm *RepoManager) ResetRepo(ctx context.Context, uid models.Uid) error { unlock := rm.lockUser(ctx, uid) defer unlock() diff --git a/pkg/hold/pds/xrpc.go b/pkg/hold/pds/xrpc.go index 1dc314c..40d79aa 100644 --- a/pkg/hold/pds/xrpc.go +++ b/pkg/hold/pds/xrpc.go @@ -1223,7 +1223,7 @@ func (h *XRPCHandler) HandleRequestCrew(w http.ResponseWriter, r *http.Request) json.NewEncoder(w).Encode(response) } -// getPresignedURL generates a presigned URL for GET, HEAD, or PUT operations +// GetPresignedURL generates a presigned URL for GET, HEAD, or PUT operations // Distinguishes between ATProto blobs (per-DID) and OCI blobs (content-addressed) func (h *XRPCHandler) GetPresignedURL(ctx context.Context, operation string, digest string, did string) (string, error) { var path string diff --git a/pkg/s3/types.go b/pkg/s3/types.go index a7a44b7..9c8d89b 100644 --- a/pkg/s3/types.go +++ b/pkg/s3/types.go @@ -1,13 +1,17 @@ +// Package s3 provides S3 client initialization and presigned URL generation +// for hold services. It supports S3, Storj, and Minio storage backends, +// with fallback to buffered proxy mode when presigned URLs are unavailable. package s3 import ( "fmt" + "log" + "strings" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" - "log" - "strings" ) type S3Service struct { @@ -16,7 +20,7 @@ type S3Service struct { PathPrefix string // S3 path prefix (if any) } -// initializes the S3 client for presigned URL generation +// NewS3Service initializes the S3 client for presigned URL generation // Returns nil error if S3 client is successfully initialized // Returns error if storage is not S3 or if initialization fails (service will fall back to proxy mode) func NewS3Service(params map[string]any, disablePresigned bool, storageType string) (*S3Service, error) { @@ -85,7 +89,7 @@ func NewS3Service(params map[string]any, disablePresigned bool, storageType stri }, nil } -// blobPath converts a digest (e.g., "sha256:abc123...") or temp path to a storage path +// BlobPath converts a digest (e.g., "sha256:abc123...") or temp path to a storage path // Distribution stores blobs as: /docker/registry/v2/blobs/{algorithm}/{xx}/{hash}/data // where xx is the first 2 characters of the hash for directory sharding // NOTE: Path must start with / for filesystem driver