/letsgopher

A simple, yet flexible project generator for Go projects.

Primary LanguageGoApache License 2.0Apache-2.0

letsgopher Build Status Go Report Card Codecov

A simple, yet flexible project generator for Go projects. It uses templates bundled in ZIP files hosted on an HTTP server, downloads them on demand and generates a project structure from it.

DeyZit32MmnqInOwQJ66cZOp9

Installation

Simply download one of the pre-built binaries and add it to your PATH environment variable.

Initializing the tool

Upon its first use, letsgopher needs to initialize the local infrastructure. Run the init command to get started.

$ letsgopher init

You will find that a new directory in your home directory named .letsgopher.

$ tree ~/.letsgopher
/Users/bmuschko/.letsgopher
├── archive
└── templates.yaml

1 directory, 1 file

The directory contains the subdirectory archive. That’s the location where template archive are stored after they have been downloaded. The file templates.yaml keeps track of all downloaded and usable templates.

Note
Do not manually edit the templates.yaml file. The tool provides management commands for installing and uninstalling templates.

Managing templates

The project doesn’t come with any templates out-of-the-box. You need to install them yourself. A template archive needs to be hosted on a HTTP server and follow the naming convention [TEMPLATE-NAME]-[TEMPLATE-VERSION].[ARCHIVE-EXTENSION]. The [TEMPLATE-VERSION] needs to follow the semantic versioning scheme.

Note
The only supported archive type at the moment are ZIP files.

Installing a template

To download and install a template, run the template install command.

$ letsgopher template install [ARCHIVE-URL] [TEMPLATE-NAME]

The following example installs the archive hello-world-0.2.0.zip from a Dropbox URL and registers it with the name basic.

$ letsgopher template install https://dl.dropboxusercontent.com/s/002j89do6epotqs/hello-world-0.2.0.zip basic
"basic" has been added to your templates

Listing installed templates

Installed templates can be listed with the list command.

$ letsgopher template list

As you can see the following output, the provided template name can help you provide descriptive name in case the ZIP files name doesn’t properly express its purpose.

$ letsgopher template list
NAME    VERSION   ARCHIVE PATH
basic   0.2.0     /Users/bmuschko/.letsgopher/archive/hello-world-0.2.0.zip

Inspecting an installed template

Templates can provide additional metadata. For example parameters can be defined to replace placeholder variable with actual values entered by the user when generating a new project from that template. To inspect the metadata of an installed template, use the inspect command.

$ letsgopher template inspect [TEMPLATE-NAME] [TEMPLATE-VERSION]

The command line output below shows the metadata for the basic template with version 0.2.0.

$ letsgopher template inspect basic 0.2.0
template:
  name: "basic"
  version: "0.2.0"
manifest:
  version: "0.1.0"
  parameters:
    - name: "module"
      prompt: "Please provide a module name"
      type: "string"
      description: "The module name is used in the go.mod file"
    - name: "message"
      prompt: "Please select a message"
      type: "string"
      enum: ["Hello World!", "Let's get started", "This is just the beginning"]
      description: "The message to be rendered when executing the program"

Uninstalling a template

Sometimes you’ll want to delete a template - maybe you are not using anymore or the version became outdated. The uninstall command deletes the archive file on your local disk and removes the template entry from the templates.yaml file.

$ letsgopher template uninstall [TEMPLATE-NAME] [TEMPLATE-VERSION]

The following command execution deletes the template basic with version 0.2.0.

$ letsgopher template uninstall basic 0.2.0
template "my-world" has been removed

Generating projects from a template

After installing a template you can derive a completely new project from it. Run the create command to start the generation process. The command will ask you to interactively enter values for each parameter defined in the project metadata.

$ letsgopher template create [TEMPLATE-NAME] [TEMPLATE-VERSION] [PROJECT-NAME]

As you can see in the command line output below, letsgopher prompts the user with the help of different UI elements.

$ letsgopher create basic 0.2.0 go-hello-world
? Please provide a module name hello-world
? Please select a message  [Use arrows to move, type to filter, ? for more help]
  Hello World!
❯ Let's get started
  This is just the beginning
created project at "go-hello-world"

Alternatively, you can ask pass in the parameter values with the command line option --param to forgo the interactive mode.

$ letsgopher create basic 0.2.0 go-hello-world --param module=hello-world --param message="Let's get started"
created project at "go-hello-world"

Creating your own template

A template defines the structure of a project including directories and files. Additionally, a template needs to add a manifest.yaml file to the root directory the project structure. The manifest file describes the metadata of a template. Files can use Go’s templating mechanism for replacing placeholders at project generation time.

Note
letsgopher automatically excludes the file manifest.yaml when generating a project.

Let’s say you want to build a very simple "Hello World!" Go template. The following directory structure shows the main.go file and the Go module file go.mod. The directory also contains the manifest file.

$ tree hello-world-0.2.0
hello-world-0.2.0
├── go.mod
├── main.go
└── manifest.yaml

0 directories, 3 files

Next, we’ll have a look at the metadata that has to be defined for a template.

The manifest file

The manifest file has to have the name manifest.yaml. It contains a version which ensures that updates to the YAML structure can be made in the future. The current supported version is 0.1.0. A manifest may optionally declare parameters. Specified parameters request an input from the user. The captured value is used to replace placeholders in template files at the time of project generation. The following manifest.yaml demonstrates a typical example:

version: "0.1.0"
parameters:
  - name: "module"
    prompt: "Please provide a module name"
    type: "string"
    description: "The module name is used in the go.mod file"
  - name: "message"
    prompt: "Please select a message"
    type: "string"
    enum: ["Hello World!", "Let's get started", "This is just the beginning"]
    description: "The message to be rendered when executing the program"

A template can define any number of parameters. Some attributes are mandatory, some of them are optional. See the following table for an overview on the different attributes:

Table 1. Parameters
Name Required Description

name

yes

The placeholder key uses in templates.

prompt

yes

The UI prompt in the interactive mode for requesting values from users.

type

yes

The type of a parameter. Valid values are string, integer and boolean.

enum

no

A list of allowed and selectable values for a parameter.

description

no

Describes the parameter purpose. Does not show up in the UI.

Creating the template archive

At the moment there’s no tooling for creating an archive for the template from within letsgopher. The ZIP file name has to follow the convention [TEMPLATE-NAME]-[TEMPLATE-VERSION].[ARCHIVE-EXTENSION]. You can simply run the zip command to create the file, as shown below. The [TEMPLATE-VERSION] needs to follow the semantic versioning scheme.

$ cd hello-world-0.2.0
$ zip -r hello-world-0.2.0.zip .
  adding: go.mod (deflated 10%)
  adding: .gitignore (stored 0%)
  adding: manifest.yaml (deflated 45%)
  adding: main.go (deflated 7%)

Now, you can simply upload the ZIP file to a HTTP server of your choice for later consumption.

Limitations

The project is still in its early stages. Currently, the following functionality is not supported.

  • Defining and executing custom logic for dynamically generating project structures e.g. if a user answers "yes" for a parameters then a new file is created with a specific name.

  • Before and after hooks that can run additional scripts.

  • Other template archive formats than .zip, for example .tar.gz.

  • Downloading template archives with other protocols than HTTP.