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.