Build your own CLI using GoLang and Cobra

·

4 min read

Table of contents

No heading

No headings in the article.

The Go programming language is an open source project to make programmers more productive.

Go is expressive, concise, clean, and efficient. Its concurrency mechanisms make it easy to write programs that get the most out of multicore and networked machines, while its novel type system enables flexible and modular program construction. Go compiles quickly to machine code yet has the convenience of garbage collection and the power of run-time reflection. It’s a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language.

Go Programming.png

Goals

By the end of this tutorial, you will:

Learn how to use Cobra to create CLI(we will be creating a CLI command for GIT to list all the repo), and Understand the parts of a web application written in Go. Understand GitHub RESTful APIs interactions in GoLang.

Prerequisites

For this tutorial, you will need GoLang installed on your machine.

List of Packages we are going to use:

github.com/spf13/cobra

Cobra

Cobra.png

Cobra is a library for creating powerful modern CLI applications.

Cobra is used in many Go projects such as Kubernetes, Hugo, and Github CLI to name a few. This list contains a more extensive list of projects using Cobra.

Cobra is a library providing a simple interface to create powerful modern CLI interfaces similar to git & go tools.

Cobra provides:

  • Easy subcommand-based CLIs: app server, app fetch, etc.
  • Fully POSIX-compliant flags (including short & long versions)
  • Nested subcommands
  • Global, local and cascading flags
  • Intelligent suggestions (app srver... did you mean app server?)
  • Automatic help generation for commands and flags
  • Automatic help flag recognition of -h, --help, etc.
  • Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell)
  • Automatically generated man pages for your application
  • Command aliases so you can change things without breaking them
  • The flexibility to define your own help, usage, etc.
  • Optional seamless integration with viper for 12-factor apps

Let’s get started….

main.go

package main

import (
   "go-cli-for-git/cmd"
)

func main() {
   cmd.Execute()
}

**cmd/execute.go**

package cmd

import (
   "fmt"
   "github.com/spf13/cobra"
   "os"
)

var rootCmd = &cobra.Command{
   Use:   "cli",
   Short: "git cli execution using cobra to get all the repositories and their clone url",
}

func Execute() {
   if err := rootCmd.Execute(); err != nil {
      fmt.Println(err)
      os.Exit(1)
   }
}

we will be initializing the cobra command to the rootCmd variable with short description and trying to Execute it.

cmd/base.go

package cmd

import (
   b64 "encoding/base64"
   "encoding/json"
   "fmt"
   "github.com/spf13/cobra"
   "io/ioutil"
   "net/http"
)

// addCmd represents the add command
var addCmd = &cobra.Command{
   Use:   "get",
   Short: "get repo details",
   Long:  `Get Repo information using the Cobra Command`,
   Run: func(cmd *cobra.Command, args []string) {
      username, _ := rootCmd.Flags().GetString("username")
      password, _ := rootCmd.Flags().GetString("password")
      auth := fmt.Sprintf("%s:%s", username, password)
      authEncode := b64.StdEncoding.EncodeToString([]byte(auth))

      url := "https://api.github.com/user/repos"
      method := "GET"

      client := &http.Client{}
      req, err := http.NewRequest(method, url, nil)

      if err != nil {
         fmt.Println(err)
         return
      }
      req.Header.Add("Authorization", fmt.Sprintf("Basic %s", authEncode))

      res, err := client.Do(req)
      if err != nil {
         fmt.Println(err)
         return
      }
      defer res.Body.Close()

      var response []interface{}

      body, err := ioutil.ReadAll(res.Body)
      if err != nil {
         fmt.Println(err)
         return
      }

      err = json.Unmarshal(body, &response)

      for _, repoDetails := range response {
         repo := repoDetails.(map[string]interface{})
         fmt.Println(" name : ", repo["name"], " private :", repo["private"], "clone_url :", repo["clone_url"])
      }
   },
}

func init() {
   rootCmd.AddCommand(addCmd)
   rootCmd.PersistentFlags().StringP("username", "u", "", "the username of git")
   rootCmd.PersistentFlags().StringP("password", "p", "", "the access token of the git")
}

we will be initializing the commands in the rootCmd and initialize the flags that are required to perform your operations.

we have initialized the addCmd in the rootCmd for the execution of the command and initialzed the flags -u and -p to get the username and accessToken of the gitHub account.

rootCmd.PersistentFlags().StringP("username", "u", "", "the username of git") is the way you set the PersistentFlags in the command.

rootCmd.Flags().GetString("username") is the way to get the PersistentFlag value while the command gets executed.

we have used gitHub RESTful APIs to get all repositories of an specific account.

docs.github.com/en/rest this link will help you find the other REST API’s that is given by GitHub.

Build Binary of your Application using the below go command

go build -o git-cli Perfect!! We are all set now. Let’s run this project:

./git-cli get -u -p or

./git-cli get --username --password

So, It’s a SUCCESS!

1_4WiwZX_Pdg3YM9k_5eKmcg.png

The Cobra Command got executed and the gitHub Repo’s has been listed in the terminal.

If you find any kind of difficulty following the above steps, please check this repo and run:

git clone github.com/venkateshsuresh/go-cli-for-git.git

I hope this article helped you. Thanks for reading and stay tuned!

@Venkatesh

@BootLabs