Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions api/internal/db/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@
// These settings balance performance with resource usage
db.SetMaxOpenConns(25) // Maximum number of open connections to the database
db.SetMaxIdleConns(5) // Maximum number of connections in the idle connection pool
db.SetConnMaxLifetime(5 * time.Minute) // Maximum amount of time a connection may be reused (5 minutes)

Check failure on line 188 in api/internal/db/database.go

View workflow job for this annotation

GitHub Actions / Go Dependency Vulnerability Scan (api)

undefined: time
db.SetConnMaxIdleTime(1 * time.Minute) // Maximum amount of time a connection may be idle (1 minute)

Check failure on line 189 in api/internal/db/database.go

View workflow job for this annotation

GitHub Actions / Go Dependency Vulnerability Scan (api)

undefined: time

// Test connection
if err := db.Ping(); err != nil {
Expand Down Expand Up @@ -1976,6 +1976,11 @@
return fmt.Errorf("failed to process password reset: %w", err)
}

// Ensure default template repository is configured
if err := d.ensureDefaultRepository(); err != nil {
return fmt.Errorf("failed to configure default repository: %w", err)
}

return nil
}

Expand Down Expand Up @@ -2096,3 +2101,66 @@

return nil
}

// ensureDefaultRepository ensures the official StreamSpace templates repository is configured.
// This hardcodes the default repository URL: https://github.com/JoshuaAFerguson/streamspace-templates
//
// The repository will be automatically synced by the sync service on startup.
//
// Behavior:
// - If repository already exists (by name or URL), skip insertion
// - If not exists, insert with status 'pending' to trigger sync
// - Does not fail if repository already configured
//
// Default repository configuration:
// - Name: "streamspace-templates"
// - URL: https://github.com/JoshuaAFerguson/streamspace-templates
// - Branch: main
// - Auth: none (public repository)
// - Status: pending (will be synced automatically)
func (d *Database) ensureDefaultRepository() error {
const (
defaultRepoName = "streamspace-templates"
defaultRepoURL = "https://github.com/JoshuaAFerguson/streamspace-templates"
defaultBranch = "main"
)

// Check if default repository already exists (by name or URL)
var existingID int
err := d.db.QueryRow(`
SELECT id FROM repositories
WHERE name = $1 OR url = $2
LIMIT 1
`, defaultRepoName, defaultRepoURL).Scan(&existingID)

// Repository already exists - skip
if err == nil {
log.Printf("✓ Default template repository '%s' already configured (ID: %d)", defaultRepoName, existingID)
return nil
}

// Error other than "not found" - report it
if err != sql.ErrNoRows {
return fmt.Errorf("failed to check existing repository: %w", err)
}

// Repository doesn't exist - insert it
log.Println("📦 Adding default template repository...")
log.Printf(" Name: %s", defaultRepoName)
log.Printf(" URL: %s", defaultRepoURL)
log.Printf(" Branch: %s", defaultBranch)

_, err = d.db.Exec(`
INSERT INTO repositories (name, url, branch, auth_type, status, created_at, updated_at)
VALUES ($1, $2, $3, 'none', 'pending', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
`, defaultRepoName, defaultRepoURL, defaultBranch)

if err != nil {
return fmt.Errorf("failed to insert default repository: %w", err)
}

log.Println("✓ Default template repository added successfully")
log.Println(" The repository will be synced automatically on startup")

return nil
}
14 changes: 8 additions & 6 deletions api/internal/sync/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
//
// Validation:
// - Required fields: name, displayName, baseImage
// - API version: stream.streamspace.io/v1alpha1
// - API version: stream.space/v1alpha1 (or stream.streamspace.io/v1alpha1 for backward compatibility)
// - App type inference: desktop (VNC) or webapp (HTTP)
//
// Example usage:
Expand Down Expand Up @@ -119,7 +119,7 @@ type ParsedTemplate struct {
//
// Example YAML:
//
// apiVersion: stream.streamspace.io/v1alpha1
// apiVersion: stream.space/v1alpha1
// kind: Template
// metadata:
// name: firefox-browser
Expand Down Expand Up @@ -293,8 +293,9 @@ func (p *TemplateParser) ParseTemplateFile(filePath string) (*ParsedTemplate, er
return nil, fmt.Errorf("not a Template resource (kind: %s)", manifest.Kind)
}

if manifest.APIVersion != "stream.streamspace.io/v1alpha1" {
return nil, fmt.Errorf("unsupported API version: %s", manifest.APIVersion)
// Support both old and new API versions for backward compatibility
if manifest.APIVersion != "stream.space/v1alpha1" && manifest.APIVersion != "stream.streamspace.io/v1alpha1" {
return nil, fmt.Errorf("unsupported API version: %s (expected stream.space/v1alpha1)", manifest.APIVersion)
}

// Validate required fields
Expand Down Expand Up @@ -406,8 +407,9 @@ func (p *TemplateParser) ValidateTemplateManifest(yamlContent string) error {
return fmt.Errorf("kind must be 'Template', got '%s'", manifest.Kind)
}

if manifest.APIVersion != "stream.streamspace.io/v1alpha1" {
return fmt.Errorf("apiVersion must be 'stream.streamspace.io/v1alpha1', got '%s'", manifest.APIVersion)
// Support both old and new API versions
if manifest.APIVersion != "stream.space/v1alpha1" && manifest.APIVersion != "stream.streamspace.io/v1alpha1" {
return fmt.Errorf("apiVersion must be 'stream.space/v1alpha1', got '%s'", manifest.APIVersion)
}

if manifest.Metadata.Name == "" {
Expand Down
Loading