github.com/zaquestion/lab@v0.25.1/cmd/project_create.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/MakeNowJust/heredoc/v2"
     8  	"github.com/spf13/cobra"
     9  	"github.com/xanzy/go-gitlab"
    10  	"github.com/zaquestion/lab/internal/git"
    11  	lab "github.com/zaquestion/lab/internal/gitlab"
    12  )
    13  
    14  // projectCreateCmd represents the create command
    15  var projectCreateCmd = &cobra.Command{
    16  	Use:   "create [path]",
    17  	Short: "Create a new project on GitLab",
    18  	Long: heredoc.Doc(`
    19  		Create a new project on GitLab.
    20  
    21  		"path" refers to the path on GitLab not including the group/namespace.
    22  		If no path or name is provided and the current directory is a git repo,
    23  		the name of the	current working directory will be used.`),
    24  	Example: heredoc.Doc(`
    25  		lab project create myproject
    26  		lab project create myproject -n "new proj"
    27  		lab project create myproject -r myupstream
    28  		lab project create -g mygroup myproject
    29  		lab project create mygroup/myproject -n "new proj"
    30  		lab project create myproject --http
    31  		lab project create myproject --internal
    32  		lab project create myproject --private
    33  		lab project create myproject --public`),
    34  	Args:             cobra.MaximumNArgs(1),
    35  	PersistentPreRun: labPersistentPreRun,
    36  	Run: func(cmd *cobra.Command, args []string) {
    37  		var (
    38  			name, _   = cmd.Flags().GetString("name")
    39  			desc, _   = cmd.Flags().GetString("description")
    40  			group, _  = cmd.Flags().GetString("group")
    41  			remote, _ = cmd.Flags().GetString("remote")
    42  		)
    43  
    44  		g, path := determineNamespacePath(args, name)
    45  		if path == "" && name == "" {
    46  			log.Fatal("path or name must be set")
    47  		}
    48  		if g != "" && group != "" {
    49  			log.Fatalf("group can be passed by flag or in path, but not both\n%s", labUsageFormat(cmd))
    50  		}
    51  		if g != "" {
    52  			group = g
    53  		}
    54  
    55  		var namespaceID *int
    56  		if group != "" {
    57  			groupObj, err := lab.GroupSearch(group)
    58  			if err != nil {
    59  				log.Fatal(err)
    60  			}
    61  			namespaceID = &groupObj.ID
    62  		}
    63  
    64  		// set the default visibility
    65  		visibility := gitlab.PrivateVisibility
    66  
    67  		// now override the visibility if the user passed in relevant flags. if
    68  		// the user passes multiple flags, this will use the "most private"
    69  		// option given, ignoring the rest
    70  		switch {
    71  		case private:
    72  			visibility = gitlab.PrivateVisibility
    73  		case internal:
    74  			visibility = gitlab.InternalVisibility
    75  		case public:
    76  			visibility = gitlab.PublicVisibility
    77  		}
    78  
    79  		opts := gitlab.CreateProjectOptions{
    80  			// if namespaceID is nil, the project will be created in user's
    81  			// namespace
    82  			NamespaceID:          namespaceID,
    83  			Path:                 gitlab.String(path),
    84  			Name:                 gitlab.String(name),
    85  			Description:          gitlab.String(desc),
    86  			Visibility:           &visibility,
    87  			ApprovalsBeforeMerge: gitlab.Int(0),
    88  		}
    89  		p, err := lab.ProjectCreate(&opts)
    90  		if err != nil {
    91  			log.Fatal(err)
    92  		}
    93  
    94  		if remote != "" {
    95  			if git.InsideGitRepo() {
    96  				urlToRepo := labURLToRepo(p)
    97  				err = git.RemoteAdd(remote, urlToRepo, ".")
    98  				if err != nil {
    99  					log.Fatal(err)
   100  				}
   101  			} else {
   102  				log.Warnf("outside of a git repo. remote '%s' not added\n", remote)
   103  			}
   104  		}
   105  
   106  		fmt.Println(strings.TrimSuffix(p.HTTPURLToRepo, ".git"))
   107  	},
   108  }
   109  
   110  func determineNamespacePath(args []string, name string) (string, string) {
   111  	if len(args) > 0 {
   112  		ps := strings.Split(args[0], "/")
   113  		if len(ps) == 1 {
   114  			return "", ps[0]
   115  		}
   116  		return strings.Join(ps[:len(ps)-1], "/"), ps[len(ps)-1]
   117  	}
   118  
   119  	var path string
   120  	if name == "" && git.InsideGitRepo() {
   121  		wd, err := git.WorkingDir()
   122  		if err != nil {
   123  			log.Fatal(err)
   124  		}
   125  		p := strings.Split(wd, "/")
   126  		path = p[len(p)-1]
   127  	}
   128  	return "", path
   129  }
   130  
   131  func init() {
   132  	projectCreateCmd.Flags().StringP("name", "n", "", "name of the new project")
   133  	projectCreateCmd.Flags().StringP("group", "g", "", "group name (also known as namespace)")
   134  	projectCreateCmd.Flags().StringP("description", "d", "", "description of the new project")
   135  	projectCreateCmd.Flags().StringP("remote", "r", "", "add remote referring to the new project")
   136  	projectCreateCmd.Flags().BoolVarP(&private, "private", "p", false, "make project private: visible only to project members")
   137  	projectCreateCmd.Flags().BoolVar(&public, "public", false, "make project public: visible without any authentication")
   138  	projectCreateCmd.Flags().BoolVar(&internal, "internal", false, "make project internal: visible to any authenticated user (default)")
   139  	projectCreateCmd.Flags().BoolVar(&useHTTP, "http", false, "use HTTP protocol instead of SSH")
   140  	projectCmd.AddCommand(projectCreateCmd)
   141  }