diff --git a/services/context/repo.go b/services/context/repo.go index c3fe8cffc4..fbe8178bd6 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -12,6 +12,7 @@ import ( "net/http" "net/url" "path" + "strconv" "strings" "code.gitea.io/gitea/models/db" @@ -396,7 +397,27 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) { return } ctx.Data["Permission"] = &ctx.Repo.Permission - ctx.Data["AllowCreateDevcontainer"] = ctx.Doer.AllowCreateDevcontainer + if ctx.Doer != nil { + ctx.Data["AllowCreateDevcontainer"] = ctx.Doer.AllowCreateDevcontainer + } else { + query := ctx.Req.URL.Query() + userID := query.Get("user") + userNum, err := strconv.ParseInt(userID, 10, 64) + if err != nil { + return + } + u, err := user_model.GetUserByID(ctx, userNum) + if err != nil { + if user_model.IsErrUserNotExist(err) { + ctx.Redirect(setting.AppSubURL + "/-/admin/users") + } else { + ctx.ServerError("GetUserByID", err) + } + return + } + ctx.Data["AllowCreateDevcontainer"] = u.AllowCreateDevcontainer + } + if repo.IsMirror { pullMirror, err := repo_model.GetMirrorByRepoID(ctx, repo.ID) if err == nil { diff --git a/services/devcontainer/devcontainer.go b/services/devcontainer/devcontainer.go index 6050ded27c..900df9dce8 100644 --- a/services/devcontainer/devcontainer.go +++ b/services/devcontainer/devcontainer.go @@ -305,12 +305,13 @@ func CreateDevContainer(ctx context.Context, repo *repo.Repository, doer *user.U if setting.K8sConfig.Enable { //k8s的逻辑 } else { - if isWebTerminal { - CreateDevContainerByDockerCommand(otherCtx, &newDevcontainer, repo, publicKeyList) - } else { - CreateDevContainerByDockerAPI(otherCtx, &newDevcontainer, repo, publicKeyList) + imageName, err := CreateDevContainerByDockerCommand(otherCtx, &newDevcontainer, repo, publicKeyList) + if err != nil { + return + } + if !isWebTerminal { + CreateDevContainerByDockerAPI(otherCtx, &newDevcontainer, imageName, repo, publicKeyList) } - } }() return nil diff --git a/services/devcontainer/docker_agent.go b/services/devcontainer/docker_agent.go index ae5268eb48..22bfba2731 100644 --- a/services/devcontainer/docker_agent.go +++ b/services/devcontainer/docker_agent.go @@ -41,7 +41,7 @@ func GetDevContainerStatusFromDocker(ctx context.Context, containerName string) } return containerStatus, nil } -func CreateDevContainerByDockerAPI(ctx context.Context, newDevcontainer *devcontainer_models.Devcontainer, repo *repo.Repository, publicKeyList []string) error { +func CreateDevContainerByDockerAPI(ctx context.Context, newDevcontainer *devcontainer_models.Devcontainer, imageName string, repo *repo.Repository, publicKeyList []string) error { dbEngine := db.GetEngine(ctx) configurationString, err := GetDevcontainerConfigurationString(ctx, repo) if err != nil { @@ -51,8 +51,6 @@ func CreateDevContainerByDockerAPI(ctx context.Context, newDevcontainer *devcont if err != nil { return err } - - var imageName = configurationModel.Image dockerSocket, err := docker_module.GetDockerSocketPath() if err != nil { return err @@ -75,48 +73,6 @@ func CreateDevContainerByDockerAPI(ctx context.Context, newDevcontainer *devcont if err != nil { return err } - } else { - dockerfileContent, err := GetFileContentByPath(ctx, repo, ".devcontainer/"+configurationModel.Build.Dockerfile) - if err != nil { - return err - } - // 创建构建上下文(包含Dockerfile的tar包) - var buf bytes.Buffer - tw := tar.NewWriter(&buf) - defer tw.Close() - // 添加Dockerfile到tar包 - dockerfile := "Dockerfile" - content := []byte(dockerfileContent) - header := &tar.Header{ - Name: dockerfile, - Size: int64(len(content)), - Mode: 0644, - } - if err := tw.WriteHeader(header); err != nil { - return err - } - if _, err := tw.Write(content); err != nil { - return err - } - // 执行镜像构建 - imageName = fmt.Sprintf("%d", newDevcontainer.UserId) + "-" + fmt.Sprintf("%d", newDevcontainer.RepoId) + "-dockerfile" - buildOptions := types.ImageBuildOptions{ - Tags: []string{imageName}, // 镜像标签 - } - - buildResponse, err := cli.ImageBuild( - context.Background(), - &buf, - buildOptions, - ) - if err != nil { - return err - } - output, err := io.ReadAll(buildResponse.Body) - if err != nil { - return err - } - log.Info(string(output)) } _, err = dbEngine.Table("devcontainer"). @@ -161,26 +117,26 @@ func CreateDevContainerByDockerAPI(ctx context.Context, newDevcontainer *devcont return nil } -func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *devcontainer_models.Devcontainer, repo *repo.Repository, publicKeyList []string) error { +func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *devcontainer_models.Devcontainer, repo *repo.Repository, publicKeyList []string) (string, error) { dbEngine := db.GetEngine(ctx) configurationString, err := GetDevcontainerConfigurationString(ctx, repo) if err != nil { - return err + return "", err } configurationModel, err := UnmarshalDevcontainerConfigContent(configurationString) if err != nil { - return err + return "", err } var imageName = configurationModel.Image dockerSocket, err := docker_module.GetDockerSocketPath() if err != nil { - return err + return "", err } if configurationModel.Build != nil && configurationModel.Build.Dockerfile != "" { dockerfileContent, err := GetFileContentByPath(ctx, repo, ".devcontainer/"+configurationModel.Build.Dockerfile) if err != nil { - return err + return "", err } // 创建构建上下文(包含Dockerfile的tar包) var buf bytes.Buffer @@ -195,10 +151,10 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev Mode: 0644, } if err := tw.WriteHeader(header); err != nil { - return err + return "", err } if _, err := tw.Write(content); err != nil { - return err + return "", err } // 执行镜像构建 imageName = fmt.Sprintf("%d", newDevcontainer.UserId) + "-" + fmt.Sprintf("%d", newDevcontainer.RepoId) + "-dockerfile" @@ -207,7 +163,7 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev } cli, err := docker_module.CreateDockerClient(ctx) if err != nil { - return err + return "", err } buildResponse, err := cli.ImageBuild( context.Background(), @@ -215,11 +171,11 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev buildOptions, ) if err != nil { - return err + return "", err } output, err := io.ReadAll(buildResponse.Body) if err != nil { - return err + return "", err } log.Info(string(output)) @@ -236,11 +192,11 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev DevcontainerId: newDevcontainer.Id, }); err != nil { log.Info("Failed to insert record: %v", err) - return err + return imageName, err } cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf) if err != nil { - return err + return imageName, err } var startCommand string = `docker -H ` + dockerSocket + ` run -d --name ` + newDevcontainer.Name @@ -299,7 +255,7 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev DevcontainerId: newDevcontainer.Id, }); err != nil { log.Info("Failed to insert record: %v", err) - return err + return imageName, err } //安装基本工具的命令 onCreateCommand := strings.TrimSpace(strings.Join(configurationModel.ParseCommand(configurationModel.OnCreateCommand), ";")) @@ -320,7 +276,7 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev DevcontainerId: newDevcontainer.Id, }); err != nil { log.Info("Failed to insert record: %v", err) - return err + return imageName, err } //连接容器的命令 if _, err := dbEngine.Table("devcontainer_output").Insert(&devcontainer_models.DevcontainerOutput{ @@ -333,9 +289,9 @@ func CreateDevContainerByDockerCommand(ctx context.Context, newDevcontainer *dev DevcontainerId: newDevcontainer.Id, }); err != nil { log.Info("Failed to insert record: %v", err) - return err + return imageName, err } - return nil + return imageName, nil } func IsContainerNotFound(ctx context.Context, containerName string) (bool, error) { cli, err := docker_module.CreateDockerClient(ctx)