From 6925a7a132ab4e4b2ade85b6705fa4074dcb68b4 Mon Sep 17 00:00:00 2001 From: Oliver Braun Date: Mon, 11 Sep 2023 14:54:13 +0200 Subject: [PATCH] add update command --- cmd/update.go | 33 +++++++++++ gitlab/generate.go | 2 +- gitlab/update.go | 133 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 cmd/update.go create mode 100644 gitlab/update.go diff --git a/cmd/update.go b/cmd/update.go new file mode 100644 index 0000000..e4683d0 --- /dev/null +++ b/cmd/update.go @@ -0,0 +1,33 @@ +package cmd + +import ( + "fmt" + + "github.com/logrusorgru/aurora/v4" + "github.com/obcode/glabs/config" + "github.com/obcode/glabs/gitlab" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(updateCmd) +} + +var updateCmd = &cobra.Command{ + Use: "update course assignment [groups...|students...]", + Short: "Update repositories with code.", + Long: `Update repositories with code from the startercode repo. + USE WITH CARE! + This can result in merge conflicts, which cannot be handled + Use only with fresh, i.e. untouched, repositories.`, + Args: cobra.MinimumNArgs(2), //nolint:gomnd + Run: func(cmd *cobra.Command, args []string) { + assignmentConfig := config.GetAssignmentConfig(args[0], args[1], args[2:]...) + assignmentConfig.Show() + fmt.Println(aurora.Red("Heads up! Use only with untouched projects.")) + fmt.Println(aurora.Magenta("Config okay? Press 'Enter' to continue or 'Ctrl-C' to stop ...")) + fmt.Scanln() + c := gitlab.NewClient() + c.Update(assignmentConfig) + }, +} diff --git a/gitlab/generate.go b/gitlab/generate.go index 44c4ba8..aa84033 100644 --- a/gitlab/generate.go +++ b/gitlab/generate.go @@ -159,7 +159,7 @@ func (c *Client) generate(assignmentCfg *config.AssignmentConfig, assignmentGrou func (c *Client) generatePerStudent(assignmentCfg *config.AssignmentConfig, assignmentGroupID int, starterrepo *git.Starterrepo) { if len(assignmentCfg.Students) == 0 { - fmt.Println("no students in config for assignment found") + log.Info().Str("group", assignmentCfg.Course).Msg("no students found") return } diff --git a/gitlab/update.go b/gitlab/update.go new file mode 100644 index 0000000..682786d --- /dev/null +++ b/gitlab/update.go @@ -0,0 +1,133 @@ +package gitlab + +import ( + "fmt" + "os" + "time" + + "github.com/logrusorgru/aurora" + "github.com/obcode/glabs/config" + "github.com/obcode/glabs/git" + "github.com/rs/zerolog/log" + "github.com/theckman/yacspin" + "github.com/xanzy/go-gitlab" +) + +func (c *Client) Update(assignmentCfg *config.AssignmentConfig) { + assignmentGitLabGroupID, err := c.getGroupID(assignmentCfg) + if err != nil { + fmt.Printf("error: GitLab group for assignment does not exist, please create the group %s\n", assignmentCfg.URL) + os.Exit(1) + } + + var starterrepo *git.Starterrepo + + if assignmentCfg.Startercode != nil { + starterrepo, err = git.PrepareStartercodeRepo(assignmentCfg) + + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } + + switch per := assignmentCfg.Per; per { + case config.PerGroup: + c.updatePerGroup(assignmentCfg, assignmentGitLabGroupID, starterrepo) + case config.PerStudent: + c.updatePerStudent(assignmentCfg, assignmentGitLabGroupID, starterrepo) + default: + fmt.Printf("it is only possible to update for students oder groups, not for %v", per) + os.Exit(1) + } +} + +func (c *Client) update(assignmentCfg *config.AssignmentConfig, project *gitlab.Project, starterrepo *git.Starterrepo) { + + cfg := yacspin.Config{ + Frequency: 100 * time.Millisecond, + CharSet: yacspin.CharSets[69], + Suffix: aurora.Sprintf(aurora.Cyan(" updating project %s at %s"), + aurora.Yellow(project.Name), + aurora.Magenta(assignmentCfg.URL+"/"+project.Name), + ), + SuffixAutoColon: true, + StopCharacter: "✓", + StopColors: []string{"fgGreen"}, + StopFailMessage: "error", + StopFailCharacter: "✗", + StopFailColors: []string{"fgRed"}, + } + + spinner, err := yacspin.New(cfg) + if err != nil { + log.Debug().Err(err).Msg("cannot create spinner") + } + err = spinner.Start() + if err != nil { + log.Debug().Err(err).Msg("cannot start spinner") + } + + if starterrepo != nil { + cfg.Suffix = aurora.Sprintf(aurora.Cyan(" ↪ pushing updates from startercode")) + + err = c.pushStartercode(assignmentCfg, starterrepo, project) + if err != nil { + spinner.StopFailMessage(fmt.Sprintf("problem: %v", err)) + + err := spinner.StopFail() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + return + } + + err = spinner.Stop() + if err != nil { + log.Debug().Err(err).Msg("cannot stop spinner") + } + } +} + +func (c *Client) updatePerStudent(assignmentCfg *config.AssignmentConfig, assignmentGroupID int, + starterrepo *git.Starterrepo) { + if len(assignmentCfg.Students) == 0 { + log.Info().Str("group", assignmentCfg.Course).Msg("no students found") + return + } + + for _, student := range assignmentCfg.Students { + name := assignmentCfg.Name + "-" + assignmentCfg.RepoSuffix(student) + projectname := fmt.Sprintf("%s/%s", assignmentCfg.Path, name) + project, _, err := c.Projects.GetProject( + projectname, + &gitlab.GetProjectOptions{}, + ) + if err != nil { + fmt.Printf("cannot set access for project %s failed with %s", projectname, err) + return + } + c.update(assignmentCfg, project, starterrepo) + } +} + +func (c *Client) updatePerGroup(assignmentCfg *config.AssignmentConfig, assignmentGroupID int, + starterrepo *git.Starterrepo) { + if len(assignmentCfg.Groups) == 0 { + log.Info().Str("group", assignmentCfg.Course).Msg("no groups found") + return + } + + for _, grp := range assignmentCfg.Groups { + projectname := fmt.Sprintf("%s/%s-%s", assignmentCfg.Path, assignmentCfg.Name, grp.Name) + project, _, err := c.Projects.GetProject( + projectname, + &gitlab.GetProjectOptions{}, + ) + if err != nil { + fmt.Printf("cannot set access for project %s failed with %s", projectname, err) + return + } + c.update(assignmentCfg, project, starterrepo) + } +}