Files
devstar/models/devcontainer/devcontainer.go

157 lines
6.8 KiB
Go
Raw Normal View History

package devcontainer
import (
"context"
"encoding/json"
"io"
"net/http"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
)
type Devcontainer struct {
Id int64 `xorm:"BIGINT pk NOT NULL autoincr 'id' comment('主键devContainerId')"`
Name string `xorm:"VARCHAR(64) charset=utf8mb4 collate=utf8mb4_bin UNIQUE NOT NULL 'name' comment('devContainer名称自动生成')"`
DevcontainerHost string `xorm:"VARCHAR(256) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'devcontainer_host' comment('SSH Host')"`
DevcontainerPort uint16 `xorm:"SMALLINT UNSIGNED NOT NULL 'devcontainer_port' comment('SSH Port')"`
DevcontainerStatus uint16 `xorm:"SMALLINT UNSIGNED NOT NULL 'devcontainer_status' comment('SSH Status')"`
DevcontainerUsername string `xorm:"VARCHAR(32) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'devcontainer_username' comment('SSH Username')"`
DevcontainerWorkDir string `xorm:"VARCHAR(256) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'devcontainer_work_dir' comment('SSH 工作路径,典型值 ~/${project_name}256字节以内')"`
RepoId int64 `xorm:"BIGINT NOT NULL FK('repo_id') REFERENCES repository(id) ON DELETE CASCADE 'repo_id' comment('repository表主键')"`
UserId int64 `xorm:"BIGINT NOT NULL FK('user_id') REFERENCES user(id) ON DELETE CASCADE 'user_id' comment('user表主键')"`
CreatedUnix int64 `xorm:"BIGINT 'created_unix' comment('创建时间戳')"`
UpdatedUnix int64 `xorm:"BIGINT 'updated_unix' comment('更新时间戳')"`
}
type DevcontainerOutput struct {
Id int64 `xorm:"BIGINT pk NOT NULL autoincr 'id' comment('主键devContainerId')"`
RepoId int64 `xorm:"BIGINT NOT NULL unique(uniquename) 'repo_id' comment('repository表主键')"`
UserId int64 `xorm:"BIGINT NOT NULL unique(uniquename) 'user_id' comment('user表主键')"`
Status string `xorm:"VARCHAR(255) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'status' comment('status')"`
Output string `xorm:"TEXT 'output' comment('output')"`
Command string `xorm:"TEXT 'command' comment('command')"`
ListId int64 `xorm:"BIGINT NOT NULL unique(uniquename) 'list_id' comment('list_id')"`
DevcontainerId int64 `xorm:"BIGINT NOT NULL FK('devcontainer_id') REFERENCES devcontainer(id) ON DELETE CASCADE 'devcontainer_id' comment('devcontainer表主键')"`
}
type DevcontainerScript struct {
Id int64 `xorm:"BIGINT pk NOT NULL autoincr 'id' comment('主键devContainerId')"`
RepoId int64 `xorm:"BIGINT NOT NULL 'repo_id' comment('repository表主键')"`
UserId int64 `xorm:"BIGINT NOT NULL 'user_id' comment('user表主键')"`
VariableName string `xorm:"NOT NULL 'variable_name' comment('user表主键')"`
}
func init() {
db.RegisterModel(new(Devcontainer))
db.RegisterModel(new(DevcontainerScript))
db.RegisterModel(new(DevcontainerOutput))
}
func GetScript(ctx context.Context, userId, repoID int64) (map[string]string, error) {
variables := make(map[string]string)
var devstarVariables []*DevcontainerVariable
var name []string
// Devstar level
// 从远程获取Devstar变量
client := &http.Client{}
req, err := http.NewRequest("GET", "http://devstar.cn/variables/export", nil)
if err != nil {
log.Error("Failed to create request for devstar variables: %v", err)
} else {
resp, err := client.Do(req)
if err != nil {
log.Error("Failed to fetch devstar variables: %v", err)
} else {
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Error("Failed to read devstar variables response: %v", err)
} else {
err = json.Unmarshal(body, &devstarVariables)
if err != nil {
log.Error("Failed to unmarshal devstar variables: %v", err)
}
}
}
}
// Global
err = db.GetEngine(ctx).
Select("variable_name").
Table("devcontainer_script").
Where("user_id = ? AND repo_id = ?", 0, 0).
Find(&name)
globalVariables, err := db.Find[DevcontainerVariable](ctx, FindVariablesOpts{})
if err != nil {
log.Error("find global variables: %v", err)
return nil, err
}
// 过滤出name在variableNames中的变量
globalVariables = append(devstarVariables, globalVariables...)
var filteredGlobalVars []*DevcontainerVariable
for _, v := range globalVariables {
if contains(name, v.Name) {
filteredGlobalVars = append(filteredGlobalVars, v)
}
}
// Org / User level
err = db.GetEngine(ctx).
Select("variable_name").
Table("devcontainer_script").
Where("user_id = ? AND repo_id = ?", userId, 0).
Find(&name)
ownerVariables, err := db.Find[DevcontainerVariable](ctx, FindVariablesOpts{OwnerID: userId})
if err != nil {
log.Error("find variables of org: %d, error: %v", userId, err)
return nil, err
}
// 过滤出name在variableNames中的变量
ownerVariables = append(devstarVariables, ownerVariables...)
var filteredOwnerVars []*DevcontainerVariable
for _, v := range ownerVariables {
if contains(name, v.Name) {
filteredOwnerVars = append(filteredOwnerVars, v)
}
}
// Repo level
err = db.GetEngine(ctx).
Select("variable_name").
Table("devcontainer_script").
Where("repo_id = ?", repoID).
Find(&name)
repoVariables, err := db.Find[DevcontainerVariable](ctx, FindVariablesOpts{RepoID: repoID})
if err != nil {
log.Error("find variables of repo: %d, error: %v", repoID, err)
return nil, err
}
// 过滤出name在variableNames中的变量
repoVariables = append(devstarVariables, repoVariables...)
var filteredRepoVars []*DevcontainerVariable
for _, v := range repoVariables {
if contains(name, v.Name) {
filteredRepoVars = append(filteredRepoVars, v)
}
}
// Level precedence: Org / User > Repo > Global
for _, v := range append(filteredGlobalVars, append(filteredRepoVars, filteredOwnerVars...)...) {
variables[v.Name] = v.Data
}
return variables, nil
}
// contains 检查字符串切片中是否包含指定的字符串
func contains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}