github.com/elopio/cli@v6.21.2-0.20160902224010-ea909d1fdb2f+incompatible/CONTRIBUTING.md (about)

     1  # Contributing to CLI
     2  
     3  The Cloud Foundry team uses GitHub and accepts code contributions via
     4  [pull requests](https://help.github.com/articles/using-pull-requests).
     5  If your contribution includes a change that is exposed to cf CLI users
     6  (e.g. introducing a new command or flag), please submit an issue
     7  to discuss it first.
     8  Major new feature proposals generally entail a publicly viewable
     9  google document with commenting allowed to be discussed on the [cf-dev](https://lists.cloudfoundry.org/archives/list/cf-dev@lists.cloudfoundry.org/) mailing list.
    10  
    11  ## Contributor License Agreement
    12  
    13  Follow these steps to make a contribution to any of our open source repositories:
    14  
    15  1. Ensure that you have completed our CLA Agreement for
    16    [individuals](https://www.cloudfoundry.org/wp-content/uploads/2015/09/CFF_Individual_CLA.pdf) or
    17    [corporations](https://www.cloudfoundry.org/wp-content/uploads/2015/09/CFF_Corporate_CLA.pdf).
    18  
    19  ## Setup
    20  
    21  1. Install [Go 1.6.x](https://golang.org)
    22  1. Create a directory where you would like to store the source for Go projects and their binaries (e.g. `$HOME/go`)
    23  1. Set an environment variable, `GOPATH`, pointing at the directory you created
    24  1. Get the `cf` source: `go get github.com/cloudfoundry/cli`
    25    * (Ignore any warnings about "no buildable Go source files")
    26  1. [Fork this repository](https://help.github.com/articles/fork-a-repo/), adding your fork as a remote
    27  1. Run our bootstrap script, `bin/bootstrap`
    28  
    29  ## Workflow
    30  
    31  1. Run all the existing tests with `bin/test` to ensure they pass
    32  1. Write a new test, see it fail when running `bin/test` (or `ginkgo -p path/to/the/package/being/tested`)
    33  1. Write code to pass the test
    34  1. Repeat the above two steps until the feature is complete
    35  1. Run all the existing tests with `bin/test` to ensure they *still* pass
    36  1. Submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the `master` branch
    37  
    38  **_*_ For development guide on writing a cli plugin, see [here](https://github.com/cloudfoundry/cli/tree/master/plugin_examples)**
    39  
    40  ## Architecture Overview
    41  
    42  A command is a struct that implements this interface:
    43  
    44  ```Go
    45  type Command interface {
    46  	MetaData() CommandMetadata
    47  	SetDependency(deps Dependency, pluginCall bool) Command
    48  	Requirements(requirementsFactory requirements.Factory, context flags.FlagContext) []requirements.Requirement
    49  	Execute(context flags.FlagContext)
    50  }
    51  ```
    52  [Source code](https://github.com/cloudfoundry/cli/blob/master/cf/commandregistry/command.go#L9)
    53  
    54  `Metadata()` is just a description of the command name, usage and flags:
    55  ```Go
    56  type CommandMetadata struct {
    57  	Name            string
    58  	ShortName       string
    59  	Usage           []string
    60  	Description     string
    61  	Flags           map[string]flags.FlagSet
    62  	SkipFlagParsing bool
    63  	TotalArgs       int
    64  	Examples        []string
    65  }
    66  ```
    67  [Source code](https://github.com/cloudfoundry/cli/blob/master/cf/commandregistry/command.go#L16)
    68  
    69  The `Examples` field represents the set of lines to be printed when printing examples in the help text.
    70  
    71  `Requirements()` returns a list of requirements that need to be met before a command can be invoked.
    72  
    73  `Execute()` is the method that your command implements to do whatever it's supposed to do. The `context` object
    74  provides flags and arguments.
    75  
    76  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)).
    77  
    78  `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.
    79  The bool argument `pluginCall` indicates whether the command is invoked by one of the CLI's plugin API methods.
    80  
    81  Dependencies are injected into each command, so tests can inject a fake. This means that dependencies are
    82  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))
    83  
    84  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).
    85  
    86  Repositories communicate with the api endpoints through a Gateway (see [`cf/net`](https://github.com/cloudfoundry/cli/tree/master/cf/net)).
    87  
    88  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
    89  apps, buildpacks, domains, etc.
    90  
    91  ## Managing Dependencies
    92  
    93  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.
    94  
    95  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)
    96  
    97  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).
    98  
    99  ## Example Command
   100  
   101  Create Space is a good example of a command. Its tests include checking arguments, requiring the user
   102  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).
   103  
   104  ## i18n
   105  
   106  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`.
   107  
   108  After adding/changing strings supplied to the goi18n `T()` translation func, run the following to update the translations binary:
   109  
   110      i18n4go -c fixup # answer any prompts appropriately
   111      goi18n -outdir cf/i18n/resources cf/i18n/resources/*.all.json
   112      bin/generate-language-resources
   113  
   114  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.
   115  
   116  After running the above, be sure to commit the translations binary, `cf/resources/i18n_resources.go`.
   117  
   118  ## Current Conventions
   119  
   120  ### Creating Commands
   121  
   122  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`)
   123  
   124  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.
   125  
   126  ### Creating Repositories
   127  
   128  Although not ideal, we use the name "Repository" for API related operations as opposed to "Service". Repository was chosen
   129  to avoid confusion with Service model objects (i.e. creating Services and Service Instances within Cloud Foundry).
   130  
   131  By convention, Repository methods return a model object and an error. Models are used in both Commands and Repositories
   132  to model Cloud Foundry data. This convention provides a consistent method signature across repositories.