get.porter.sh/porter@v1.3.0/CONTRIBUTING.md (about) 1 # Contributing Guide 2 3 --- 4 * [How to help](#how-to-help) 5 * [Code of Conduct](#code-of-conduct) 6 * [Find an issue](#find-an-issue) 7 * [Which branch to use](#which-branch-to-use) 8 * [When to open a pull request](#when-to-open-a-pull-request) 9 * [How to test your pull request](#how-to-test-your-pull-request) 10 * [How to get your pull request reviewed fast](#how-to-get-your-pull-request-reviewed-fast) 11 * [Signing your commits](#signing-your-commits) 12 * [The life of a pull request](#the-life-of-a-pull-request) 13 * [Contribution Ladder](#contribution-ladder) 14 * [Developer Tasks](#developer-tasks) 15 * [Initial setup](#initial-setup) 16 * [Magefile explained](#magefile-explained) 17 * [Test Porter](#test-porter) 18 * [Install mixins](#install-mixins) 19 * [Plugin Debugging](#plugin-debugging) 20 * [Preview documentation](#preview-documentation) 21 * [Write a blog post](#write-a-blog-post) 22 * [View a trace of a Porter command](#view-a-trace-of-a-porter-command) 23 * [Debug Smoke Tests](#debug-smoke-tests) 24 * [Command Documentation](#command-documentation) 25 * [Work on the Porter Operator](#work-on-the-porter-operator) 26 * [Code structure and practices](#code-structure-and-practices) 27 * [What is the general code layout?](#what-is-the-general-code-layout) 28 * [Logging](#logging) 29 * [Tracing Sensitive Data](#tracing-sensitive-data) 30 * [Breaking Changes](#breaking-changes) 31 * [Infrastructure](#infrastructure) 32 * [CDN Setup](#cdn-setup) 33 * [Custom Windows CI Agent](#custom-windows-ci-agent) 34 * [Releases](#releases) 35 --- 36 37 ## How to help 38 39 We welcome your contributions and participation! If you aren't sure what to 40 expect, here are some norms for our project so you feel more comfortable with 41 how things will go. 42 43 If this is your first contribution to Porter, we have a [tutorial] that walks you 44 through how to setup your developer environment, make a change and test it. 45 46 [tutorial]: https://porter.sh/docs/contribute/tutorial/ 47 48 ### Code of Conduct 49 50 The Porter community is governed by our [Code of Conduct][coc]. 51 This includes but isn't limited to: the porter and related mixin repositories, 52 slack, interactions on social media, project meetings, conferences and meetups. 53 54 [coc]: https://porter.sh/src/CODE_OF_CONDUCT.md 55 56 ### Find an issue 57 58 Use the [porter.sh/find-issue] link to find good first issues for new contributors and help wanted issues for our other contributors. 59 60 When you have been contributing for a while, take a look at the "Backlog" column on our [project board][board] for high priority issues. 61 The project board is at the organization level, so it contains issues from across all the Porter repositories. 62 63 * [`good first issues`][good-first-issue] has extra information to help you make your first contribution. 64 * [`help wanted`][help-wanted] are issues suitable for someone who isn't a core maintainer. 65 * `hmm 🛑🤔` issues should be avoided. They are not ready to be worked on yet 66 because they are not finished being designed or we aren't sure if we want the 67 feature, etc. 68 69 Maintainers will do their best to regularly make new issues for you to solve and then 70 help out as you work on them. 💖 71 72 We have a [roadmap] that will give you a good idea of the 73 larger features that we are working on right now. That may help you decide what 74 you would like to work on after you have tackled an issue or two to learn how to 75 contribute to Porter. If you have a big idea for Porter, learn [how to propose 76 a change to Porter][pep]. 77 78 Another great way to contribute is to create a mixin! You can start using the 79 [Porter Skeletor][skeletor] repository as a template to start, along with the 80 [Mixin Developer Guide][mixin-dev-guide]. 81 82 When you create your first pull request, add your name to the bottom of our 83 [Contributors][contributors] list. Thank you for making Porter better! 🙇♀️ 84 85 [porter.sh/find-issue]: https://porter.sh/find-issue/ 86 [contributors]: https://porter.sh/src/CONTRIBUTORS.md 87 [skeletor]: https://github.com/getporter/skeletor 88 [mixin-dev-guide]: https://porter.sh/mixin-dev-guide/ 89 [good-first-issue]: https://porter.sh/board/good+first+issue 90 [help-wanted]: https://porter.sh/board/help+wanted 91 [board]: https://porter.sh/board 92 [slack]: https://porter.sh/community#slack 93 [roadmap]: https://porter.sh/src/README.md#roadmap 94 [pep]: https://porter.sh/docs/contribute/proposals/ 95 96 ### Which branch to use 97 98 Unless the issue specifically mentions a branch, please create your feature branch from the **main** branch. 99 100 For example: 101 102 ```bash 103 # Make sure you have the most recent changes to main 104 git checkout main 105 git pull 106 107 # Create a branch based on main named MY_FEATURE_BRANCH 108 git checkout -b MY_FEATURE_BRANCH main 109 ``` 110 111 ### When to open a pull request 112 113 It's OK to submit a PR directly for problems such as misspellings or other 114 things where the motivation/problem is unambiguous. 115 116 If there isn't an issue for your PR, please make an issue first and explain the 117 problem or motivation for the change you are proposing. When the solution isn't 118 straightforward, for example, "Implement missing command X", then also outline 119 your proposed solution. Your PR will go smoother if the solution is agreed upon 120 before you've spent a lot of time implementing it. 121 122 Since Porter is a CLI, the "solution" will usually look like this: 123 124 ```console 125 $ porter newcommand [OPTIONAL] [--someflag VALUE] 126 example output 127 ``` 128 129 ### How to test your pull request 130 131 We recommend running the following every time: 132 133 ``` 134 mage Build TestUnit 135 ``` 136 137 If your test modified anything related to running a bundle, also run: 138 139 ``` 140 mage TestIntegration 141 ``` 142 143 If you want to know _all_ the targets that the CI runs, look at 144 <build/azure-pipelines.pr-automatic.yml>. 145 146 ### How to get your pull request reviewed fast 147 148 🚧 If you aren't done yet, create a draft pull request or put WIP in the title 149 so that reviewers wait for you to finish before commenting. 150 151 1️⃣ Limit your pull request to a single task. Don't tackle multiple unrelated 152 things, especially refactoring. If you need large refactoring for your change, 153 chat with a maintainer first, then do it in a separate PR first without any 154 functionality changes. 155 156 🎳 Group related changes into separate commits to make it easier to review. 157 158 😅 Make requested changes in new commits. Please don't amend or rebase commits 159 that we have already reviewed. When your pull request is ready to merge, you can 160 rebase your commits yourself, or we can squash when we merge. Just let us know 161 what you are more comfortable with. 162 163 🚀 We encourage [follow-on PRs](#follow-on-pr) and a reviewer may let you know in 164 their comment if it is okay for their suggestion to be done in a follow-on PR. 165 You can decide to make the change in the current PR immediately, or agree to 166 tackle it in a reasonable amount of time in a subsequent pull request. If you 167 can't get to it soon, please create an issue and link to it from the pull 168 request comment so that we don't collectively forget. 169 170 ### Signing your commits 171 172 You can automatically sign your commits to meet the DCO requirement for this 173 project by running the following command: `mage SetupDCO`. 174 175 Licensing is important to open source projects. It provides some assurances that 176 the software will continue to be available based under the terms that the 177 author(s) desired. We require that contributors sign off on commits submitted to 178 our project's repositories. The [Developer Certificate of Origin 179 (DCO)](https://developercertificate.org/) is a way to certify that you wrote and 180 have the right to contribute the code you are submitting to the project. 181 182 You sign-off by adding the following to your commit messages: 183 184 ```bash 185 Author: Your Name <your.name@example.com> 186 Date: Thu Feb 2 11:41:15 2018 -0800 187 188 This is my commit message 189 190 Signed-off-by: Your Name <your.name@example.com> 191 ``` 192 193 Notice the `Author` and `Signed-off-by` lines match. If they don't, the PR will 194 be rejected by the automated DCO check. 195 196 Git has a `-s` command line option to do this automatically: 197 198 ``` 199 git commit -s -m 'This is my commit message' 200 ``` 201 202 If you forgot to do this and have not yet pushed your changes to the remote 203 repository, you can amend your commit with the sign-off by running 204 205 ``` 206 git commit --amend -s 207 ``` 208 209 ### The life of a pull request 210 211 1. You create a draft or WIP pull request. Reviewers will ignore it mostly 212 unless you mention someone and ask for help. Feel free to open one and use 213 the pull request to see if the CI passes. Once you are ready for a review, 214 remove the WIP or click "Ready for Review" and leave a comment that it's 215 ready for review. 216 217 If you create a regular pull request, a reviewer won't wait to review it. 218 1. A reviewer will assign themselves to the pull request. If you don't see 219 anyone assigned after 3 business days, you can leave a comment asking for a 220 review, or ping in [slack][slack]. Sometimes we have busy days, sick days, 221 weekends and vacations, so a little patience is appreciated! 🙇♀️ 222 1. The reviewer will leave feedback. 223 * `nits`: These are suggestions that you may decide to incorporate into your pull 224 request or not without further comment. 225 * It can help to put a 👍 on comments that you have implemented so that you 226 can keep track. 227 * It is okay to clarify if you are being told to make a change or if it is a 228 suggestion. 229 1. After you have made the changes (in new commits please!), leave a comment. If 230 3 business days go by with no review, it is okay to bump. 231 1. When a pull request has been approved, the reviewer will squash and merge 232 your commits. If you prefer to rebase your own commits, at any time leave a 233 comment on the pull request to let them know that. 234 235 At this point your changes are available in the [canary][canary] release of 236 Porter! After your first pull request is merged, you will be invited to the 237 [Contributors team] which you may choose to accept (or not). Joining the team lets 238 you have issues in GitHub assigned to you. 239 240 [canary]: https://porter.sh/install/#canary 241 [Contributors team]: https://github.com/orgs/getporter/teams/contributors 242 243 #### Follow-on PR 244 245 A follow-on PR is a pull request that finishes up suggestions from another pull 246 request. 247 248 When the core of your changes are good, and it won't hurt to do more of the 249 changes later, our preference is to merge early, and keep working on it in a 250 subsequent. This allows us to start testing out the changes in our canary 251 builds, and more importantly enables other developers to immediately start 252 building their work on top of yours. 253 254 This helps us avoid pull requests to rely on other pull requests. It also avoids 255 pull requests that last for months, and in general we try to not let "perfect be 256 the enemy of the good". It's no fun to watch your work sit in purgatory, and it 257 kills contributor momentum. 258 259 ## Contribution Ladder 260 261 Our [contribution ladder][ladder] defines the roles and responsibilities for this 262 project and how to participate with the goal of moving from a user to a 263 maintainer. 264 265 [ladder]: https://porter.sh/src/CONTRIBUTION_LADDER.md 266 267 ## Developer Tasks 268 269 ### Initial setup 270 271 We have a [tutorial] that walks you through how to set up your developer 272 environment, make a change and test it. 273 274 Here are the key steps, if you run into trouble, the tutorial has more details: 275 276 1. Install Go version 1.17 or higher. 277 1. Clone this repository with `git clone https://github.com/getporter/porter.git ~/go/src/get.porter.sh/porter`. 278 1. Run `go run mage.go EnsureMage` to install [mage](#magefile-explained). 279 1. Run `mage Build Install` from within the newly cloned repository. 280 281 If you are planning on contributing back to the project, you'll need to 282 [fork](https://guides.github.com/activities/forking/) and clone your fork. If 283 you want to build porter from scratch, you can follow the process above and 284 clone directly from the project. 285 286 You now have canary builds of porter and all the mixins installed. 287 288 ### Magefile explained 289 290 Porter uses a cross-platform make alternative called [mage](https://magefile.org), where the targets are written in Go. 291 292 #### Mage Targets 293 294 Mage targets are not case-sensitive, but in our docs we use camel case to make 295 it easier to read. You can run either `mage TestSmoke` or `mage testsmoke` for 296 example. 297 298 * **Build** builds all binaries, porter and internal mixins. 299 * **BuildClient** just builds the porter client for your operating system. 300 It does not build the porter-runtime binary. Useful when you just want to do a 301 build and don't remember the proper way to call `go build` yourself. 302 * **BuildPorter** builds both the porter client and runtime. 303 * **Clean** removes artifacts from previous builds and test runs. 304 * **UpdateTestfiles** updates the "golden" test files to match the latest test output. 305 This is mostly useful for when you change the schema of porter.yaml which will 306 break TestPorter_PrintManifestSchema. Run this target to fix it. 307 Learn more about [golden files]. 308 * **Test** runs all the tests. 309 * **TestUnit** runs the unit tests 310 * **TestSmoke** runs a small suite of tests using the Porter CLI to validate 311 that Porter is (mostly) working. 312 * **TestIntegration** runs our integration tests, which run the bundles 313 against a test KIND cluster. 314 * **Install** installs porter _and_ the mixins from source into **$(HOME)/.porter/**. 315 * **DocsPreview** hosts the docs site. See [Preview Documentation](#preview-documentation). 316 * **DocsGen** generates the CLI documentation for the website. This is run automatically by build. 317 * **SetupDCO** installs a git commit hook that automatically signsoff your commit 318 messages per the DCO requirement. 319 320 [golden files]: https://ieftimov.com/post/testing-in-go-golden-files/ 321 322 ### Test Porter 323 324 We have a few different kinds of tests in Porter. You can run all tests types 325 with `mage test`. 326 327 #### Unit Tests 328 329 ``` 330 mage TestUnit 331 ``` 332 333 Should not rely on Docker, or try to really run bundles without key components 334 mocked. Most structs have test functions, e.g. `porter.NewTestPorter` that are 335 appropriate for unit tests. 336 337 Fast! 🏎💨 This takes about 15s - 3 minutes, depending on your computer hardware. 338 339 #### Integration Tests 340 341 ``` 342 mage TestIntegration 343 ``` 344 345 These tests run parts of Porter, using the Porter structs instead of the cli. 346 They can use Docker, expect that a cluster is available, etc. These tests all 347 use functions like `porter.SetupIntegrationTest()` to update the underlying 348 components so that they hit the real filesystem, and don't mock out stuff like 349 Docker. 350 351 You must have Docker on your computer to run these tests. The test setup handles 352 creating a Kubernetes cluster and Docker registry. Since they are slow, it is 353 perfectly fine to not run these locally and rely on the CI build that's triggered 354 when you push commits to your pull request instead. 355 356 When I am troubleshooting an integration test, I will run just the single test 357 locally by using `go test -run TESTNAME ./...`. If the test needs infrastructure, 358 we have scripts that you can use, like `mage StartDockerRegistry` or 359 `mage EnsureTestCluster`. 360 361 Slow! 🐢 This takes between 8-16 minutes, depending on your computer hardware. 362 363 🚧 We are in the process of updating our integration tests to reduce total test time by combining test cases into larger tests so that we aren't running expensive set up operations like building bundles as often. 364 The goal is to make the integration tests use the same test framework [tests/tester] which tests porter using the CLI instead of by calling porter's code directly. 365 Follow the example of the [hello smoke test] for a good test to copy and make new tests from. 366 We use the [Testify library](https://github.com/stretchr/testify)'s [`require`](https://pkg.go.dev/github.com/stretchr/testify@v1.8.2/require) package (instead of [`assert`](https://pkg.go.dev/github.com/stretchr/testify@v1.8.2/assert)) in these long tests because we want the test to stop on the first failure instead of having the rest of the test output a bunch of failures too. 367 The first failure is the relevant one, and stopping immediately makes it faster and easier to see the root problem. 368 369 [hello smoke test]: https://github.com/getporter/porter/blob/main/tests/smoke/hello_test.go 370 [tests/tester]: https://github.com/getporter/porter/blob/main/tests/tester/main.go#L46 371 372 #### Smoke Tests 373 374 ``` 375 mage testSmoke 376 ``` 377 378 Smoke tests test Porter using the CLI and quickly identify big problems with a 379 build that would make it unusable. 380 If you intend to change Porter code (not docs), we recommend running smoke tests locally before submitting a pull request with your changes. Doing so allows you to immediately ensure you haven't broken or altered any core functionality. 381 382 Short! We want this to always be something you can run in under 3 minutes. 383 384 ### Install mixins 385 386 When you run `mage build`, the canary\* build of mixins are automatically 387 installed into your bin directory in the root of the repository. You can use 388 `porter mixin install NAME` to install the latest released version of a mixin. 389 390 \* canary = most recent successful build of the "main" branch 391 392 ### Plugin Debugging 393 394 If you are developing a [plugin](https://porter.sh/plugins/) and you want to 395 debug it follow these steps: 396 397 The plugin to be debugged should be compiled and placed in porters plugin path 398 (e.g. in the Azure plugin case the plugin would be copied to 399 $PORTER_HOME/plugins/azure/. 400 401 The following environment variables should be set: 402 403 `PORTER_RUN_PLUGIN_IN_DEBUGGER` should be set to the name of the plugin to be 404 debugged (e.g. secrets.azure.keyvault to debug the azure secrets plugin) 405 `PORTER_DEBUGGER_PORT` should be set to the port number where the delve API will 406 listen, if not set it defaults to 2345 407 `PORTER_PLUGIN_WORKING_DIRECTORY` should be the path to the directory containing 408 *source code* for the plugin being executed. 409 410 When porter is run it will start delve and attach it to the plugin process, this 411 exposes the delve API so that any delve client can connect to the server and 412 debug the plugin. 413 414 ### Preview documentation 415 416 We use [Hugo](https://gohugo.io) to build our documentation site, and it is hosted on 417 [Netlify](https://netlify.com). You don't have to install Hugo locally because the 418 preview happens inside a docker container. 419 420 1. Run `mage DocsPreview` to start serving the docs. It will watch the file 421 system for changes. 422 1. Our mage target should open <http://localhost:1313/docs> to preview the 423 site/docs. 424 425 or use only Hugo 426 427 1. Download and install [Hugo 0.117.0](https://github.com/gohugoio/hugo/releases/tag/v0.117.0) extended version. 428 2. `cd docs` 429 3. `hugo server --watch` 430 431 We welcome your contribution to improve our documentation, and we hope it is an 432 easy process! ❤️ 433 434 ### Write a blog post 435 436 Thank you for writing a post for our blog! 🙇♀️ Here's what you need to do to create 437 a new blog post and then preview it: 438 439 1. Go to /docs/content/blog and create a new file. Whatever you name the file 440 will be the last part of the URL. For example a file named 441 "porter-collaboration.md" will be located at 442 <https://porter.sh/blog/porter-collaboration/>. 443 444 1. At the top of the file copy and paste the frontmatter template below. The 445 frontmatter is YAML that instructs the blogging software, Hugo, how to render the 446 blog post. 447 448 ```yaml 449 --- 450 title: "Title of Your Blog Post in Titlecase" 451 description: "SEO description of your post, displayed in search engine results." 452 date: "2020-07-28" 453 authorname: "Your Name" 454 author: "@yourhandle" #Not used to link to github/twitter, but informally that's what people put here 455 authorlink: "https://link/to/your/website" # link to your personal website, github, social media... 456 authorimage: "https://link/to/your/profile/picture" # Optional, https://github.com/yourhandle.png works great 457 tags: [] # Optional, look at other pages and pick tags that are already in use, e.g. ["mixins"] 458 --- 459 ``` 460 461 1. [Preview](#preview-documentation) the website and click "Blog" at the top 462 right to find your blog post. 463 464 1. When you create a pull request, look at the checks run by the pull request, 465 and click "Details" on the **netlify/porter/deploy-preview** one to see a live 466 preview of your pull request. 467 468 Our pull request preview and the live site will not show posts with a date in 469 the future. If you don't see your post, change the date to today's date. 470 471 ### View a trace of a Porter command 472 473 Porter can send trace data about the commands run to an OpenTelemetry backend. 474 It can be very helpful when figuring out why a command failed because you can see the values of variables and stack traces. 475 476 In development, you can use the [otel-jaeger bundle] to set up a development instance of Jaeger, which gives you a nice website to see each command run. 477 478 ``` 479 porter install OtelJaeger --reference ghcr.io/getporter/examples/otel-jaeger:v0.1.0 --allow-docker-host-access 480 ``` 481 482 Then to turn on tracing in Porter, set the following environment variables. 483 This tells Porter to turn on tracing, and connect to OpenTelemetry server that you just installed. 484 485 **Posix** 486 ```bash 487 export PORTER_TELEMETRY_ENABLED="true" 488 export OTEL_EXPORTER_OTLP_PROTOCOL="grpc" 489 export OTEL_EXPORTER_OTLP_INSECURE="true" 490 ``` 491 492 **Powershell** 493 ```powershell 494 $env:PORTER_TELEMETRY_ENABLED="true" 495 $env:OTEL_EXPORTER_OTLP_PROTOCOL="grpc" 496 $env:OTEL_EXPORTER_OTLP_INSECURE="true" 497 ``` 498 499 Next run a Porter command to generate some trace data, such as `porter list`. 500 Then go to the Jaeger website to see your data: http://localhost:16686. 501 On the Jaeger dashboard, select "porter" from the service drop down, and click "Find Traces". 502 503 The smoke and integration tests will run with telemetry enabled when the PORTER_TEST_TELEMETRY_ENABLED environment variable is true. 504 505 [otel-jaeger bundle]: https://porter.sh/examples/src/otel-jaeger 506 507 ### Debug Smoke Tests 508 509 If you want to attach a debugger to Porter when it is running in a smoke test, first install delve: 510 511 ``` 512 go install github.com/go-delve/delve/cmd/dlv@latest 513 ``` 514 515 Next, determine the porter command that you want the smoke test to automatically run through delve so that you can attach to it and debug. 516 Set `PORTER_RUN_IN_DEBUGGER` to the command(s) to run in delve. 517 Use `porter` to target any porter command, or target a specific command for example `porter installation apply`. 518 519 When the smoke tests run a porter command that has the prefix contained in PORTER_RUN_IN_DEBUGGER, instead of running porter directly, porter is run in delve. 520 Delve will wait for you to attach a debugger, and then proceed to run the porter command so that you can debug into it. 521 522 The default debugger port is `55942` which you can override with the `PORTER_DEBUGGER_PORT` environment variable. 523 524 Now run the smoke test with `go test -run TESTNAME -tags smoke ./tests/smoke`, then use your Go IDE or delve directly to attach to Porter. 525 If you are using GoLand, use the **Go Remote** debug configuration and make sure to specify the same port that you used when running the smoke test (default is 55942). 526 527 ### Command Documentation 528 529 Our commands are documented at <https://porter.sh/docs/references/> and that documentation is 530 generated by our CLI. You should regenerate that documentation when you change 531 any files in **cmd/porter** by running `mage DocsGen` which is run every time 532 you run `mage build`. 533 534 ### Work on the Porter Operator 535 536 Instructions for building the Porter Operator from source are located in its repository: https://github.com/getporter/operator. 537 Sometimes you may need to make changes to Porter and work on the Operator at the same time. 538 Here's how to build porter so that you can use it locally: 539 540 1. You must be on a feature branch. Not main. This matters because it affects the generated 541 docker image tag. 542 1. Deploy the operator to a KinD cluster by running `mage deploy` from inside the operator repository. 543 That cluster has a local registry running that you can publish to, and it will pull images from it, 544 running on localhost:5000. 545 1. Run the following command from the porter repository to build the Porter Agent image, and publish it 546 to the test cluster's registry. `mage XBuildAll LocalPorterAgentBuild`. 547 1. Edit your AgentConfig in the Porter Operator and set it to use your local build of the porter-agent. 548 549 ```yaml 550 apiVersion: porter.sh/v1 551 kind: AgentConfig 552 metadata: 553 name: porter 554 namespace: test # You may need to change this depending on what you are testing 555 spec: 556 porterRepository: localhost:5000/porter-agent 557 porterVersion: canary-dev 558 serviceAccount: porter-agent 559 ``` 560 561 ## Code structure and practices 562 563 Carolyn Van Slyck gave a talk about the design of Porter, [Designing 564 Command-Line Tools People Love][porter-design] that you may find helpful in 565 understanding the why's behind its command grammar, package structure, use of 566 dependency injection and testing strategies. 567 568 [porter-design]: https://carolynvanslyck.com/talks/#gocli 569 570 ### What is the general code layout? 571 572 * **cmd**: go here to add a new command or flag to porter or one of the mixins in 573 this repository 574 * **docs**: our website 575 * **pkg** 576 * **build**: implements building the bundle image. 577 * **cache**: handles the cache of bundles that have been pulled by commands 578 like `porter install --reference`. 579 * **cnab**: deals with the CNAB spec 580 * **cnab-to-oci**: talking to an OCI registry. 581 * **config-adapter**: converting porter.yaml to bundle.json. 582 * **extensions**: extensions to the CNAB spec, at this point that's just 583 dependencies. 584 * **provider**: the CNAB runtime, i.e. `porter install`. 585 * **config**: anything related to `porter.yaml` and `~/.porter`. 586 * **context**: essentially dependency injection that's needed throughout Porter, 587 such as stdout, stderr, stdin, filesystem and command execution. 588 * **exec**: the exec mixin 589 * **mixin**: enums, functions and interfaces for the mixin framework. 590 * **feed**: works with mixin atom feeds 591 * **provider**: handles communicating with mixins 592 * **porter**: the implementation of the porter commands. Every command in Porter 593 has a corresponding function in here. 594 * **version**: reusable library used by all the mixins for implementing a mixin 595 * **secrets**: used to access porter's secret store through plugins. 596 * **storage**: used to access porter's data store through plugins. 597 * **templates**: files that need to be compiled into the porter binary with 598 version command. 599 * **scripts**: 600 * **install**: Porter [installation](https://porter.sh/install) scripts 601 * **tests** have Go-based integration tests. 602 603 ### Logging 604 605 **Print to the `Out` property for informational messages and send debug messages to the `Err` property.** 606 607 Example: 608 609 ```golang 610 fmt.Fprintln(p.Out, "Initiating battlestar protocol") 611 fmt.Fprintln(p.Err, "DEBUG: loading plans from r2d2...") 612 ``` 613 614 Most of the structs in Porter have an embedded 615 `get.porter.sh/porter/pkg/portercontext.Context` struct. This has both `Out` and 616 `Err` which represent stdout and stderr respectively. You should log to those 617 instead of directly to stdout/stderr because that is how we capture output in 618 our unit tests. That means use `fmt.Fprint*` instead of `fmt.Print*` so that you 619 can pass in `Out` or `Err`. 620 621 Some of our commands are designed to be consumed by another tool and intermixing 622 debug lines and the command output would make the resulting output unusable. For 623 example, `porter schema` outputs a json schema and if log lines were sent to 624 stdout as well, then the resulting json schema would be unparsable. This is why 625 we send regular command output to `Out` and debug information to `Err`. It 626 allows us to then run the command and see the debug output separately, like so 627 `porter schema --debug 2> err.log`. 628 629 #### Tracing Sensitive Data 630 631 Sometimes when debugging your code you may need to print out variables that can contain sensitive data, for example printing out the resolved values for parameters and credentials. 632 In this case, do not use fmt.Println and instead use the open telemetry trace logger to include the data in attributes. 633 634 ```go 635 func myFunc(ctx context.Context) { 636 ctx, span := tracing.StartSpan(ctx) 637 defer span.EndSpan() 638 639 // This contains resolved sensitive values, so only trace it in special dev builds (nothing is traced for release builds) 640 span.SetSensitiveAttributes(attribute.String("sensitive-stuff", mysensitiveVar)) 641 } 642 ``` 643 644 In normal builds of Porter, created with `go build`, `mage Build` or `mage XBuildAll`, no sensitive data is ever traced because `SetSensitiveAttributes` is compiled to do nothing by default. 645 Calls to `SetSensitiveAttributes` are only implemented when Porter is built with the `traceSensitiveAttributes` build tag. 646 647 Each time you call `SetSensitiveAttributes` include in your comment why the data is sensitive, and that it is only traced in special dev builds since people may not think to read the function documentation. 648 649 In order to debug your code and see the sensitive data, you need to: 650 651 1. Compile a build of porter with sensitive tracing turned on, `go build -tags traceSensitiveAttributes -o bin/porter ./cmd/porter`. 652 2. [Enable tracing with Jaeger](#view-a-trace-of-a-porter-command) 653 3. Run a porter command and then view the sensitive attributes in the trace data sent to Jaeger. 654 655 ### Breaking Changes 656 657 Some changes in Porter break our compatibility with previous versions of Porter. 658 When that happens, we need to release that change with a new major version number to indicate to users that it contains breaking changes. 659 When you realize that you may need to make a breaking change, discuss it with a maintainer on the issue or pull request and we'll come up with a plan for how it should be released. 660 Here are some examples of breaking changes: 661 662 * The schema of porter.yaml changed. 663 * The schema of Porter's [file formats](https://porter.sh/references/file-formats) changed. 664 * The schema of Porter's [config file](https://porter.sh/configuration/#config-file) changed. 665 * Flags or behavior of a CLI command changed, such as removing a flag or adding a validation that can result in a hard error, preventing the command from running. 666 667 All of Porter's documents have a schemaVersion field and when the schema of the document is changed, the version number should be incremented as well in the default set on new documents, the supported schema version constant in the code, and in the documentation for that document. 668 669 ## Infrastructure 670 671 This section includes overviews of infrastructure Porter relies on, mostly intended 672 for maintainers. 673 674 ### CDN Setup 675 676 See the [CDN Setup Doc][cdn] for details on the services Porter uses to 677 host and distribute its release binaries. 678 679 ### Custom Windows CI Agent 680 681 Some of our tests need to run on Windows, like the Smoke Tests - Windows stage of our build pipeline. 682 We use a custom Windows agent registered with Azure Pipelines that we build and maintain ourselves. 683 See the [Custom Windows CI Agent] documentation for details on how the agent is created and configured. 684 685 ### Releases 686 687 Our [version strategy] explains how we version the project, when you should expect 688 breaking changes in a release, and the process for the v1 release. 689 690 [cdn]: https://porter.sh/src/infra/cdn.md 691 [version strategy]: https://porter.sh/references/version-strategy/ 692 [Custom Windows CI Agent]: https://porter.sh/src/infra/custom-windows-ci-agent.md