= CONTRIBUTING :toc: preamble :toclevels: 3 Thanks for your interest in this project, feel free to ask any questions you may have. == REQUIREMENTS To build the project, make sure that you link:golang[https://go.dev/] installed, link:https://www.gnu.org/software/make/[GNU Make] and link:https://goreleaser.com/install/[goreleaser installed], then execute the command `make build`, or use Docker with: ``` docker run --rm -v "$PWD":/usr/src/updatecli -w /usr/src/updatecli -e GOOS=windows -e GOARCH=386 golang:1.16 go build -v ``` == CONTRIBUTE They're multiple ways to contribute which don't necessarily involve coding, like providing feedback, improving documentation and processes. Here I'll just highlight some of them: === FEEDBACK It's significantly harder to build a solution that could be used by different people. It involves many different skills hard to master and it's easy to get stuck in local optimum. So feel free to reach out to say what's wrong and what could be improved. === CODE The code is divided into two categories, core and plugins. The core is designed to be independent and to provide the skeleton for the application, while the plugins define how things are automated for a specific use-case. The easiest part is probably plugins as it allows you to contribute independently to the process you are looking to automate. ==== CORE This section is still evolving as they're many areas that need attention. ==== PLUGINS Plugins can be easily added by following this workflow: ===== 1. Define package name Creating a new directory using your "packageName" under the directory `pkg/plugins` that will contain your go package similar to: ``` pkg ├── plugins │   └── packageName │  ├── source_test.go │  ├── source.go │  ├── condition_test.go │  ├── condition.go │  ├── spec.go │  ├── target_test.go │  ├── target.go │  ├── main_test.go │ └── main.go └── main_test.go ``` ===== 2. Define configuration In the `spec.go`, you need to define the `struct` that you'll use to configure your workflow where the capitalized fields will be set when unmarshalling from your future configuration.yaml ``` /* One multiline comment is required */ type Spec struct { /* One multiline comment is required per field */ Field1 string `yaml:",omitempty"` Field2 string `yaml:",omitempty" jsonschema:"required"` Field3 string `yaml:",omitempty"` Field4 string `yaml:",omitempty"` } ``` **Tags** Fields tags are important components and can come from one of the two following modules: * https://github.com/go-yaml/yaml * https://github.com/invopop/jsonschema **Comments** Fields comments are critical as they are used to generate Updatecli documentation available both from www.updatecli.io and your favorite IDE. Our objective is to have `Spec` comments such as ``` A short one-line description of the parameter compatible * source * condition * target default: A short explanation of the default value. It's also the place for explaining if the value is inherited from the source output. remarks: A list of information to be aware of when using the parameter such * info 1 * info 2 example: If useful, a simple example of how to use it ``` ===== 3. Respect the contract Your 'packageName' must provide a `struct` which implements the `Resource` interface by defining the following functions: [cols="1,2a,2", options="header"] .Rules |=== | Stage | Interface | Description | Source | ``` Source(workingDir string, resultSource *result.Source) error ``` | Defines how a version will be retrieved then passed the following stages | Changelog | ``` Changelog() string ``` | Retrieve the changelog for a specific source. | Condition | ``` Condition(source string, scm scm.ScmHandler) (pass bool, message string, err error) ``` | Define a condition which has to pass in order to proceed | Target | ``` Target(source string, scm scm.ScmHandler, dryRun bool, resultTarget *result.Target) error ``` | Define how a target file is updated |=== ===== 4. Claim your name Each stage which can be configured using a yaml/go template has to bind a resource kind and a package name, this is done in the "Unmarshal" function ``` import "github.com/updatecli/updatecli/pkg/plugins/packageName" ... case "packageName": p := packageName.PackageName{} err := mapstructure.Decode(s.Spec, &p) if err != nil { return err } spec = &p ``` Now something like this should be working: config.value ``` # updatecli diff --config config.value sources: default: kind: packageName spec: field1: "value" field3: "value" targets: idName: name: "updatecli" kind: "yaml" spec: file: "..." key: "..." transformers: - addPrefix: "olblak/polls@256:" ``` === DOCUMENTATION If you spot phrasing issues or just a lack of documentation, feel free to open link:https://github.com/updatecli/updatecli/issues[an issue] and/or link:https://github.com/updatecli/updatecli/pulls[a pull request]. https://github.com/updatecli/website[website]