137 lines
4.5 KiB
Go
137 lines
4.5 KiB
Go
|
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||
|
|
// SPDX-License-Identifier: MIT
|
||
|
|
|
||
|
|
package actions
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"code.gitea.io/gitea/models/db"
|
||
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
||
|
|
user_model "code.gitea.io/gitea/models/user"
|
||
|
|
"code.gitea.io/gitea/modules/json"
|
||
|
|
"code.gitea.io/gitea/modules/timeutil"
|
||
|
|
"code.gitea.io/gitea/modules/util"
|
||
|
|
"xorm.io/builder"
|
||
|
|
)
|
||
|
|
|
||
|
|
// DebugSession represents a workflow debug session
|
||
|
|
type DebugSession struct {
|
||
|
|
ID int64 `xorm:"pk autoincr"`
|
||
|
|
RepoID int64 `xorm:"index"`
|
||
|
|
Repo *repo_model.Repository `xorm:"-"`
|
||
|
|
CreatorID int64 `xorm:"index"`
|
||
|
|
Creator *user_model.User `xorm:"-"`
|
||
|
|
WorkflowID string // workflow file name
|
||
|
|
WorkflowContent string `xorm:"LONGTEXT"` // edited workflow YAML content
|
||
|
|
Status string `xorm:"index"` // draft/running/success/failed/cancelled
|
||
|
|
RunID int64 `xorm:"-"` // the actual run ID when executed (0 if not run yet)
|
||
|
|
DebugParams string `xorm:"TEXT"` // JSON: {ref, event, inputs, env}
|
||
|
|
ErrorMsg string `xorm:"TEXT"`
|
||
|
|
CreatedUnix timeutil.TimeStamp `xorm:"created index"`
|
||
|
|
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||
|
|
ExpiresUnix timeutil.TimeStamp // auto cleanup after expiration
|
||
|
|
}
|
||
|
|
|
||
|
|
// TableName sets the table name
|
||
|
|
func (DebugSession) TableName() string {
|
||
|
|
return "action_debug_session"
|
||
|
|
}
|
||
|
|
|
||
|
|
func init() {
|
||
|
|
db.RegisterModel(new(DebugSession))
|
||
|
|
}
|
||
|
|
|
||
|
|
// DebugSessionStatus represents the possible statuses of a debug session
|
||
|
|
const (
|
||
|
|
DebugSessionStatusDraft = "draft"
|
||
|
|
DebugSessionStatusRunning = "running"
|
||
|
|
DebugSessionStatusSuccess = "success"
|
||
|
|
DebugSessionStatusFailed = "failed"
|
||
|
|
DebugSessionStatusCancelled = "cancelled"
|
||
|
|
)
|
||
|
|
|
||
|
|
// CreateDebugSession creates a new debug session
|
||
|
|
func CreateDebugSession(ctx context.Context, session *DebugSession) error {
|
||
|
|
session.Status = DebugSessionStatusDraft
|
||
|
|
session.CreatedUnix = timeutil.TimeStampNow()
|
||
|
|
session.UpdatedUnix = timeutil.TimeStampNow()
|
||
|
|
session.ExpiresUnix = timeutil.TimeStampNow().AddDuration(time.Hour * 24) // expire in 24 hours
|
||
|
|
_, err := db.GetEngine(ctx).Insert(session)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetDebugSession gets a debug session by ID
|
||
|
|
func GetDebugSession(ctx context.Context, id int64) (*DebugSession, error) {
|
||
|
|
session := &DebugSession{}
|
||
|
|
has, err := db.GetEngine(ctx).ID(id).Get(session)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if !has {
|
||
|
|
return nil, fmt.Errorf("debug session with id %d: %w", id, util.ErrNotExist)
|
||
|
|
}
|
||
|
|
return session, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// UpdateDebugSession updates a debug session
|
||
|
|
func UpdateDebugSession(ctx context.Context, session *DebugSession) error {
|
||
|
|
session.UpdatedUnix = timeutil.TimeStampNow()
|
||
|
|
_, err := db.GetEngine(ctx).ID(session.ID).Update(session)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
// ListDebugSessions lists debug sessions for a repository
|
||
|
|
func ListDebugSessions(ctx context.Context, repoID int64) ([]*DebugSession, error) {
|
||
|
|
var sessions []*DebugSession
|
||
|
|
err := db.GetEngine(ctx).
|
||
|
|
Where("repo_id = ?", repoID).
|
||
|
|
Where("status != ?", DebugSessionStatusCancelled).
|
||
|
|
OrderBy("created_unix DESC").
|
||
|
|
Find(&sessions)
|
||
|
|
return sessions, err
|
||
|
|
}
|
||
|
|
|
||
|
|
// DeleteDebugSession deletes a debug session
|
||
|
|
func DeleteDebugSession(ctx context.Context, id int64) error {
|
||
|
|
_, err := db.GetEngine(ctx).ID(id).Delete(&DebugSession{})
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
// CleanupExpiredDebugSessions cleans up expired debug sessions
|
||
|
|
func CleanupExpiredDebugSessions(ctx context.Context) error {
|
||
|
|
now := timeutil.TimeStampNow()
|
||
|
|
_, err := db.GetEngine(ctx).Where(builder.Lt{"expires_unix": now}).Delete(&DebugSession{})
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
// DebugParams represents the parameters for a debug session
|
||
|
|
type DebugParams struct {
|
||
|
|
Ref string `json:"ref"` // branch/tag
|
||
|
|
Event string `json:"event"` // push/pull_request/etc
|
||
|
|
Inputs map[string]string `json:"inputs"` // workflow inputs
|
||
|
|
Env map[string]string `json:"env"` // environment variables
|
||
|
|
}
|
||
|
|
|
||
|
|
// ParseDebugParams parses the JSON debug params
|
||
|
|
func (s *DebugSession) ParseDebugParams() (*DebugParams, error) {
|
||
|
|
params := &DebugParams{}
|
||
|
|
if s.DebugParams == "" {
|
||
|
|
return params, nil
|
||
|
|
}
|
||
|
|
err := json.Unmarshal([]byte(s.DebugParams), params)
|
||
|
|
return params, err
|
||
|
|
}
|
||
|
|
|
||
|
|
// SetDebugParams sets the debug params from a struct
|
||
|
|
func (s *DebugSession) SetDebugParams(params *DebugParams) error {
|
||
|
|
data, err := json.Marshal(params)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
s.DebugParams = string(data)
|
||
|
|
return nil
|
||
|
|
}
|