Themelio compatibility reference. This page describes the retained Themelio implementation or its historical design. Check the parallel-operation guide before applying it to the current platform.
ADR-0013: actions.yaml Automation System
Status: Proposed
Date: 2026-06-03
Deciders: TBD
Relates to: ADR-0012 (Job and Deployment Management System) — actions.yaml builds on the PostgreSQL persistence layer
Context
Themelio users need a way to define reusable, parameterized computational workflows directly in their repositories. Currently, creating jobs or deployments requires manual API calls for each operation, which prevents users from packaging, sharing, and automating common computational patterns.
Without repository-scoped automation, users cannot:
- Define custom workflows that others can reuse
- Parameterize operations for different use cases
- Embed computational setup alongside code and data
- Provide self-service automation for repository consumers
ADR-0012 provides the PostgreSQL-based persistence layer for jobs and deployments. This ADR builds on that foundation by introducing a declarative YAML format for defining automated actions.
Current Problems
The absence of a repository-scoped automation system creates several problems:
-
No Declarative Automation: Users cannot define computational workflows in their repositories. Every job or deployment must be created manually through API calls or UI interactions.
-
No Custom Workflows: Repository maintainers cannot package common computational patterns (e.g., "train this model with these parameters") for others to use.
-
No Reusable Action Patterns: Each operation must be configured from scratch. There is no way to share or reuse action definitions across repositories or teams.
-
No UI-Guided Setup: Creating deployable models or spaces requires manual
actions.yamlcreation. There is no guided UI flow to automatically generate appropriate action configurations for supported model types (e.g., KServe for inference) or space types (e.g., Gradio for apps).
Requirements
An actions.yaml system must satisfy the following requirements:
-
Repository-Scoped Definition: Actions must be definable within a GitLab repository via a YAML file (
actions.yaml) that lives alongside code and data. -
Parameter Substitution: Actions must support parameterization using a
$parameterNamesyntax so users can provide runtime values. -
Multiple Action Types: The system must support at least three action types:
slurm-job: Execute scripts on an external SLURM cluster via SSHk8s-deployment: Deploy long-running services on Kubernetesk8s-inferenceservice: Deploy ML inference services via KServe
-
Web UI Integration: The web service must provide UI components for:
- Discovering available actions in a repository
- Displaying action parameters with appropriate input fields
- Executing actions with user-provided parameter values
-
UI-Guided Creation: For supported model and space types, the UI must guide users through automatic
actions.yamlgeneration:- Models: When creating a new model with KServe support, automatically generate a
k8s-inferenceserviceaction - Spaces: When creating a new space of a supported type (e.g., "gradio"), automatically generate a
k8s-deploymentaction
- Models: When creating a new model with KServe support, automatically generate a
-
ADR-0012 Integration: All actions must integrate with the PostgreSQL-based persistence layer described in ADR-0012 for job/deployment tracking and history.
-
Quota Enforcement: Resources created by actions must be isolated and quota-enforced:
- Kubernetes resources: Created in the k8s namespace linked to the Themelio project that the user is a member of
- SLURM resources: Created under the corresponding SLURM account associated with the user's project
- This leverages existing quota mechanisms at the namespace/account level
Decision Drivers
- User Empowerment: Repository maintainers should be able to define self-service automation without requiring operator intervention.
- Reusability: Common computational patterns should be definable once and reused across many repositories.
- Integration: The system must build on ADR-0012's persistence layer without requiring architectural changes.
- Security: User-provided YAML must be validated and sandboxed to prevent security vulnerabilities.
- Simplicity: The YAML format should be simple enough for non-experts while powerful enough for complex workflows.
Considered Options
Option A: actions.yaml with Multiple Action Types
Introduce a actions.yaml file that repository maintainers can create at the root of their GitLab repositories. This file defines one or more actions that users can execute through the web UI.
Architecture:
- YAML Format: Actions are defined in
actions.yamlwith the following structure:
-
Web Service Integration:
ResourceActionscomponent displays available actions in a dropdown menu- For each action, render parameter input fields based on the YAML definition
- Submit action requests to
POST /api/repos/[namespace]/[repo]/action/[branch]with parameter values
-
k8s-root-actor Execution:
- Accept action execution requests from the web service
- Parse
actions.yamlfrom the GitLab repository - Substitute
$parameterNameplaceholders with user-provided values - Route to appropriate handler based on action type:
slurm-job: Create Kubernetes Job that SSHs to SLURM clusterk8s-deployment: Create Kubernetes Deployment with Service and VirtualServicek8s-inferenceservice: Create KServe InferenceService
- Create job/deployment records in PostgreSQL per ADR-0012
-
Template System:
- Use Handlebars templates for Kubernetes manifest generation
- Support YAML references via
#/references/syntax for reusable configurations - Support nested references (references within references) for complex configurations
- Templates stored in
k8s-root-actor/src/templates/
-
Persistence:
- All actions create job/deployment records in PostgreSQL via ADR-0012's schema
- Job/deployment status tracked through ADR-0012's polling mechanism
- Destroy actions update records to "destroyed" status and clean up Kubernetes resources
Data Flow:
Action Execution:
- User navigates to repository in web UI
- Web service fetches
actions.yamlfrom GitLab repository ResourceActionscomponent parses YAML and displays available actions- User selects action and provides parameter values
- Web service calls
k8s-root-actorwith action name and parameters k8s-root-actorfetchesactions.yaml, validates action existsk8s-root-actorsubstitutes parameters and creates Kubernetes resourcesk8s-root-actorcreates job/deployment record in PostgreSQL- User monitors progress through web UI (polling via ADR-0012 endpoints)
Resource Destruction:
- User views job/deployment list for a repository in web UI
- User clicks "destroy" button on a specific job or deployment
- Web service calls ADR-0012's destroy endpoint
- k8s-root-actor deletes corresponding Kubernetes/SLURM resources
- PostgreSQL record updated to "destroyed" status
UI-Guided Creation:
- User creates a new model or space through web UI
- If the model/space type is supported (KServe for models, Gradio for spaces), UI prompts to auto-generate
actions.yaml - User confirms, web service commits appropriate action configuration to the repository
- User can immediately execute the action or modify it manually
Pros:
- User Empowerment: Repository maintainers can define self-service automation without operator intervention
- Reusability: Action definitions can be versioned, forked, and shared like code
- Flexibility: Parameter substitution allows a single action to serve many use cases
- Integration: Builds cleanly on ADR-0012's PostgreSQL persistence layer
- Declarative: YAML format is simple, readable, and familiar to DevOps practitioners
- UI-Guided Setup: Automatic
actions.yamlgeneration for supported model/space types reduces manual configuration - Destroy Support: Per-resource-type destroy functionality accessible via job/deployment list UI
Cons:
- Security Surface Area: User-provided YAML scripts execute in Kubernetes pods with access to cluster resources
- Complexity: Three action types (slurm-job, k8s-deployment, k8s-inferenceservice) with different execution paths increase implementation and maintenance burden
- Validation Challenges: YAML syntax errors, missing parameters, or invalid action types must be caught and communicated clearly
- Resource Limits: Users may create actions that consume excessive resources (CPUs, GPUs, memory), though quota enforcement at the project namespace/SLURM account level provides some protection
- GitLab Token Scope: Actions require GitLab API access with appropriate scopes to fetch repository files
- Learning Curve: Users must learn the action YAML syntax and parameter substitution patterns
- UI Complexity: Guided creation flows for different model/space types increase UI development effort
Decision
We will implement Option A: the actions.yaml automation system with multiple action types.
This approach provides the best balance of user empowerment, reusability, and integration with the existing ADR-0012 architecture. The declarative YAML format allows repository maintainers to define self-service automation while the parameter substitution system enables flexible runtime configuration.
The UI-guided creation for supported model and space types (KServe for models, Gradio for spaces) reduces manual configuration burden and improves user experience. Destroy functionality is provided per resource type through the job/deployment list UI, leveraging ADR-0012's existing destroy endpoints.
See also: DD-0013: Implementation details
Consequences
Positive:
- Repository maintainers can define self-service automation without requiring operator intervention for each action
- Action definitions are versioned alongside code, enabling reproducible computational workflows
- Parameter substitution allows a single action definition to serve many use cases
- Clean integration with ADR-0012's PostgreSQL persistence layer ensures job/deployment history and auditability
- UI-guided creation for supported types (KServe models, Gradio spaces) reduces manual configuration
- Destroy functionality accessible via job/deployment list UI enables full lifecycle management
- Reusable action patterns can be shared across repositories and teams
Negative:
- Increased security surface area: user-provided scripts execute in Kubernetes pods with cluster access
- Implementation complexity: three action types with different execution paths require careful testing and maintenance
- YAML syntax errors and validation failures create a new category of user-facing errors
- Resource exhaustion risk: users may define actions that consume excessive cluster resources
- Operational burden: operators must monitor action execution and handle failures gracefully
- Additional infrastructure: Handlebars template compilation and reference resolution add runtime complexity
- UI development effort: guided creation flows for different model/space types increase frontend complexity
Neutral:
- Actions are stored in GitLab repositories alongside code, leveraging existing access control and versioning
- Web service acts as a passthrough for action execution, delegating logic to k8s-root-actor
- Job/deployment records in PostgreSQL are owned solely by k8s-root-actor, maintaining ADR-0012's single-owner pattern
- The system does not introduce new databases or storage mechanisms beyond ADR-0012's PostgreSQL schema
References
- ADR-0012: Job and Deployment Management System — PostgreSQL persistence layer for jobs and deployments
- Kubernetes API Documentation — Kubernetes resource types and APIs
- SLURM Documentation — SLURM workload manager reference
- KServe InferenceService CRD — KServe InferenceService specification
- Handlebars.js — Template engine for Kubernetes manifest generation
Page source
Source snapshot · Revision f928834c8.