docs: complete placeholder doc comments across the codebase

Replace every `// <Identifier> ...` placeholder doc comment with a real
description of the declared symbol. 276 comments in 71 files were rewritten:
149 top-level placeholders first, then a follow-up scan caught another 127
indented ones (interface methods and const blocks) that a column-anchored
match had missed.

Comments now open with the declared identifier and record the actual
contract - behaviour, side effects, error/panic conditions, units, HTTP
endpoints, lock keys and cache prefixes - instead of restating the
signature. Three placeholders carried a stale identifier and were corrected
to the declared symbol: ConfigurationDatabasePostgresql, GetImageRef and
Initialize.

No functional change: every modified line is a comment.

Verification:
- grep '^\s*//\s+\S+\s+\.\.\.\s*$' over all *.go returns no matches
- gofmt -l over the changed files prints nothing
- CGO_ENABLED=1 go build -tags "netgo,timetzdata,exclude_graphdriver_btrfs,containers_image_openpgp" ./... exits 0
- git diff HEAD -U0 filtered to non-comment changed lines is empty
This commit is contained in:
Tosone committed 2026-09-14 14:58:06 +08:00
1 parent a7c816494a
commit f677ad3f5f
71 files changed
+295 -239

No files matched your search

+2 -1
View File
@@ -70,7 +70,8 @@ which can be deployed on any cloud platform or on-premises.`,
return cmd
}
// Execute ...
// Execute runs the root command and exits the process with status 1 if it
// returns an error.
func Execute() {
err := NewRootCmd().Execute()
if err != nil {
+4 -1
View File
@@ -32,7 +32,10 @@ import (
var digCon = dig.New()
var digConOnce = sync.Once{}
// NewDigContainer ...
// NewDigContainer returns the process-wide dig container, registering the
// config, redis, password, token, locker, counter, work queue and storage
// providers on first call. Registration happens once; the first error from a
// provider is returned and the partially populated container is reused.
func NewDigContainer() (*dig.Container, error) {
var err error
digConOnce.Do(func() {
+5 -1
View File
@@ -70,7 +70,11 @@ type GinServerParams struct {
RedisClientFactory dalredis.ClientFactory `optional:"true"`
}
// NewGinServer ...
// NewGinServer builds the gin engine in release mode with the full middleware
// chain (tracing, CORS, ETag, metrics, body limit, health probes, authn, authz
// and optional audit) and returns it ready to serve. The login rate limiter and
// pprof are enabled only when configured; login throttling is skipped with a
// warning if its limiter cannot be created.
func NewGinServer(params GinServerParams) (*gin.Engine, error) {
gin.SetMode(gin.ReleaseMode)
e := gin.New()
+2 -1
View File
@@ -40,7 +40,8 @@ import (
mcpserver "github.com/go-sigma/sigma/pkg/server/mcp"
)
// ServerConfig ...
// ServerConfig selects which optional subsystems Serve initializes; each
// Without* field disables the corresponding component.
type ServerConfig struct {
WithoutDistribution bool
WithoutWorker bool
+4 -4
View File
@@ -164,13 +164,13 @@ func builderLockKey(builderID string) string {
return fmt.Sprintf("%s:%s", consts.LockerCronjobBuilder, builderID)
}
// buildRunnerOption ...
// buildRunnerOption carries the tag and source branch to apply to the runner.
type buildRunnerOption struct {
Tag string
ScmBranch *string
}
// buildRunner ...
// buildRunner creates a pending BuilderRunner for builder with a fresh UUID and the tag/branch from option.
// nolint: unparam
func buildRunner(builder *models.Builder, option buildRunnerOption) (*models.BuilderRunner, error) {
runner := &models.BuilderRunner{
@@ -184,14 +184,14 @@ func buildRunner(builder *models.Builder, option buildRunnerOption) (*models.Bui
return runner, nil
}
// buildTagOption ...
// buildTagOption supplies the template variables (branch, tag, ref) used to render a build tag.
type buildTagOption struct {
ScmBranch string
ScmTag string
ScmRef string
}
// buildTag ...
// buildTag renders tmpl as a sprig-augmented text/template over option and returns the resulting tag, wrapping parse or execute failures.
func buildTag(tmpl string, option buildTagOption) (string, error) {
t, err := template.New("tag").Funcs(sprig.FuncMap()).Parse(tmpl)
if err != nil {
+3 -3
View File
@@ -29,13 +29,13 @@ const (
MaxJob = 100
)
// Starter ...
// Starter holds the cronjob registration functions run in order by Initialize.
var Starter []func(*dig.Container) error
// Stopper ...
// Stopper holds the cronjob teardown functions run by DeInitialize.
var Stopper []func()
// Initialize ...
// Initialize runs every registered cronjob starter, rolling back via DeInitialize and returning the error if one fails.
func Initialize(digCon *dig.Container) error {
for _, start := range Starter {
if err := start(digCon); err != nil {
+1 -1
View File
@@ -17,7 +17,7 @@ type Factory interface {
// Daemons is the registry for daemon factories
var Daemons = make(registry.Factories[string, Factory])
// Initialize ...
// Initialize initializes the validators, then every registered daemon factory, naming the failing factory in the returned error.
func Initialize(digCon *dig.Container) error {
err := validators.Initialize()
if err != nil {
+2 -2
View File
@@ -104,9 +104,9 @@ type decoratorWebhook struct {
WebhookObj any
}
// Runner ...
// Runner runs a single GC task; each GC kind (blob, repository, tag) provides an implementation selected by initGc.
type Runner interface {
// Run ...
// Run executes the GC task identified by runnerID, reporting progress and the final status through runner.
Run(ctx context.Context, runner *runnerContext, runnerID string) error
}
+1 -1
View File
@@ -55,7 +55,7 @@ type gcBlob struct {
locker lock.Locker
}
// Run ...
// Run deletes blobs that are unreferenced and last pulled before the rule's retention window, batch by batch through the storage driver, recording a DaemonGcRecord per blob and finishing the runner with the success/failure counts.
func (g *gcBlob) Run(ctx context.Context, runner *runnerContext, runnerID string) error {
if err := runner.start(); err != nil {
return fmt.Errorf("start gc blob runner failed: %v", err)
+1 -1
View File
@@ -50,7 +50,7 @@ type gcRepository struct {
locker lock.Locker
}
// Run ...
// Run deletes repositories left empty past the rule's retention period, either scoped to the rule's namespace or across all namespaces in cursor batches, recording a DaemonGcRecord for each deletion.
func (g *gcRepository) Run(ctx context.Context, runner *runnerContext, runnerID string) error {
if err := runner.start(); err != nil {
return fmt.Errorf("start gc repository runner failed: %v", err)
+1 -1
View File
@@ -53,7 +53,7 @@ type gcTag struct {
locker lock.Locker
}
// Run ...
// Run deletes tags matching the rule's retention type (age or count) and optional name pattern, scoped to the rule's namespace or all namespaces, and fails early on an unsupported retention type or invalid pattern.
func (g *gcTag) Run(ctx context.Context, runner *runnerContext, runnerID string) error {
if err := runner.start(); err != nil {
return fmt.Errorf("start gc tag runner failed: %v", err)
+2 -2
View File
@@ -35,13 +35,13 @@ import (
"github.com/go-sigma/sigma/pkg/utils/uuid"
)
// reportDistro ...
// reportDistro is the OS distribution identity extracted from a syft report.
type reportDistro struct {
Name string `json:"name"`
Version string `json:"version"`
}
// reportSbom ...
// reportSbom mirrors the summary fields (distro, OS, architecture) that sigma persists from a syft JSON document.
type reportSbom struct {
Distro reportDistro `json:"distro"`
Os string `json:"os"`
@@ -66,7 +66,7 @@ type Daemon struct {
StorageDriver storage.StorageDriver
}
// reportVulnerability ...
// reportVulnerability mirrors the per-severity match counts sigma persists from a grype JSON document.
type reportVulnerability struct {
Critical int64 `json:"critical"`
High int64 `json:"high"`
+2 -1
View File
@@ -20,7 +20,8 @@ type checker func(cfg Configuration) error
var checkers []checker
// CheckMiddleware ...
// CheckMiddleware runs every registered configuration checker against the singleton configuration and returns the first error.
// It is invoked during startup by the server and worker bootstrap (cmd/tools/middleware_checker.go).
func CheckMiddleware() error {
for _, checker := range checkers {
err := checker(ptr.To(configuration))
+40 -40
View File
@@ -54,7 +54,7 @@ func GetConfig() *Configuration {
return configuration
}
// Configuration ...
// Configuration is the root configuration object; it aggregates every YAML section and is exposed as a singleton by GetConfig.
type Configuration struct {
Log ConfigurationLog `yaml:"log"`
Database ConfigurationDatabase `yaml:"database" mapstructure:"DATABASE"`
@@ -192,23 +192,23 @@ type ConfigurationBuilderK8s struct {
type ConfigurationBuilderDocker struct {
}
// ConfigurationLog ...
// ConfigurationLog sets the application log level and the separate level used for the registry proxy.
type ConfigurationLog struct {
Level enums.LogLevel `yaml:"level"`
ProxyLevel enums.LogLevel `yaml:"proxyLevel"`
}
// ConfigurationDatabaseSqlite3 ...
// ConfigurationDatabaseSqlite3 configures the embedded SQLite3 backend by its database file path.
type ConfigurationDatabaseSqlite3 struct {
Path string `yaml:"path"`
}
// ConfigurationDatabaseTurso ...
// ConfigurationDatabaseTurso configures the Turso/libSQL backend via its DSN.
type ConfigurationDatabaseTurso struct {
DSN string `yaml:"dsn"`
}
// ConfigurationDatabaseMysql ...
// ConfigurationDatabaseMysql configures connection parameters for the MySQL backend.
type ConfigurationDatabaseMysql struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
@@ -217,7 +217,7 @@ type ConfigurationDatabaseMysql struct {
Database string `yaml:"database"`
}
// ConfigurationDatabase ...
// ConfigurationDatabasePostgresql configures connection parameters for the PostgreSQL backend, including the SSL mode.
type ConfigurationDatabasePostgresql struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
@@ -227,7 +227,7 @@ type ConfigurationDatabasePostgresql struct {
SslMode string `yaml:"sslMode"`
}
// ConfigurationDatabase ...
// ConfigurationDatabase selects the database backend and configures the shared connection pool and per-backend settings.
type ConfigurationDatabase struct {
Type enums.Database `yaml:"type" mapstructure:"TYPE"`
MaxOpenConns int `yaml:"maxOpenConns"`
@@ -256,7 +256,7 @@ func (c *ConfigurationDatabase) WithDefaults() {
}
}
// ConfigurationRedis ...
// ConfigurationRedis configures the shared Redis client used by the cache, locker and work queue.
//
// 启用条件:URL 或 Addrs 任一非空,即视为启用 Redis;两者皆空则视为未启用。
type ConfigurationRedis struct {
@@ -277,7 +277,7 @@ func (r ConfigurationRedis) Enabled() bool {
return r.URL != "" || len(r.Addrs) > 0 || r.MasterName != ""
}
// ConfigurationCacheRedis ...
// ConfigurationCacheRedis holds the TTL applied when the Redis cache backend is selected.
type ConfigurationCacheRedis struct {
Ttl time.Duration `yaml:"ttl"`
}
@@ -294,12 +294,12 @@ func (c ConfigurationCachePrewarm) IsEnabled() bool {
return c.Enabled == nil || *c.Enabled
}
// ConfigurationCacheInmemory ...
// ConfigurationCacheInmemory configures the in-memory cache backend, where size is the maximum number of cached entries.
type ConfigurationCacheInmemory struct {
Size int `yaml:"size"`
}
// ConfigurationCache ...
// ConfigurationCache selects the cache backend (redis or inmemory) and configures the key prefix, TTLs and prewarming.
type ConfigurationCache struct {
Type enums.CacherType `yaml:"type"`
Prefix string `yaml:"prefix"`
@@ -361,7 +361,7 @@ func (c *ConfigurationWorkQueueInmemmory) WithDefaults() {
}
}
// ConfigurationWorkQueue ...
// ConfigurationWorkQueue selects the work queue backend (redis, database or inmemory) and its per-backend settings.
type ConfigurationWorkQueue struct {
Type enums.WorkQueueType `yaml:"type"`
Redis ConfigurationWorkQueueRedis `yaml:"redis"`
@@ -370,10 +370,10 @@ type ConfigurationWorkQueue struct {
Inmemory ConfigurationWorkQueueInmemmory `yaml:"inmemory"`
}
// ConfigurationLockerRedis ...
// ConfigurationLockerRedis is the option-less configuration for the Redis locker backend.
type ConfigurationLockerRedis struct{}
// ConfigurationLocker ...
// ConfigurationLocker selects the distributed locker backend (redis or inmemory) and the shared key prefix.
type ConfigurationLocker struct {
Type enums.LockerType `yaml:"type"`
Redis ConfigurationLockerRedis `yaml:"redis"`
@@ -387,7 +387,7 @@ func (c *ConfigurationLocker) WithDefaults() {
}
}
// ConfigurationNamespace ...
// ConfigurationNamespace controls whether namespaces are created automatically on push and the visibility assigned to them.
type ConfigurationNamespace struct {
AutoCreate bool `yaml:"autoCreate"`
Visibility enums.Visibility `yaml:"visibility"`
@@ -400,7 +400,7 @@ func (c *ConfigurationNamespace) WithDefaults() {
}
}
// ConfigurationHttpTLS ...
// ConfigurationHttpTLS enables TLS termination for the HTTP server and points at the certificate and private key files.
type ConfigurationHttpTLS struct {
Enabled bool `yaml:"enabled"`
Certificate string `yaml:"certificate"`
@@ -499,7 +499,7 @@ func (c *ConfigurationHTTPTimeout) WithDefaults() {
}
}
// ConfigurationHTTP ...
// ConfigurationHTTP configures the HTTP server endpoints, TLS, request body-size limits and timeouts.
type ConfigurationHTTP struct {
Endpoint string `yaml:"endpoint"`
InternalEndpoint string `yaml:"internalEndpoint"`
@@ -535,12 +535,12 @@ func durationOrZero(v *time.Duration) time.Duration {
return *v
}
// ConfigurationStorageFilesystem ...
// ConfigurationStorageFilesystem configures the local filesystem storage backend by its root path.
type ConfigurationStorageFilesystem struct {
Path string `yaml:"path"`
}
// ConfigurationStorageS3 ...
// ConfigurationStorageS3 configures the S3-compatible object storage backend, including credentials, endpoint and path-style access.
type ConfigurationStorageS3 struct {
Ak string `yaml:"ak"`
Sk string `yaml:"sk"`
@@ -552,7 +552,7 @@ type ConfigurationStorageS3 struct {
ChecksumValidation string `yaml:"checksumValidation"`
}
// ConfigurationStorageCos ...
// ConfigurationStorageCos configures the Tencent Cloud COS storage backend.
type ConfigurationStorageCos struct {
Ak string `yaml:"ak"`
Sk string `yaml:"sk"`
@@ -560,7 +560,7 @@ type ConfigurationStorageCos struct {
ForcePathStyle bool `yaml:"forcePathStyle"`
}
// ConfigurationStorageQiniu ...
// ConfigurationStorageQiniu configures the Qiniu object storage backend.
type ConfigurationStorageQiniu struct {
Ak string `yaml:"ak"`
Sk string `yaml:"sk"`
@@ -569,7 +569,7 @@ type ConfigurationStorageQiniu struct {
UseHTTPS bool `yaml:"useHttps"`
}
// ConfigurationStorageOss ...
// ConfigurationStorageOss configures the Alibaba Cloud OSS storage backend.
type ConfigurationStorageOss struct {
Ak string `yaml:"ak"`
Sk string `yaml:"sk"`
@@ -578,7 +578,7 @@ type ConfigurationStorageOss struct {
ForcePathStyle bool `yaml:"forcePathStyle"`
}
// ConfigurationStorage ...
// ConfigurationStorage selects the blob storage backend (filesystem, s3, cos, oss or qiniu) and shared options such as redirects.
type ConfigurationStorage struct {
RootDirectory string `yaml:"rootDirectory"`
Redirect bool `yaml:"redirect"`
@@ -589,7 +589,7 @@ type ConfigurationStorage struct {
Oss ConfigurationStorageOss `yaml:"oss"`
}
// ConfigurationProxy ...
// ConfigurationProxy configures the upstream registry proxy used to pull and cache images from a remote registry.
type ConfigurationProxy struct {
Enabled bool `yaml:"enabled"`
Endpoint string `yaml:"endpoint"`
@@ -599,7 +599,7 @@ type ConfigurationProxy struct {
Token string `yaml:"token"`
}
// ConfigurationDaemonGc ...
// ConfigurationDaemonGc configures the garbage collection daemon, including retention, schedule, batch sizes and lock behaviour.
type ConfigurationDaemonGc struct {
Retention time.Duration `yaml:"retention"`
Cron string `yaml:"cron"`
@@ -629,13 +629,13 @@ func (c *ConfigurationDaemonGc) WithDefaults() {
}
}
// ConfigurationDaemonDocker ...
// ConfigurationDaemonDocker configures the docker builder backend, pointing at the daemon socket and container network.
type ConfigurationDaemonDocker struct {
Sock *string `yaml:"sock"`
Network string `yaml:"network"`
}
// ConfigurationDaemonKubernetes ...
// ConfigurationDaemonKubernetes configures the kubernetes builder backend by kubeconfig and target namespace.
type ConfigurationDaemonKubernetes struct {
Kubeconfig *string `yaml:"kubeconfig"`
Namespace string `yaml:"namespace"`
@@ -648,7 +648,7 @@ func (c *ConfigurationDaemonKubernetes) WithDefaults() {
}
}
// ConfigurationDaemonPodman ...
// ConfigurationDaemonPodman configures the podman builder backend by its service URI.
type ConfigurationDaemonPodman struct {
URI string `yaml:"uri"`
}
@@ -660,7 +660,7 @@ func (c *ConfigurationDaemonPodman) WithDefaults() {
}
}
// ConfigurationDaemonBuilder ...
// ConfigurationDaemonBuilder selects the image builder backend (docker, kubernetes or podman) and holds its shared options.
type ConfigurationDaemonBuilder struct {
Enabled bool `yaml:"enabled"`
Type enums.BuilderType `yaml:"type"`
@@ -719,7 +719,7 @@ func (c *ConfigurationDaemonSizeReconcile) WithDefaults() {
}
}
// ConfigurationDaemon ...
// ConfigurationDaemon groups the background daemons: builder, garbage collection, vulnerability scanning and size reconciliation.
type ConfigurationDaemon struct {
Builder ConfigurationDaemonBuilder `yaml:"builder"`
GC ConfigurationDaemonGc `yaml:"gc"`
@@ -736,25 +736,25 @@ func (c *ConfigurationDaemon) WithDefaults() {
c.SizeReconcile.WithDefaults()
}
// ConfigurationAuthInternalUser ...
// ConfigurationAuthInternalUser configures the built-in internal user account used by system components.
type ConfigurationAuthInternalUser struct {
Username string `yaml:"username"`
}
// ConfigurationAuthAdmin ...
// ConfigurationAuthAdmin configures the initial administrator account created on first startup.
type ConfigurationAuthAdmin struct {
Username string `yaml:"username"`
Password string `yaml:"password"`
Email string `yaml:"email"`
}
// ConfigurationAuthToken ...
// ConfigurationAuthToken configures the realm and service name advertised by the Docker token authentication flow.
type ConfigurationAuthToken struct {
Realm string `yaml:"realm"`
Service string `yaml:"service"`
}
// ConfigurationAuthJwt ...
// ConfigurationAuthJwt configures the JWT signing key and the access and refresh token lifetimes.
type ConfigurationAuthJwt struct {
Ttl time.Duration `yaml:"ttl"`
RefreshTTL time.Duration `yaml:"refreshTTL"`
@@ -771,40 +771,40 @@ func (c *ConfigurationAuthJwt) WithDefaults() {
}
}
// ConfigurationAuthOauth2Github ...
// ConfigurationAuthOauth2Github configures GitHub as an OAuth2 login provider.
type ConfigurationAuthOauth2Github struct {
Enabled bool `yaml:"enabled"`
ClientID string `yaml:"clientId"`
ClientSecret string `yaml:"clientSecret"`
}
// ConfigurationAuthOauth2Gitlab ...
// ConfigurationAuthOauth2Gitlab configures GitLab as an OAuth2 login provider.
type ConfigurationAuthOauth2Gitlab struct {
Enabled bool `yaml:"enabled"`
ClientID string `yaml:"clientId"`
ClientSecret string `yaml:"clientSecret"`
}
// ConfigurationAuthOauth2Gitea ...
// ConfigurationAuthOauth2Gitea configures Gitea as an OAuth2 login provider.
type ConfigurationAuthOauth2Gitea struct {
Enabled bool `yaml:"enabled"`
ClientID string `yaml:"clientId"`
ClientSecret string `yaml:"clientSecret"`
}
// ConfigurationAuthOauth2 ...
// ConfigurationAuthOauth2 groups the supported external OAuth2 login providers.
type ConfigurationAuthOauth2 struct {
Github ConfigurationAuthOauth2Github `yaml:"github"`
Gitlab ConfigurationAuthOauth2Gitlab `yaml:"gitlab"`
Gitea ConfigurationAuthOauth2Gitea `yaml:"gitea"`
}
// ConfigurationAuthAnonymous ...
// ConfigurationAuthAnonymous controls whether unauthenticated access to public resources is allowed.
type ConfigurationAuthAnonymous struct {
Enabled bool `yaml:"enabled"`
}
// ConfigurationAuth ...
// ConfigurationAuth configures authentication: the admin account, token service, JWT, OAuth2 providers and anonymous access.
type ConfigurationAuth struct {
Anonymous ConfigurationAuthAnonymous `yaml:"anonymous"`
Admin ConfigurationAuthAdmin `yaml:"admin"`
+15 -15
View File
@@ -64,17 +64,17 @@ const (
ContextUser = "ctx-user"
// HotNamespace top hot namespaces
HotNamespace = 3
// WebhookSecretHeader ...
// WebhookSecretHeader is the HTTP header carrying the hex-encoded HMAC-SHA256 signature of a webhook payload.
WebhookSecretHeader = "X-Sigma-Signature-256" // nolint: gosec
// InsertBatchSize ...
// InsertBatchSize is the number of records written per statement when inserting rows in bulk.
InsertBatchSize = 10
// MaxNamespaceMember ...
// MaxNamespaceMember is the maximum number of members a single namespace may have.
MaxNamespaceMember = 10
// MaxWebhooks ...
// MaxWebhooks is the maximum number of webhooks a single namespace may have.
MaxWebhooks = 5
// ObsPresignMaxTtl
ObsPresignMaxTtl = time.Minute * 30
// PprofPath ...
// PprofPath is the URL path where the pprof profiling handlers are mounted when debug logging is enabled.
PprofPath = "/__debug/pprof"
)
@@ -103,9 +103,9 @@ var (
)
const (
// CacherBlob ...
// CacherBlob is the cache prefix under which blob metadata entries are stored.
CacherBlob = "blob"
// CacherManifest ...
// CacherManifest is the cache prefix under which manifest entries are stored.
CacherManifest = "manifest"
)
@@ -124,17 +124,17 @@ const (
)
const (
// LockerMigration ...
// LockerMigration is the distributed lock key serializing database migration runs.
LockerMigration = "locker-migration"
// LockerCronjobBuilder ...
// LockerCronjobBuilder is the distributed lock key prefix serializing builder cronjob runs; a builder ID is appended to it.
LockerCronjobBuilder = "locker-cronjob-builder"
// LockerAnalyticsFlush ...
// LockerAnalyticsFlush is the distributed lock key prefix serializing analytics flush runs; the target hour is appended to it.
LockerAnalyticsFlush = "locker-analytics-flush"
// LockerCronjobAudit ...
// LockerCronjobAudit is the distributed lock key serializing audit log cleanup runs.
LockerCronjobAudit = "locker-cronjob-audit"
// LockerCronjobSize ...
// LockerCronjobSize is the distributed lock key serializing namespace size reconciliation runs.
LockerCronjobSize = "locker-cronjob-size"
// LockerVulnerabilityScan ...
// LockerVulnerabilityScan is the distributed lock key serializing vulnerability scan runs.
LockerVulnerabilityScan = "locker-vulnerability-scan"
)
@@ -144,8 +144,8 @@ var (
)
const (
// LockerRetryDelay ...
// LockerRetryDelay is the delay between successive attempts to acquire a distributed lock.
LockerRetryDelay = time.Second * 1
// LockerRetryMaxTimes ...
// LockerRetryMaxTimes is the maximum number of attempts made to acquire a distributed lock before giving up.
LockerRetryMaxTimes = 6
)
+2 -2
View File
@@ -17,8 +17,8 @@ package consts
import "regexp"
var (
// RegexUsername ...
// RegexUsername matches usernames made up solely of ASCII letters, digits, or the characters _, @, #, $, %, and -.
RegexUsername = regexp.MustCompile(`^[a-zA-Z0-9_@#$%-]+$`)
// RegexEmail ...
// RegexEmail matches an email address with an RFC 5322 dot-atom or quoted-string local part and a domain of dot-separated labels or bracketed literals.
RegexEmail = regexp.MustCompile(`^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$`)
)
+3 -1
View File
@@ -115,7 +115,9 @@ func connectDatabase(cfg *config.Configuration) (*gorm.DB, error) {
}
}
// DeInitialize ...
// DeInitialize closes the database connection resolved from digCon, releasing
// the connection pool. It returns an error if no database is registered or the
// underlying connection cannot be closed.
func DeInitialize(digCon *dig.Container) error {
var db *gorm.DB
if err := digCon.Invoke(func(database *gorm.DB) { db = database }); err != nil {
+2 -2
View File
@@ -59,7 +59,7 @@ type Artifact struct {
Tags []*Tag `gorm:"foreignKey:ArtifactID;"`
}
// ArtifactSizeByNamespaceOrRepository ...
// ArtifactSizeByNamespaceOrRepository defines generated queries that sum the blob sizes of all artifacts in a namespace or in a single repository.
type ArtifactSizeByNamespaceOrRepository interface {
// SELECT sum(blobs_size) as size FROM @@table WHERE repository_id in (
// SELECT id from repositories where namespace_id = @namespaceID)
@@ -68,7 +68,7 @@ type ArtifactSizeByNamespaceOrRepository interface {
ArtifactSizeByRepository(repositoryID string) (gen.T, error)
}
// ArtifactAssociated ...
// ArtifactAssociated defines the generated query that counts the artifacts referencing the given artifact as their sub-artifact.
type ArtifactAssociated interface {
// SELECT COUNT(artifact_id) as count FROM artifact_artifacts LEFT JOIN artifacts ON artifacts.id = artifact_artifacts.artifact_id WHERE artifacts.deleted_at = 0 AND artifact_sub_id=@artifactID
ArtifactAssociated(artifactID string) (gen.M, error)
+1 -1
View File
@@ -37,7 +37,7 @@ type Blob struct {
Artifacts []*Artifact `gorm:"many2many:artifact_blobs;"`
}
// BlobAssociateWithArtifact ...
// BlobAssociateWithArtifact defines the generated query that returns which of the given blob IDs are still referenced by at least one artifact.
type BlobAssociateWithArtifact interface {
// SELECT blob_id FROM artifact_blobs WHERE blob_id in (@ids)
BlobAssociateWithArtifact(ids []string) (gen.M, error)
+4 -4
View File
@@ -20,7 +20,7 @@ import (
"github.com/go-sigma/sigma/pkg/api/enums"
)
// CodeRepository ...
// CodeRepository stores a source-code repository synced from a third-party provider, bound to one OCI repository and the User3rdParty account that owns it.
type CodeRepository struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
@@ -44,7 +44,7 @@ type CodeRepository struct {
Branches []CodeRepositoryBranch
}
// CodeRepositoryBranch ...
// CodeRepositoryBranch stores a branch of a CodeRepository.
type CodeRepositoryBranch struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
@@ -55,7 +55,7 @@ type CodeRepositoryBranch struct {
Name string
}
// CodeRepositoryOwner ...
// CodeRepositoryOwner caches the owners (users or organizations) seen for a third-party account, for filtering code repositories.
type CodeRepositoryOwner struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
@@ -70,7 +70,7 @@ type CodeRepositoryOwner struct {
User3rdParty User3rdParty `gorm:"foreignKey:User3rdPartyID"`
}
// CodeRepositoryCloneCredential ...
// CodeRepositoryCloneCredential stores the per-provider credentials (SSH key, username/password or token) used to clone a User3rdParty's code repositories.
type CodeRepositoryCloneCredential struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
+2 -2
View File
@@ -37,7 +37,7 @@ type User struct {
NamespaceCount int64 `gorm:"default:0"`
}
// User3rdParty ...
// User3rdParty stores a third-party (e.g. GitHub, GitLab) account linked to a User, including its OAuth tokens and last code-repository sync status.
type User3rdParty struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
@@ -57,7 +57,7 @@ type User3rdParty struct {
User User
}
// TableName ...
// TableName overrides the GORM table name for User3rdParty to "user_3rdparty".
func (User3rdParty) TableName() string {
return "user_3rdparty"
}
+2 -2
View File
@@ -20,7 +20,7 @@ import (
"github.com/go-sigma/sigma/pkg/api/enums"
)
// Webhook ...
// Webhook stores an HTTP endpoint that receives notifications for the selected events, optionally scoped to a namespace.
type Webhook struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
@@ -44,7 +44,7 @@ type Webhook struct {
EventDaemonTaskGc bool
}
// WebhookLog ...
// WebhookLog stores the request/response payloads and status code of one webhook delivery attempt.
type WebhookLog struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
+1 -1
View File
@@ -20,7 +20,7 @@ import (
"github.com/go-sigma/sigma/pkg/api/enums"
)
// WorkQueue ...
// WorkQueue stores a queued daemon task to be executed asynchronously, keyed by topic and payload with its processing status.
type WorkQueue struct {
CreatedAt int64 `gorm:"autoCreateTime:milli"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli"`
+2 -1
View File
@@ -25,7 +25,8 @@ import (
"github.com/go-sigma/sigma/pkg/config"
)
// Client ...
// Client is the process-wide Redis client handle, nil until the embedding
// application assigns a client to it.
var Client redis.UniversalClient
// ClientFactory lazily creates a Redis client.
+3 -1
View File
@@ -28,7 +28,9 @@ import (
"github.com/go-sigma/sigma/pkg/dal/query"
)
// TxnWithRetry ...
// TxnWithRetry runs fc in a query transaction, retrying up to six times with
// jittered backoff (capped at 10s) when the database reports a deadlock. It
// returns the last error once the attempts are exhausted.
func TxnWithRetry(fc func(tx *query.Query) error, opts ...*sql.TxOptions) error {
randInt, err := rand.Int(rand.Reader, big.NewInt(300))
if err != nil {
+3 -3
View File
@@ -29,7 +29,7 @@ import (
"github.com/go-sigma/sigma/pkg/consts"
)
// GetBlob ...
// GetBlob fetches the blob at GET /v2/<repository>/blobs/<digest> and returns its descriptor plus the caller-owned response body reader. It errors on transport failure or any status other than 200 OK.
func (c *clients) GetBlob(ctx context.Context, repository string, digest digest.Digest) (distribution.Descriptor, io.ReadCloser, error) {
statusCode, header, reader, err := c.DoRequest(ctx, http.MethodGet, path.Join("/v2/", repository, "blobs", digest.String()), nil)
if err != nil {
@@ -45,7 +45,7 @@ func (c *clients) GetBlob(ctx context.Context, repository string, digest digest.
return descriptor, reader, nil
}
// HeadBlob ...
// HeadBlob issues HEAD /v2/<repository>/blobs/<digest> to read the blob's descriptor (media type, size, digest) without downloading its content.
func (c *clients) HeadBlob(ctx context.Context, repository string, digest digest.Digest) (distribution.Descriptor, error) {
statusCode, header, _, err := c.DoRequest(ctx, http.MethodHead, path.Join("/v2/", repository, "blobs", digest.String()), nil)
if err != nil {
@@ -95,7 +95,7 @@ func (c *clients) initUpload(ctx context.Context, repository string) (*url.URL,
return locationURL, nil
}
// PutBlob ...
// PutBlob uploads content as the blob identified by digest: it opens an upload session with POST /v2/<repository>/blobs/uploads/, then completes it with a PUT to the returned location carrying the digest query parameter. It errors unless the registry answers 201 Created.
func (c *clients) PutBlob(ctx context.Context, repository string, digest digest.Digest, content io.Reader) error {
location, err := c.initUpload(ctx, repository)
if err != nil {
+4 -4
View File
@@ -53,9 +53,9 @@ type Clients interface {
HeadBlob(ctx context.Context, repository string, digest digest.Digest) (distribution.Descriptor, error)
// PutBlob upload blob to target
PutBlob(ctx context.Context, repository string, digest digest.Digest, content io.Reader) error
// GetManifest ...
// GetManifest fetches and unmarshals the manifest for reference and returns it with its descriptor.
GetManifest(ctx context.Context, repository, reference string) (distribution.Manifest, distribution.Descriptor, error)
// HeadManifest ...
// HeadManifest reports whether a manifest exists for reference, returning false without error on a 404 response.
HeadManifest(ctx context.Context, repository, reference string) (bool, error)
}
@@ -66,14 +66,14 @@ type clients struct {
endpoint string
}
// ClientsFactory ...
// ClientsFactory creates a Clients bound to the upstream registry described by the supplied configuration.
type ClientsFactory interface {
New(config *config.Configuration) (Clients, error)
}
type clientsFactory struct{}
// NewClientsFactory ...
// NewClientsFactory returns a stateless ClientsFactory that builds a new registry client for each configuration passed to New.
func NewClientsFactory() ClientsFactory {
return &clientsFactory{}
}
+2 -2
View File
@@ -26,7 +26,7 @@ import (
"github.com/go-sigma/sigma/pkg/consts"
)
// GetManifest ...
// GetManifest fetches the manifest at GET /v2/<repository>/manifests/<reference>, advertising the Docker v2 and OCI manifest/index media types, and unmarshals the body according to the response Content-Type. It errors on transport failure, any status other than 200 OK, a body read failure, or an unsupported media type.
func (c *clients) GetManifest(ctx context.Context, repository, reference string) (distribution.Manifest, distribution.Descriptor, error) {
var header = http.Header{}
header.Add(consts.HeaderAccept, "application/vnd.docker.distribution.manifest.v2+json")
@@ -52,7 +52,7 @@ func (c *clients) GetManifest(ctx context.Context, repository, reference string)
return manifest, descriptor, nil
}
// HeadManifest ...
// HeadManifest reports whether a manifest exists via HEAD /v2/<repository>/manifests/<reference>. A 404 returns (false, nil), 200 returns (true, nil), and any other status is an error.
func (c *clients) HeadManifest(ctx context.Context, repository, reference string) (bool, error) {
var header = http.Header{}
header.Add(consts.HeaderAccept, "application/vnd.docker.distribution.manifest.v2+json")
+2 -2
View File
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Package reference ...
// Package reference parses registry image references into their domain, namespace, repository, and tag or digest components.
package reference
import (
@@ -22,7 +22,7 @@ import (
"github.com/distribution/reference"
)
// Parse ...
// Parse splits name into its domain, namespace (first repository path component), full repository path, and tag or digest. It requires a namespaced reference and, when neither a tag nor a digest is present, falls back to the default tag "latest"; a missing namespace yields an error.
func Parse(name string) (string, string, string, string, error) {
if !strings.Contains(name, "/") {
return "", "", "", "", fmt.Errorf("invalid reference: %s", name)
+3 -3
View File
@@ -44,7 +44,7 @@ type factory struct{}
var _ signing.SigningFactory = factory{}
// New ...
// New returns a cosign signing client; http selects plain-HTTP registries instead of TLS, and multiArch enables recursive signing of a multi-architecture index.
func (factory) New(http, multiArch bool) (signing.Signing, error) {
return &client{
MultiArch: multiArch,
@@ -52,7 +52,7 @@ func (factory) New(http, multiArch bool) (signing.Signing, error) {
}, nil
}
// Sign ...
// Sign signs the image identified by ref with the PEM private key priKey, resolving ref to a digest-pinned reference and shelling out to the cosign executable with signature transparency logging disabled. The key is written to a temporary file that is removed afterwards, and the command's exit error is returned.
func (s *client) Sign(ctx context.Context, token, priKey, ref string) error {
imageRef, err := s.GetImageRef(ctx, token, ref)
if err != nil {
@@ -97,7 +97,7 @@ func (s *client) Sign(ctx context.Context, token, priKey, ref string) error {
return cmd.Run()
}
// GetDigest ...
// GetImageRef resolves ref against its registry and returns a digest-pinned reference of the form <domain>/<repository>@sha256:<digest>, where the digest is computed over the raw manifest payload. It honors the client's Http flag by contacting the registry over http instead of https.
func (s *client) GetImageRef(ctx context.Context, token, ref string) (string, error) {
domain, _, repo, tag, err := reference.Parse(ref)
if err != nil {
+7 -7
View File
@@ -25,17 +25,17 @@ import (
//go:generate go tool mockgen -destination=signing_mocks.go -package=signing github.com/go-sigma/sigma/pkg/distribution/signing Signing,Verifying,SigningFactory,VerifyingFactory
// Signing ...
// Signing signs the image referenced by ref against the registry, authenticating with token and using priKey as the signing key.
type Signing interface {
Sign(ctx context.Context, token, priKey, ref string) error
}
// Verifying ...
// Verifying validates the signature of the image referenced by ref, using token to authenticate to the registry.
type Verifying interface {
Verify(ref, token string) error
}
// Options ...
// Options selects the signing driver and carries the driver settings used when constructing a Signing or Verifying instance.
type Options struct {
Type enums.SigningType
@@ -56,7 +56,7 @@ var verifyingFactories = make(map[enums.SigningType]VerifyingFactory)
var signingFactories = make(map[enums.SigningType]SigningFactory)
// RegisterSigning ...
// RegisterSigning registers factory as the signing driver for signingType, typically from a driver's init function. Registering a type that is already present is a no-op, so it always returns nil.
func RegisterSigning(signingType enums.SigningType, factory SigningFactory) error {
if _, ok := signingFactories[signingType]; ok {
return nil
@@ -65,7 +65,7 @@ func RegisterSigning(signingType enums.SigningType, factory SigningFactory) erro
return nil
}
// RegisterVerifying ...
// RegisterVerifying registers factory as the verifying driver for signingType, typically from a driver's init function. Registering a type that is already present is a no-op, so it always returns nil.
func RegisterVerifying(signingType enums.SigningType, factory VerifyingFactory) error {
if _, ok := verifyingFactories[signingType]; ok {
return nil
@@ -74,7 +74,7 @@ func RegisterVerifying(signingType enums.SigningType, factory VerifyingFactory)
return nil
}
// NewSigning ...
// NewSigning instantiates a Signing from the factory registered for opt.Type, passing opt.Http and opt.MultiArch to the driver. It errors when the type has no registered signing driver.
func NewSigning(opt Options) (Signing, error) {
factory, ok := signingFactories[opt.Type]
if !ok {
@@ -87,7 +87,7 @@ func NewSigning(opt Options) (Signing, error) {
return signing, nil
}
// NewVerifying ...
// NewVerifying instantiates a Verifying from the factory registered for opt.Type, passing it a fresh dependency-injection container. It errors when the type has no registered verifying driver.
func NewVerifying(opt Options) (Verifying, error) {
factory, ok := verifyingFactories[opt.Type]
if !ok {
+5 -2
View File
@@ -42,12 +42,15 @@ type item struct {
f func()
}
// GetCtx ...
// GetCtx returns the package shutdown context tagged with name, so shutdown
// hooks can identify which component they belong to. The returned context is
// cancelled when Shutdown begins.
func GetCtx(name string) context.Context {
return context.WithValue(ctx, ctxNameKey, name) // nolint: staticcheck
}
// RunAtShutdown ...
// RunAtShutdown registers f to be invoked by Shutdown, ordered by ascending
// index; nil hooks are ignored. Registration is safe for concurrent use.
func RunAtShutdown(name string, index int, f func()) {
if f == nil {
return
+2 -1
View File
@@ -29,7 +29,8 @@ import (
// Fetcher loads a value when the cache misses.
type Fetcher[T any] func(ctx context.Context, key string) (T, error)
// Cacher ...
// Cacher is a generic read-through key/value cache: Get invokes the Fetcher to
// load and cache a missing value, while Set and Del manage stored entries.
type Cacher[T any] interface {
// Set sets the value of given key if it is new to the cache.
// Param val should not be nil.
+2 -1
View File
@@ -47,7 +47,8 @@ type factory struct{}
var _ lock.Factory = factory{}
// New ...
// New builds an in-memory Locker backed by a fresh per-key lock map; Params is
// ignored and the call never fails.
func (factory) New(_ lock.Params) (lock.Locker, error) {
return &lockerMemory{
locks: make(map[string]*memoryLock),
+5 -4
View File
@@ -31,7 +31,7 @@ import (
//go:generate go tool mockgen -destination=locker_mocks.go -package=lock github.com/go-sigma/sigma/pkg/infra/lock Locker,Lock,Factory
const (
// MinLockExpire ...
// MinLockExpire is the shortest lease TTL accepted by Acquire and Renew; a shorter one fails with ErrLockTooShort.
MinLockExpire = 100 * time.Millisecond
)
@@ -46,9 +46,9 @@ var (
// Lock lock interface
type Lock interface {
// Unlock ...
// Unlock releases the held lease, returning ErrLockNotHeld when it is no longer held because it expired or was taken over.
Unlock(ctx context.Context) error
// Renew ...
// Renew extends the held lease by the given TTL, or by the original TTL when none is supplied, keeping the lock alive; it returns ErrLockTooShort for a TTL below MinLockExpire and ErrLockNotHeld once the lease is lost.
Renew(ctx context.Context, ttls ...time.Duration) error
}
@@ -75,7 +75,8 @@ type Params struct {
var Factories = make(registry.Factories[enums.LockerType, Factory])
// New ...
// Initialize constructs the Locker for the driver named by Config.Locker.Type,
// returning an error when that driver has not been registered.
func Initialize(params Params) (Locker, error) {
factory, ok := Factories[params.Config.Locker.Type]
if !ok {
+2 -1
View File
@@ -58,7 +58,8 @@ type factory struct{}
var _ lock.Factory = factory{}
// New ...
// New builds a Redis-backed Locker wrapping a Redsync instance over the client
// from RedisClientFactory; it errors when the factory or its client is nil.
func (factory) New(params lock.Params) (lock.Locker, error) {
if params.RedisClientFactory == nil {
return nil, fmt.Errorf("redis client factory is required")
+3 -1
View File
@@ -37,7 +37,9 @@ const defaultMaxBacklog = 1000
// This is only for small-scale deployment; the default queue backlog limit is 1000 messages.
var packs = make(map[enums.Daemon]chan *models.WorkQueue, 10)
// New ...
// New allocates one bounded channel per registered topic and starts a goroutine
// consuming each topic up to its handler's Concurrency; a non-positive
// Config.WorkQueue.Inmemory.MaxBacklog falls back to defaultMaxBacklog.
func (consumerFactory) New(params workq.ConsumerParams) error {
maxBacklog := params.Config.WorkQueue.Inmemory.MaxBacklog
if maxBacklog <= 0 {
+4 -2
View File
@@ -34,13 +34,15 @@ type producerFactory struct{}
var _ workq.ProducerFactory = producerFactory{}
// NewWorkQueueProducer ...
// New returns the stateless in-memory Producer; Params is ignored and the call
// never fails.
func (producerFactory) New(_ workq.ProducerParams) (workq.Producer, error) {
p := &producer{}
return p, nil
}
// Produce ...
// Produce marshals payload and performs a non-blocking send on the topic's
// channel, erroring when the topic was never initialized or the backlog is full.
func (p *producer) Produce(ctx context.Context, topic enums.Daemon, payload any) error {
data, err := workq.MarshalPayload(ctx, payload)
if err != nil {
+2 -1
View File
@@ -20,7 +20,8 @@ type makeClient struct {
redisCli redis.UniversalClient
}
// MakeRedisClient ...
// MakeRedisClient exposes the wrapped redis.UniversalClient as an any, adapting
// it to the client interface expected by asynq and redsync.
func (m makeClient) MakeRedisClient() any {
return m.redisCli
}
+3 -1
View File
@@ -34,7 +34,9 @@ type consumerFactory struct{}
var _ workq.ConsumerFactory = consumerFactory{}
// New ...
// New starts an asynq server that dispatches the registered topics to their
// handlers with tracing and the configured Redis concurrency; it errors when
// Redis or its client factory is not configured.
func (consumerFactory) New(params workq.ConsumerParams) error {
config := params.Config
if !config.Redis.Enabled() {
+5 -2
View File
@@ -45,7 +45,9 @@ type producerFactory struct{}
var _ workq.ProducerFactory = producerFactory{}
// New ...
// New builds a Redis-backed Producer with an asynq client and inspector, taking
// the backlog limit from Config.WorkQueue.Redis.MaxBacklog; it errors when Redis
// or its client factory is not configured.
func (producerFactory) New(params workq.ProducerParams) (workq.Producer, error) {
config := params.Config
if !config.Redis.Enabled() {
@@ -70,7 +72,8 @@ func (producerFactory) New(params workq.ProducerParams) (workq.Producer, error)
return p, nil
}
// Produce ...
// Produce rejects the payload when the queue backlog has reached its limit,
// otherwise marshals it into an asynq task on the default queue and enqueues it.
func (p *producer) Produce(ctx context.Context, topic enums.Daemon, payload any) error {
if err := p.ensureBacklogAvailable(); err != nil {
return err
+12 -6
View File
@@ -29,16 +29,17 @@ import (
//go:generate go tool mockgen -destination=workq_mocks.go -package=workq github.com/go-sigma/sigma/pkg/infra/workq Producer,ProducerFactory,ConsumerFactory
// Consumer ...
// Consumer describes a topic handler along with the concurrency limit and
// timeout a consumer driver applies when dispatching messages to it.
type Consumer struct {
Handler func(ctx context.Context, payload []byte) error
Concurrency int
Timeout time.Duration
}
// Producer ...
// Producer enqueues a payload for a topic so that registered consumers process it.
type Producer interface {
// Produce ...
// Produce enqueues payload for the given topic so that a registered consumer processes it.
Produce(ctx context.Context, topic enums.Daemon, payload any) error
}
@@ -75,7 +76,8 @@ type ConsumerParams struct {
HandlerRegistry HandlerRegistry
}
// Message ...
// Message is a serialized work item, pairing a topic with its raw payload, as
// exchanged with a queue backend.
type Message struct {
Topic string
Payload []byte
@@ -142,7 +144,9 @@ func RegisterConsumer(name enums.WorkQueueType, factory ConsumerFactory) error {
return nil
}
// InitProducer ...
// InitProducer constructs the Producer for the driver named by
// Config.WorkQueue.Type, returning an error when no factory has been registered
// for that (unsupported) work-queue type.
func InitProducer(params ProducerParams) (Producer, error) {
factory, ok := producerFactories[params.Config.WorkQueue.Type]
if !ok {
@@ -151,7 +155,9 @@ func InitProducer(params ProducerParams) (Producer, error) {
return factory.New(params)
}
// InitConsumer ...
// InitConsumer constructs the consumer for the driver named by
// Config.WorkQueue.Type, returning an error when no factory has been registered
// for that (unsupported) work-queue type.
func InitConsumer(params ConsumerParams) error {
factory, ok := consumerFactories[params.Config.WorkQueue.Type]
if !ok {
+6 -6
View File
@@ -248,7 +248,7 @@ var (
}
)
// GenDSErrCodeResourceSizeQuotaExceedNamespace ...
// GenDSErrCodeResourceSizeQuotaExceedNamespace builds a DENIED distribution error (403) reporting that the push would exceed the namespace's storage size quota, including current usage, the limit, and the requested increase.
func GenDSErrCodeResourceSizeQuotaExceedNamespace(name string, current, limit, increase int64) ErrCode {
c := ErrCode{
Code: "DENIED",
@@ -263,7 +263,7 @@ func GenDSErrCodeResourceSizeQuotaExceedNamespace(name string, current, limit, i
return c
}
// GenDSErrCodeResourceSizeQuotaExceedRepository ...
// GenDSErrCodeResourceSizeQuotaExceedRepository builds a DENIED distribution error (403) reporting that the push would exceed the repository's storage size quota, including current usage, the limit, and the requested increase.
func GenDSErrCodeResourceSizeQuotaExceedRepository(name string, current, limit, increase int64) ErrCode {
c := ErrCode{
Code: "DENIED",
@@ -287,7 +287,7 @@ func toFixed(num float64, precision int) float64 {
return float64(round(num*output)) / output
}
// GenDSErrCodeResourceCountQuotaExceedRepository ...
// GenDSErrCodeResourceCountQuotaExceedRepository builds a DENIED distribution error (403) reporting that the repository's tag count quota has been exceeded.
func GenDSErrCodeResourceCountQuotaExceedRepository(name string, limit int64) ErrCode {
c := ErrCode{
Code: "DENIED",
@@ -298,7 +298,7 @@ func GenDSErrCodeResourceCountQuotaExceedRepository(name string, limit int64) Er
return c
}
// GenDSErrCodeResourceCountQuotaExceedNamespaceRepository ...
// GenDSErrCodeResourceCountQuotaExceedNamespaceRepository builds a DENIED distribution error (403) reporting that the namespace's repository count quota has been exceeded.
func GenDSErrCodeResourceCountQuotaExceedNamespaceRepository(name string, limit int64) ErrCode {
c := ErrCode{
Code: "DENIED",
@@ -309,7 +309,7 @@ func GenDSErrCodeResourceCountQuotaExceedNamespaceRepository(name string, limit
return c
}
// GenDSErrCodeResourceCountQuotaExceedNamespaceTag ...
// GenDSErrCodeResourceCountQuotaExceedNamespaceTag builds a DENIED distribution error (403) reporting that the namespace's tag count quota has been exceeded.
func GenDSErrCodeResourceCountQuotaExceedNamespaceTag(name string, limit int64) ErrCode {
c := ErrCode{
Code: "DENIED",
@@ -320,7 +320,7 @@ func GenDSErrCodeResourceCountQuotaExceedNamespaceTag(name string, limit int64)
return c
}
// GenDSErrCodeResourceNotFound ...
// GenDSErrCodeResourceNotFound builds a RESOURCE_NOT_FOUND distribution error (404) whose title carries the given error's message.
func GenDSErrCodeResourceNotFound(err error) ErrCode {
c := ErrCode{
Code: "RESOURCE_NOT_FOUND",
+2 -2
View File
@@ -40,12 +40,12 @@ type ErrCode struct {
HTTPStatusCode int `json:"http_status_code" example:"401"`
}
// Error ...
// Error implements the built-in error interface, rendering the code and title as "code: title".
func (e ErrCode) Error() string {
return fmt.Sprintf("%s: %s", e.Code, e.Title)
}
// Detail ...
// Detail sets the error's Description to desc in place and returns a copy of the receiver, allowing the Description to be customized while building an ErrCode.
func (e *ErrCode) Detail(desc string) ErrCode {
e.Description = desc
return ptr.To(e)
@@ -30,7 +30,7 @@ import (
"github.com/go-sigma/sigma/pkg/server/errcode"
)
// GetRunnerLog ...
// GetRunnerLog handles GET .../builders/:builder_id/runners/:runner_id/log; it upgrades the request to a websocket and streams the runner's log (gzip-decoding it when stored compressed), looping while the runner is still building and replying 204 once the websocket handler returns.
func (h *handler) GetRunnerLog(c *gin.Context, req *api.GetRunnerLog) {
ctx := c.Request.Context()
@@ -24,7 +24,7 @@ import (
"github.com/go-sigma/sigma/pkg/server/errcode"
)
// GetRunnerRerun ...
// GetRunnerRerun handles GET .../builders/:builder_id/runners/:runner_id/rerun; it starts a new run from the original runner's spec and returns the new runner id with 200, or an error code on failure.
func (h *handler) GetRunnerRerun(c *gin.Context, req *api.GetRunnerStop) {
ctx := c.Request.Context()
@@ -24,7 +24,7 @@ import (
"github.com/go-sigma/sigma/pkg/server/errcode"
)
// PostRunnerRun ...
// PostRunnerRun handles POST .../builders/:builder_id/runners/run; it starts a new builder runner from the request spec and returns the new runner id with 201, or an error code on failure.
func (h *handler) PostRunnerRun(c *gin.Context, req *api.PostRunnerRun) {
ctx := c.Request.Context()
@@ -24,7 +24,7 @@ import (
"github.com/go-sigma/sigma/pkg/server/errcode"
)
// GetRunnerStop ...
// GetRunnerStop handles GET .../builders/:builder_id/runners/:runner_id/stop; it cancels the running runner and returns 204, or an error code describing the failure.
func (h *handler) GetRunnerStop(c *gin.Context, req *api.GetRunnerStop) {
ctx := c.Request.Context()
+5 -5
View File
@@ -33,15 +33,15 @@ type Handler interface {
UpdateBuilder(c *gin.Context, req *api.UpdateBuilderRequest)
// ListRunners handles the list builder runners request
ListRunners(c *gin.Context, req *api.ListBuilderRunnersRequest)
// PostRunnerRun ...
// PostRunnerRun starts a new builder runner from the request spec and returns the created runner ID.
PostRunnerRun(c *gin.Context, req *api.PostRunnerRun)
// GetRunnerRerun ...
// GetRunnerRerun starts a fresh run reusing the original runner's build spec and returns the new runner ID.
GetRunnerRerun(c *gin.Context, req *api.GetRunnerStop)
// GetRunnerStop ...
// GetRunnerStop cancels the specified running builder runner and responds with no content.
GetRunnerStop(c *gin.Context, req *api.GetRunnerStop)
// GetRunnerLog ...
// GetRunnerLog upgrades the request to a websocket and streams the runner's log, repeating while the build is still running.
GetRunnerLog(c *gin.Context, req *api.GetRunnerLog)
// GetRunner ...
// GetRunner returns the builder runner identified by the request, including its status, tag, and duration.
GetRunner(c *gin.Context, req *api.GetRunner)
}
+2 -2
View File
@@ -33,9 +33,9 @@ type Handler interface {
Get(c *gin.Context, req *api.GetCodeRepositoryRequest)
// ListOwner list all of the code repository owner
ListOwners(c *gin.Context, req *api.ListCodeRepositoryOwnerRequest)
// ListBranches ...
// ListBranches returns a paginated list of branches for the requested source code repository.
ListBranches(c *gin.Context, req *api.ListCodeRepositoryBranchesRequest)
// GetBranch ...
// GetBranch returns the source code repository branch identified by name.
GetBranch(c *gin.Context, req *api.GetCodeRepositoryBranchRequest)
// Resync resync all of the code repositories
Resync(c *gin.Context, req *api.GetCodeRepositoryResyncRequest)
+32 -32
View File
@@ -26,72 +26,72 @@ import (
// Handler is the interface for the gc handlers
type Handler interface {
// UpdateGcTagRule ...
// UpdateGcTagRule replaces the namespace's gc tag retention rule (cron schedule and retention policy).
UpdateGcTagRule(c *gin.Context, req *api.UpdateGcTagRuleRequest)
// GetGcTagRule ...
// GetGcTagRule returns the namespace's gc tag retention rule.
GetGcTagRule(c *gin.Context, req *api.GetGcTagRuleRequest)
// GetGcTagLatestRunner ...
// GetGcTagLatestRunner returns the most recent gc tag run of the namespace.
GetGcTagLatestRunner(c *gin.Context, req *api.GetGcTagLatestRunnerRequest)
// CreateGcTagRunner ...
// CreateGcTagRunner triggers an immediate gc tag run for the namespace.
CreateGcTagRunner(c *gin.Context, req *api.CreateGcTagRunnerRequest)
// ListGcTagRunners ...
// ListGcTagRunners returns a paginated list of the namespace's gc tag runs.
ListGcTagRunners(c *gin.Context, req *api.ListGcTagRunnersRequest)
// GetGcTagRunner ...
// GetGcTagRunner returns a single gc tag run by its runner id.
GetGcTagRunner(c *gin.Context, req *api.GetGcTagRunnerRequest)
// ListGcTagRecords ...
// ListGcTagRecords returns a paginated list of the per-tag outcomes recorded by one gc tag run.
ListGcTagRecords(c *gin.Context, req *api.ListGcTagRecordsRequest)
// GetGcTagRecord ...
// GetGcTagRecord returns a single per-tag outcome recorded by a gc tag run.
GetGcTagRecord(c *gin.Context, req *api.GetGcTagRecordRequest)
// UpdateGcRepositoryRule ...
// UpdateGcRepositoryRule replaces the namespace's gc repository retention rule (cron schedule and retention policy).
UpdateGcRepositoryRule(c *gin.Context, req *api.UpdateGcRepositoryRuleRequest)
// GetGcRepositoryRule ...
// GetGcRepositoryRule returns the namespace's gc repository retention rule.
GetGcRepositoryRule(c *gin.Context, req *api.GetGcRepositoryRuleRequest)
// GetGcRepositoryLatestRunner ...
// GetGcRepositoryLatestRunner returns the most recent gc repository run of the namespace.
GetGcRepositoryLatestRunner(c *gin.Context, req *api.GetGcRepositoryLatestRunnerRequest)
// CreateGcRepositoryRunner ...
// CreateGcRepositoryRunner triggers an immediate gc repository run for the namespace.
CreateGcRepositoryRunner(c *gin.Context, req *api.CreateGcRepositoryRunnerRequest)
// ListGcRepositoryRunners ...
// ListGcRepositoryRunners returns a paginated list of the namespace's gc repository runs.
ListGcRepositoryRunners(c *gin.Context, req *api.ListGcRepositoryRunnersRequest)
// GetGcRepositoryRunner ...
// GetGcRepositoryRunner returns a single gc repository run by its runner id.
GetGcRepositoryRunner(c *gin.Context, req *api.GetGcRepositoryRunnerRequest)
// ListGcRepositoryRecords ...
// ListGcRepositoryRecords returns a paginated list of the per-repository outcomes recorded by one gc repository run.
ListGcRepositoryRecords(c *gin.Context, req *api.ListGcRepositoryRecordsRequest)
// GetGcRepositoryRecord ...
// GetGcRepositoryRecord returns a single per-repository outcome recorded by a gc repository run.
GetGcRepositoryRecord(c *gin.Context, req *api.GetGcRepositoryRecordRequest)
// UpdateGcArtifactRule ...
// UpdateGcArtifactRule replaces the namespace's gc artifact retention rule (cron schedule and retention policy).
UpdateGcArtifactRule(c *gin.Context, req *api.UpdateGcArtifactRuleRequest)
// GetGcArtifactRule ...
// GetGcArtifactRule returns the namespace's gc artifact retention rule.
GetGcArtifactRule(c *gin.Context, req *api.GetGcArtifactRuleRequest)
// GetGcArtifactLatestRunner ...
// GetGcArtifactLatestRunner returns the most recent gc artifact run of the namespace.
GetGcArtifactLatestRunner(c *gin.Context, req *api.GetGcArtifactLatestRunnerRequest)
// CreateGcArtifactRunner ...
// CreateGcArtifactRunner triggers an immediate gc artifact run for the namespace.
CreateGcArtifactRunner(c *gin.Context, req *api.CreateGcArtifactRunnerRequest)
// ListGcArtifactRunners ...
// ListGcArtifactRunners returns a paginated list of the namespace's gc artifact runs.
ListGcArtifactRunners(c *gin.Context, req *api.ListGcArtifactRunnersRequest)
// GetGcArtifactRunner ...
// GetGcArtifactRunner returns a single gc artifact run by its runner id.
GetGcArtifactRunner(c *gin.Context, req *api.GetGcArtifactRunnerRequest)
// ListGcArtifactRecords ...
// ListGcArtifactRecords returns a paginated list of the per-artifact outcomes recorded by one gc artifact run.
ListGcArtifactRecords(c *gin.Context, req *api.ListGcArtifactRecordsRequest)
// GetGcArtifactRecord ...
// GetGcArtifactRecord returns a single per-artifact outcome recorded by a gc artifact run.
GetGcArtifactRecord(c *gin.Context, req *api.GetGcArtifactRecordRequest)
// UpdateGcBlobRule ...
// UpdateGcBlobRule replaces the namespace's gc blob retention rule (cron schedule and retention policy).
UpdateGcBlobRule(c *gin.Context, req *api.UpdateGcBlobRuleRequest)
// GetGcBlobRule ...
// GetGcBlobRule returns the namespace's gc blob retention rule.
GetGcBlobRule(c *gin.Context, req *api.GetGcBlobRuleRequest)
// GetGcBlobLatestRunner ...
// GetGcBlobLatestRunner returns the most recent gc blob run of the namespace.
GetGcBlobLatestRunner(c *gin.Context, req *api.GetGcBlobLatestRunnerRequest)
// CreateGcBlobRunner ...
// CreateGcBlobRunner triggers an immediate gc blob run for the namespace.
CreateGcBlobRunner(c *gin.Context, req *api.CreateGcBlobRunnerRequest)
// ListGcBlobRunners ...
// ListGcBlobRunners returns a paginated list of the namespace's gc blob runs.
ListGcBlobRunners(c *gin.Context, req *api.ListGcBlobRunnersRequest)
// GetGcBlobRunner ...
// GetGcBlobRunner returns a single gc blob run by its runner id.
GetGcBlobRunner(c *gin.Context, req *api.GetGcBlobRunnerRequest)
// ListGcBlobRecords ...
// ListGcBlobRecords returns a paginated list of the per-blob outcomes recorded by one gc blob run.
ListGcBlobRecords(c *gin.Context, req *api.ListGcBlobRecordsRequest)
// GetGcBlobRecord ...
// GetGcBlobRecord returns a single per-blob outcome recorded by a gc blob run.
GetGcBlobRecord(c *gin.Context, req *api.GetGcBlobRecordRequest)
}
@@ -31,11 +31,11 @@ import (
// Handler is the interface for the distribution blob handlers
type Handler interface {
// DeleteBlob ...
// DeleteBlob removes the blob identified by the path digest after a namespace-level manage authorization check and responds 202 Accepted; a blob still referenced by an artifact cannot be deleted.
DeleteBlob(ctx *gin.Context)
// HeadBlob ...
// HeadBlob reports whether the blob identified by the path digest exists, returning its Content-Length, Content-Type and Docker-Content-Digest headers with 200 OK and no body.
HeadBlob(ctx *gin.Context)
// GetBlob ...
// GetBlob serves the blob identified by the path digest with its Content-Length, Content-Type and Docker-Content-Digest headers; it returns a 301 redirect when the storage backend is configured to redirect, falls back to the configured proxy when the blob is missing locally, and otherwise streams the bytes.
GetBlob(ctx *gin.Context)
}
@@ -30,15 +30,15 @@ import (
// Handler is the interface for the distribution manifest handlers
type Handler interface {
// GetManifest ...
// GetManifest returns the raw manifest stored for the given tag or digest together with its stored content type and digest headers, records a pull event, and falls back to the upstream registry proxy when mirroring is enabled.
GetManifest(ctx *gin.Context)
// HeadManifest ...
// HeadManifest returns the manifest metadata (content type, content length and digest headers) for the given tag or digest without a body and without recording a pull event.
HeadManifest(ctx *gin.Context)
// PutManifest ...
// PutManifest stores the request body as a manifest for the given tag or digest, handling image manifests, image indexes and artifacts, advances the tag, and responds 201 Created with Docker-Content-Digest and Location headers.
PutManifest(ctx *gin.Context)
// DeleteManifest ...
// DeleteManifest deletes the manifest referenced by the path tag or digest, removing only the tag when a tag is given and the artifact plus every tag pointing to it when a digest is given, and responds 202 Accepted.
DeleteManifest(ctx *gin.Context)
// GetReferrer ...
// GetReferrer implements the OCI referrers API, returning an image index of the manifests whose subject is the path digest, filtered by the optional artifactType query parameter echoed back in OCI-Filters-Applied.
GetReferrer(ctx *gin.Context)
}
@@ -117,7 +117,7 @@ func (h *handler) GetManifest(c *gin.Context) {
c.Data(http.StatusOK, contentType, body)
}
// getManifestFallbackProxy ...
// getManifestFallbackProxy fetches the manifest from the upstream registry via the configured proxy and writes it to the client: an upstream 200 is relayed with the content digest and ETag headers, an upstream 404 becomes a manifest-unknown distribution error, and any other status becomes an unknown distribution error.
func (h *handler) getManifestFallbackProxy(c *gin.Context, refs Refs) {
statusCode, header, bodyBytes, err := h.fallbackProxy(c)
if err != nil {
@@ -112,7 +112,7 @@ func (h *handler) HeadManifest(c *gin.Context) {
c.Status(http.StatusOK)
}
// headManifestFallbackProxy ...
// headManifestFallbackProxy probes the manifest in the upstream registry via the configured proxy, forwarding the upstream content type and its 200/404 status, and reports an unknown distribution error for any other status.
func (h *handler) headManifestFallbackProxy(c *gin.Context) {
statusCode, header, _, err := h.fallbackProxy(c)
if err != nil {
@@ -26,7 +26,7 @@ import (
"github.com/go-sigma/sigma/pkg/server/errcode"
)
// GetReferrer ...
// GetReferrer handles GET /v2/<name>/referrers/<digest>; it validates the digest, echoes the requested artifactType filter in OCI-Filters-Applied, and returns the referrers image index with 200, or a distribution error on failure.
func (h *handler) GetReferrer(c *gin.Context) {
ctx := c.Request.Context()
uri := c.Request.URL.Path
@@ -29,15 +29,15 @@ import (
// Handler is the interface for the distribution blob handlers
type Handler interface {
// DeleteUpload ...
// DeleteUpload cancels an upload session, discarding its partial content and responding 204 No Content.
DeleteUpload(ctx *gin.Context)
// GetUpload ...
// GetUpload reports the status of an upload session, responding 204 No Content with the upload UUID and Location headers, or a distribution error when the session is unknown.
GetUpload(ctx *gin.Context)
// PatchUpload ...
// PatchUpload appends the request body as a chunk to an existing upload session and responds 202 Accepted with an inclusive Range header covering the bytes received so far.
PatchUpload(ctx *gin.Context)
// PostUpload ...
// PostUpload starts a blob upload session, responding 202 Accepted with a Docker-Upload-UUID and Location header, or performs a single-shot upload that stores the blob directly when a digest query parameter is present; cross-repository blob mounting is not supported.
PostUpload(ctx *gin.Context)
// PutUpload ...
// PutUpload finalises an upload session under the digest query parameter, appending any remaining request body and responding 201 Created with a Docker-Content-Digest header.
PutUpload(ctx *gin.Context)
}
+1 -1
View File
@@ -74,7 +74,7 @@ func Initialize(digCon *dig.Container) error {
return nil
}
// InitializeDistribution ...
// InitializeDistribution mounts the OCI distribution endpoints on /v2/*path, dispatching every HTTP method through distribution.All, and returns an error if route registration fails.
func InitializeDistribution(digCon *dig.Container) error {
if err := digCon.Invoke(func(e *gin.Engine) error {
e.Any("/v2/*path", server.Wrap(func(c *gin.Context) {
+1 -1
View File
@@ -31,7 +31,7 @@ type Handler interface {
Callback(c *gin.Context, req *api.Oauth2CallbackRequest)
// ClientID handles the client id request
ClientID(c *gin.Context, req *api.Oauth2ClientIDRequest)
// RedirectCallback ...
// RedirectCallback redirects the browser to the frontend login callback with the provider and authorization code so the client can finish the OAuth2 flow.
RedirectCallback(c *gin.Context, req *api.Oauth2CallbackRequest)
}
+1 -1
View File
@@ -22,7 +22,7 @@ import (
"github.com/go-sigma/sigma/pkg/server"
)
// Handler ...
// Handler validates user-supplied container references, tags, passwords, cron expressions and regular expressions for the API.
type Handler interface {
// GetReference handles the validate reference request
GetReference(c *gin.Context, req *api.GetValidatorReferenceRequest)
+5 -5
View File
@@ -38,15 +38,15 @@ type Handler interface {
DeleteWebhook(c *gin.Context, req *api.DeleteWebhookRequest)
// PutWebhook handles the put webhook request
PutWebhook(c *gin.Context, req *api.PutWebhookRequest)
// GetWebhookPing ...
// GetWebhookPing sends a test ping event to the webhook's configured endpoint and responds with no content.
GetWebhookPing(c *gin.Context, req *api.GetWebhookPingRequest)
// GetWebhookLog ...
// GetWebhookLog returns the recorded delivery log for the webhook, including request and response headers and bodies.
GetWebhookLog(c *gin.Context, req *api.GetWebhookLogRequest)
// DeleteWebhookLog ...
// DeleteWebhookLog removes the recorded webhook delivery log and responds with no content.
DeleteWebhookLog(c *gin.Context, req *api.DeleteWebhookLogRequest)
// ListWebhookLogs ...
// ListWebhookLogs returns a paginated list of delivery logs for the webhook.
ListWebhookLogs(c *gin.Context, req *api.ListWebhookLogRequest)
// GetWebhookLogResend ...
// GetWebhookLogResend re-delivers a previously recorded webhook request and responds with no content.
GetWebhookLogResend(c *gin.Context, req *api.GetWebhookLogResendRequest)
}
+1 -1
View File
@@ -57,7 +57,7 @@ type Config struct {
LoginRateLimiter ratelimit.Limiter
}
// AuthnConfig ...
// AuthnConfig holds options for the authentication middleware; Skip disables authentication entirely when true.
type AuthnConfig struct {
Skip bool
}
+2 -1
View File
@@ -42,7 +42,8 @@ type factory struct{}
var _ storage.Factory = factory{}
// New ...
// New builds a Tencent COS-backed driver from the [storage.cos] endpoint, AK/SK
// and storage.root_directory; it returns an error if the endpoint URL is invalid.
func (f factory) New(config *config.Configuration) (storage.StorageDriver, error) {
u, err := url.Parse(config.Storage.Cos.Endpoint)
if err != nil {
+2 -1
View File
@@ -43,7 +43,8 @@ type factory struct{}
var _ storage.Factory = factory{}
// New ...
// New builds an Alibaba OSS-backed driver from the [storage.oss] endpoint, AK/SK,
// bucket and force-path-style flag, rooted at storage.root_directory.
func (f factory) New(config *config.Configuration) (storage.StorageDriver, error) {
client, err := oss.New(config.Storage.Oss.Endpoint, config.Storage.Oss.Ak, config.Storage.Oss.Sk,
oss.ForcePathStyle(config.Storage.Oss.ForcePathStyle))
+6 -5
View File
@@ -26,13 +26,13 @@ import (
)
const (
// MultipartCopyThresholdSize ...
// MultipartCopyThresholdSize is the source object size at or below which a copy is done in one request instead of as a multipart copy; 64 MiB.
MultipartCopyThresholdSize = 64 << 20 // 64MB
// MultipartCopyChunkSize ...
// MultipartCopyChunkSize is the byte size of each part of a multipart copy; 64 MiB.
MultipartCopyChunkSize = 64 << 20 // 64MB
// MultipartCopyMaxConcurrency ...
// MultipartCopyMaxConcurrency caps the number of goroutines copying parts concurrently; 100.
MultipartCopyMaxConcurrency = 100 // 100 goroutines
// MaxPaginationKeys ...
// MaxPaginationKeys is the maximum number of object keys requested per paginated listing call; 1000.
MaxPaginationKeys = 1000 // 1000 keys
)
@@ -105,7 +105,8 @@ func Initialize(config *config.Configuration) (StorageDriver, error) {
return factory.New(config)
}
// SanitizePath ...
// SanitizePath joins rootDirectory and p into a storage path, trimming a leading
// "./" from both; when rootDirectory is empty, ".", "./" or "/" it returns p as is.
func SanitizePath(rootDirectory, p string) string {
if rootDirectory == "" || rootDirectory == "." || rootDirectory == "./" || rootDirectory == "/" {
return p
+2 -1
View File
@@ -54,7 +54,8 @@ func Compress(src string) ([]byte, error) {
return dst.Bytes(), nil
}
// CompressBytes ...
// CompressBytes gzip-compresses src at gzip.BestSpeed and returns the compressed
// bytes; the returned slice aliases a buffer owned by the writer and must not be mutated.
func CompressBytes(src []byte) ([]byte, error) {
srcReader := bytes.NewReader(src)
var dst bytes.Buffer
+4 -3
View File
@@ -28,7 +28,7 @@ import (
"strings"
)
// ErrNoSuchFile ...
// ErrNoSuchFile is returned by File and FileVerify when the path is not an existing regular file.
var ErrNoSuchFile = errors.New("no such file")
func isFile(filePath string) bool {
@@ -100,7 +100,7 @@ func String(str string, method ...string) (hash string, err error) {
return
}
// MustString ...
// MustString is String for callers that cannot handle an error; it panics if hashing fails.
func MustString(str string, method ...string) string {
hash, err := String(str, method...)
if err != nil {
@@ -145,7 +145,8 @@ const (
cacheSize = 10240
)
// Reader ...
// Reader hashes reader to completion in 10 KiB chunks and returns the hex digest;
// method defaults to sha256 and may be md5, sha1, sha256 or sha512.
func Reader(reader io.Reader, method ...string) (hash string, err error) {
var h = selectMethod(method)
var data = make([]byte, cacheSize)
+14 -7
View File
@@ -41,7 +41,8 @@ import (
"github.com/go-sigma/sigma/pkg/utils/ptr"
)
// GetFromCtx ...
// GetFromCtx reads key from the gin context and asserts it to T; it returns the
// zero value of T and false when the key is missing or holds a different type.
func GetFromCtx[T any](c *gin.Context, key string) (T, bool) {
val, exists := c.Get(key)
if !exists {
@@ -119,7 +120,8 @@ func NormalizePagination(in api.Pagination) api.Pagination {
return in
}
// TrimHTTP ...
// TrimHTTP strips a leading "http://" or "https://" scheme from in, or, when no
// scheme is present, a trailing "/".
func TrimHTTP(in string) string {
if after, ok := strings.CutPrefix(in, "http://"); ok {
return after
@@ -199,7 +201,8 @@ type stringsJoin interface {
String() string
}
// StringsJoin ...
// StringsJoin joins the String() form of each element of strs with sep, returning
// an empty string for an empty slice.
func StringsJoin[T stringsJoin](strs []T, sep string) string {
if len(strs) == 0 {
return ""
@@ -214,7 +217,8 @@ func StringsJoin[T stringsJoin](strs []T, sep string) string {
return strings.Join(b, sep)
}
// UnwrapJoinedErrors ...
// UnwrapJoinedErrors flattens an errors.Join-style error into a single ": "-joined
// string, falling back to err.Error() when it does not implement Unwrap() []error.
func UnwrapJoinedErrors(err error) string {
e, ok := err.(interface{ Unwrap() []error })
if !ok {
@@ -254,7 +258,8 @@ func GetUserFromCtx(c *gin.Context, format UserCtxErrorFormat) (*models.User, bo
return user, false
}
// OnceWithErr ...
// OnceWithErr runs fn at most once via once and returns its error; a panic inside
// fn (or a second call racing the first) yields an error instead of propagating it.
func OnceWithErr(once *sync.Once, fn func() error) error {
var errChan = make(chan error, 1)
defer close(errChan)
@@ -270,7 +275,8 @@ func OnceWithErr(once *sync.Once, fn func() error) error {
return <-errChan
}
// GenRsaPriKey ...
// GenRsaPriKey generates an RSA private key of 1024, 2048 or 4096 bits and returns
// it as a base64-encoded PKCS#1 PEM block; other lengths are rejected.
func GenRsaPriKey(length int) (string, error) {
if length != 1024 && length != 2048 && length != 4096 {
return "", fmt.Errorf("rsa length is not allow")
@@ -288,7 +294,8 @@ func GenRsaPriKey(length int) (string, error) {
return base64.StdEncoding.EncodeToString(pem.EncodeToMemory(privateKeyPEM)), nil
}
// GenSecureID ...
// GenSecureID returns a lowercase base32 (hex alphabet) encoding of n
// cryptographically random bytes; it panics if the system entropy source fails.
func GenSecureID(n int) string {
b := make([]byte, n)
_, err := rand.Read(b)
+12 -6
View File
@@ -136,14 +136,16 @@ func newValidator() (*validator.Validate, error) {
return v, nil
}
// ValidateNamespaceRole ...
// ValidateNamespaceRole reports whether the field parses as an enums.NamespaceRole;
// note the is_valid_namespace_role tag is currently bound to ValidateRetentionPattern.
func ValidateNamespaceRole(field validator.FieldLevel) bool {
v := field.Field().String()
_, err := enums.ParseNamespaceRole(v)
return err == nil
}
// ValidateRetentionPattern ...
// ValidateRetentionPattern implements the is_valid_retention_pattern tag: the field
// is a comma-separated list of non-empty regular expressions that must all compile.
func ValidateRetentionPattern(field validator.FieldLevel) bool {
patterns := strings.SplitSeq(field.Field().String(), ",")
for pattern := range patterns {
@@ -158,14 +160,16 @@ func ValidateRetentionPattern(field validator.FieldLevel) bool {
return true
}
// ValidateRetentionRuleType ...
// ValidateRetentionRuleType implements the is_valid_retention_rule_type tag,
// accepting field values recognized by enums.ParseRetentionRuleType.
func ValidateRetentionRuleType(field validator.FieldLevel) bool {
v := field.Field().String()
_, err := enums.ParseRetentionRuleType(v)
return err == nil
}
// ValidateCronRule ...
// ValidateCronRule implements the is_valid_cron_rule tag, accepting field values
// that cron.ParseStandard parses as standard 5-field cron expressions.
func ValidateCronRule(field validator.FieldLevel) bool {
v := field.Field().String()
_, err := cron.ParseStandard(v)
@@ -209,7 +213,8 @@ func ValidateRepository(field validator.FieldLevel) bool {
return ValidateRepositoryRaw(field.Field().String())
}
// ValidateRepositoryRaw ...
// ValidateRepositoryRaw reports whether repository contains at least one "/" and
// parses as a normalized named reference; it backs the is_valid_repository tag.
func ValidateRepositoryRaw(repository string) bool {
if len(strings.Split(repository, "/")) < 2 {
return false
@@ -230,7 +235,8 @@ func ValidateNamespace(field validator.FieldLevel) bool {
return ValidateNamespaceRaw(field.Field().String())
}
// ValidateNamespaceRaw ...
// ValidateNamespaceRaw reports whether namespace matches ^[a-z][0-9a-z-]{0,20}$
// and is at most 20 characters; it backs the is_valid_namespace tag.
func ValidateNamespaceRaw(namespace string) bool {
return namespaceRegex.MatchString(namespace) && len(namespace) <= maxNamespace
}
+3 -3
View File
@@ -15,10 +15,10 @@
package version
var (
// Version ...
// Version is the git describe tag of the build, injected at link time via -X github.com/go-sigma/sigma/pkg/version.Version.
Version = ""
// GitHash ...
// GitHash is the short git commit hash of the build, injected at link time via -X github.com/go-sigma/sigma/pkg/version.GitHash.
GitHash = ""
// BuildDate ...
// BuildDate is the UTC build timestamp, injected at link time via -X github.com/go-sigma/sigma/pkg/version.BuildDate.
BuildDate = ""
)