github.com/jasonkeene/cli@v6.14.1-0.20160816203908-ca5715166dfb+incompatible/CONTRIBUTING.md (about)

     1  # Contributing to CLI
     2  
     3  The Cloud Foundry team uses GitHub and accepts contributions via
     4  [pull request](https://help.github.com/articles/using-pull-requests).
     5  
     6  ## Contributor License Agreement
     7  
     8  Follow these steps to make a contribution to any of our open source repositories:
     9  
    10  1. Ensure that you have completed our CLA Agreement for
    11    [individuals](http://www.cloudfoundry.org/individualcontribution.pdf) or
    12    [corporations](http://www.cloudfoundry.org/corpcontribution.pdf).
    13  
    14  ## General Workflow
    15  
    16  Major new feature proposals are given as a publicly viewable google document with commenting allowed and discussed on the [cf-dev](https://lists.cloudfoundry.org/archives/list/cf-dev@lists.cloudfoundry.org/) mailing list.
    17  
    18  1. Install [Go 1.6.x](https://golang.org)
    19  1. Create a directory where you would like to store the source for Go projects and their binaries (e.g. `$HOME/go`)
    20  1. Set an environment variable, `GOPATH`, pointing at the directory you created
    21  1. Get the `cf` source: `go get github.com/cloudfoundry/cli`
    22    * (Ignore any warnings about "no buildable Go source files")
    23  1. [Fork this repository](https://help.github.com/articles/fork-a-repo/), adding your fork as a remote
    24  1. Run our bootstrap script, `bin/bootstrap`
    25  1. Write a new test, see it fail when running `bin/test` (or `ginkgo -p path/to/the/package/being/tested`)
    26  1. Write code to pass the test
    27  1. Repeat the above two steps until the feature is complete
    28  1. Submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the `master` branch
    29  
    30  **_*_ For development guide on writing a cli plugin, see [here](https://github.com/cloudfoundry/cli/tree/master/plugin_examples)**
    31  
    32  ## Architecture Overview
    33  
    34  A command is a struct that implements this interface:
    35  
    36  ```Go
    37  type Command interface {
    38  	MetaData() CommandMetadata
    39  	SetDependency(deps Dependency, pluginCall bool) Command
    40  	Requirements(requirementsFactory requirements.Factory, context flags.FlagContext) []requirements.Requirement
    41  	Execute(context flags.FlagContext)
    42  }
    43  ```
    44  [Source code](https://github.com/cloudfoundry/cli/blob/master/cf/commandregistry/command.go#L9)
    45  
    46  `Metadata()` is just a description of the command name, usage and flags:
    47  ```Go
    48  type CommandMetadata struct {
    49  	Name            string
    50  	ShortName       string
    51  	Usage           []string
    52  	Description     string
    53  	Flags           map[string]flags.FlagSet
    54  	SkipFlagParsing bool
    55  	TotalArgs       int
    56  	Examples        []string
    57  }
    58  ```
    59  [Source code](https://github.com/cloudfoundry/cli/blob/master/cf/commandregistry/command.go#L16)
    60  
    61  The `Examples` field represents the set of lines to be printed when printing examples in the help text.
    62  
    63  `Requirements()` returns a list of requirements that need to be met before a command can be invoked.
    64  
    65  `Execute()` is the method that your command implements to do whatever it's supposed to do. The `context` object
    66  provides flags and arguments.
    67  
    68  When the command is run, it communicates with api using repositories (they are in [`cf/api`](https://github.com/cloudfoundry/cli/blob/master/cf/api)).
    69  
    70  `SetDependency()` is where a command obtains its dependencies. Dependencies are typically declared as an interface type, and not a concrete type, so tests can inject a fake.
    71  The bool argument `pluginCall` indicates whether the command is invoked by one of the CLI's plugin API methods.
    72  
    73  Dependencies are injected into each command, so tests can inject a fake. This means that dependencies are
    74  typically declared as an interface type, and not a concrete type. (see [`cf/commandregistry/dependency.go`](https://github.com/cloudfoundry/cli/blob/master/cf/commandregistry/dependency.go))
    75  
    76  Some dependencies are managed by a repository locator in [`cf/api/repository_locator.go`](https://github.com/cloudfoundry/cli/blob/master/cf/api/repository_locator.go).
    77  
    78  Repositories communicate with the api endpoints through a Gateway (see [`cf/net`](https://github.com/cloudfoundry/cli/tree/master/cf/net)).
    79  
    80  Models are data structures related to Cloud Foundry (see [`cf/models`](https://github.com/cloudfoundry/cli/tree/master/cf/models)). For example, some models are
    81  apps, buildpacks, domains, etc.
    82  
    83  ## Managing Dependencies
    84  
    85  Command dependencies are managed by the command registry package. The app uses the package (in [`cf/commandregistry/dependency.go`](https://github.com/cloudfoundry/cli/blob/master/cf/commandregistry/dependency.go)) to instantiate them, this allows not sharing the knowledge of their dependencies with the app itself.
    86  
    87  For commands that use another command as dependency, `commandregistry` is used for retrieving the command dependency. For example, the command `restart` has a dependency on command `start` and `stop`, and this is how the command dependency is retrieved: [`restart.go`](https://github.com/cloudfoundry/cli/blob/master/cf/commands/application/restart.go#L59)
    88  
    89  As for repositories, we use the repository locator to handle their dependencies. You can find it in [`cf/api/repository_locator.go`](https://github.com/cloudfoundry/cli/blob/master/cf/api/repository_locator.go).
    90  
    91  ## Example Command
    92  
    93  Create Space is a good example of a command. Its tests include checking arguments, requiring the user
    94  to be logged in, and the actual behavior of the command itself. You can find it in [`cf/commands/space/create_space.go`](https://github.com/cloudfoundry/cli/blob/master/cf/commands/space/create_space.go).
    95  
    96  ## i18n
    97  
    98  If you are adding new strings or updating existing strings within the CLI code, you'll need to update the binary representation of the translation files. This file is generated/maintained using [i18n4go](https://github.com/krishicks/i18n4go), [goi18n](https://github.com/nicksnyder/go-i18n), and `bin/generate-language-resources`.
    99  
   100  After adding/changing strings supplied to the goi18n `T()` translation func, run the following to update the translations binary:
   101  
   102      i18n4go -c fixup # answer any prompts appropriately
   103      goi18n -outdir cf/i18n/resources cf/i18n/resources/*.all.json
   104      bin/generate-language-resources
   105  
   106  When running `i18n4go -c fixup`, you will be presented with the choices `new` or `upd` for each addition or update. Type in the appropriate choice. If `upd` is chosen, you will be asked to confirm which string is being updated using a numbered list.
   107  
   108  After running the above, be sure to commit the translations binary, `cf/resources/i18n_resources.go`.
   109  
   110  ## Current Conventions
   111  
   112  ### Creating Commands
   113  
   114  Resources that include several commands have been broken out into their own sub-package using the Resource name. An example of this convention is the Space resource and package (see `cf/commands/space`)
   115  
   116  In addition, command file and methods naming follows a CRUD like convention. For example, the Space resource includes commands such a CreateSpace, ListSpaces, DeleteSpace, etc.
   117  
   118  ### Creating Repositories
   119  
   120  Although not ideal, we use the name "Repository" for API related operations as opposed to "Service". Repository was chosen
   121  to avoid confusion with Service model objects (i.e. creating Services and Service Instances within Cloud Foundry).
   122  
   123  By convention, Repository methods return a model object and an error. Models are used in both Commands and Repositories
   124  to model Cloud Foundry data. This convention provides a consistent method signature across repositories.