Initial commit: GitLab repository delivery middleware
HTTP service that fetches GitLab repository archives for configured customers, merges them into a single tarball, and returns an encrypted payload. Includes Nix flake for reproducible builds.
This commit is contained in:
95
src/config.go
Normal file
95
src/config.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
type rawConfig struct {
|
||||
Schema string `toml:"schema"`
|
||||
Config struct {
|
||||
GitLabURL string `toml:"gitlab_url"`
|
||||
GitLabAPIKey string `toml:"gitlab_api_key"`
|
||||
} `toml:"config"`
|
||||
Customers map[string]rawCustomer `toml:"customers"`
|
||||
}
|
||||
|
||||
type rawCustomer struct {
|
||||
Key string `toml:"key"`
|
||||
Repos []string `toml:"repos"`
|
||||
}
|
||||
|
||||
type ResolvedConfig struct {
|
||||
GitLabURL string
|
||||
GitLabAPIKey string
|
||||
Customers map[string]ResolvedCustomer
|
||||
}
|
||||
|
||||
type ResolvedCustomer struct {
|
||||
Key []byte
|
||||
Repos []string
|
||||
}
|
||||
|
||||
func LoadConfig(path string) (*ResolvedConfig, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading config: %w", err)
|
||||
}
|
||||
|
||||
expanded := os.Expand(string(data), os.Getenv)
|
||||
|
||||
var raw rawConfig
|
||||
if err := toml.Unmarshal([]byte(expanded), &raw); err != nil {
|
||||
return nil, fmt.Errorf("parsing config: %w", err)
|
||||
}
|
||||
|
||||
if err := validateRawConfig(&raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resolved := &ResolvedConfig{
|
||||
GitLabURL: raw.Config.GitLabURL,
|
||||
GitLabAPIKey: raw.Config.GitLabAPIKey,
|
||||
Customers: make(map[string]ResolvedCustomer, len(raw.Customers)),
|
||||
}
|
||||
|
||||
for name, cust := range raw.Customers {
|
||||
key, err := hex.DecodeString(cust.Key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("customer %q: invalid hex key: %w", name, err)
|
||||
}
|
||||
resolved.Customers[name] = ResolvedCustomer{
|
||||
Key: key,
|
||||
Repos: cust.Repos,
|
||||
}
|
||||
}
|
||||
|
||||
return resolved, nil
|
||||
}
|
||||
|
||||
func validateRawConfig(raw *rawConfig) error {
|
||||
if raw.Schema != "v1" {
|
||||
return fmt.Errorf("unsupported schema: %q (expected \"v1\")", raw.Schema)
|
||||
}
|
||||
if raw.Config.GitLabURL == "" {
|
||||
return fmt.Errorf("config.gitlab_url is required")
|
||||
}
|
||||
if raw.Config.GitLabAPIKey == "" {
|
||||
return fmt.Errorf("config.gitlab_api_key is required")
|
||||
}
|
||||
if len(raw.Customers) == 0 {
|
||||
return fmt.Errorf("at least one customer is required")
|
||||
}
|
||||
for name, cust := range raw.Customers {
|
||||
if len(cust.Key) != 64 {
|
||||
return fmt.Errorf("customer %q: key must be 64 hex characters (got %d)", name, len(cust.Key))
|
||||
}
|
||||
if len(cust.Repos) == 0 {
|
||||
return fmt.Errorf("customer %q: repos list must not be empty", name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user