From 08ae47d7090dd51ad7e544b7c645ba6c3dd19bd8 Mon Sep 17 00:00:00 2001 From: Arhell Date: Mon, 8 Apr 2024 00:25:16 +0300 Subject: [PATCH 01/10] fix iframe video on mobile Signed-off-by: Arhell --- docs/assets/css/custom.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/assets/css/custom.css b/docs/assets/css/custom.css index 36e5e498c..f6c4de2b4 100644 --- a/docs/assets/css/custom.css +++ b/docs/assets/css/custom.css @@ -1,3 +1,7 @@ :root { --primary-hue: 336deg; } + +.content iframe { + max-width: 100%; +} \ No newline at end of file From c9662e0e361eed4d094dd73e7f5196562c9614a1 Mon Sep 17 00:00:00 2001 From: Ihor Sychevskyi Date: Mon, 8 Apr 2024 17:56:45 +0300 Subject: [PATCH 02/10] update porter site to hextra v0.7.3 (#3061) Signed-off-by: Arhell --- docs/go.mod | 2 +- docs/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/go.mod b/docs/go.mod index 2c7a581f2..ebb43fb48 100644 --- a/docs/go.mod +++ b/docs/go.mod @@ -2,4 +2,4 @@ module github.com/getporter/porter go 1.20 -require github.com/imfing/hextra v0.4.0 // indirect +require github.com/imfing/hextra v0.7.3 // indirect diff --git a/docs/go.sum b/docs/go.sum index a920c7262..ad0bc42dc 100644 --- a/docs/go.sum +++ b/docs/go.sum @@ -1,2 +1,2 @@ -github.com/imfing/hextra v0.4.0 h1:IwPL9eRAn2ukdhgaJHe5fPm1L/U0c5i5JkyPkyOZ9Qk= -github.com/imfing/hextra v0.4.0/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI= +github.com/imfing/hextra v0.7.3 h1:dVGA1NTcWe+FaUMdrawEypPfrrmulq5NoK0we3nC330= +github.com/imfing/hextra v0.7.3/go.mod h1:cEfel3lU/bSx7lTE/+uuR4GJaphyOyiwNR3PTqFTXpI= From 5beb4670fd935eb7d187602f4b568dad4bfc5f0b Mon Sep 17 00:00:00 2001 From: Kim Christensen <2461567+kichristensen@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:16:23 +0200 Subject: [PATCH 03/10] Make the Contributing Guide play nice with website (#3063) The Contributing Guide is taken directly from CONTRIBUTING.md, while the formatting plays nice in the Github view, it breaks the ToC on the website. This changes changes the headings to make it work in both Github and on the website. Signed-off-by: Kim Christensen --- CONTRIBUTING.md | 86 ++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 890062160..b46af9e76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,9 +2,11 @@ --- * [How to help](#how-to-help) + * [Code of Conduct](#code-of-conduct) * [Find an issue](#find-an-issue) - * [Which branch to use](#which-branch-to-use) + * [Which branch to use](#which-branch-to-use) * [When to open a pull request](#when-to-open-a-pull-request) + * [How to test your pull request](#how-to-test-your-pull-request) * [How to get your pull request reviewed fast](#how-to-get-your-pull-request-reviewed-fast) * [Signing your commits](#signing-your-commits) * [The life of a pull request](#the-life-of-a-pull-request) @@ -14,23 +16,25 @@ * [Magefile explained](#magefile-explained) * [Test Porter](#test-porter) * [Install mixins](#install-mixins) + * [Plugin Debugging](#plugin-debugging) * [Preview documentation](#preview-documentation) - * [View a trace of a Porter command](#view-a-trace-of-a-porter-command) - * [Debug smoke tests](#debug-smoke-tests) * [Write a blog post](#write-a-blog-post) + * [View a trace of a Porter command](#view-a-trace-of-a-porter-command) + * [Debug Smoke Tests](#debug-smoke-tests) + * [Command Documentation](#command-documentation) + * [Work on the Porter Operator](#work-on-the-porter-operator) * [Code structure and practices](#code-structure-and-practices) * [What is the general code layout?](#what-is-the-general-code-layout) * [Logging](#logging) - * [Tracing sensitive data](#tracing-sensitive-data) + * [Tracing Sensitive Data](#tracing-sensitive-data) * [Breaking Changes](#breaking-changes) * [Infrastructure](#infrastructure) * [CDN Setup](#cdn-setup) * [Custom Windows CI Agent](#custom-windows-ci-agent) * [Releases](#releases) - --- -# How to help +## How to help We welcome your contributions and participation! If you aren't sure what to expect, here are some norms for our project so you feel more comfortable with @@ -41,7 +45,7 @@ through how to setup your developer environment, make a change and test it. [tutorial]: https://porter.sh/docs/contribute/tutorial/ -## Code of Conduct +### Code of Conduct The Porter community is governed by our [Code of Conduct][coc]. This includes but isn't limited to: the porter and related mixin repositories, @@ -49,7 +53,7 @@ slack, interactions on social media, project meetings, conferences and meetups. [coc]: https://porter.sh/src/CODE_OF_CONDUCT.md -## Find an issue +### Find an issue Use the [porter.sh/find-issue] link to find good first issues for new contributors and help wanted issues for our other contributors. @@ -89,7 +93,7 @@ When you create your first pull request, add your name to the bottom of our [roadmap]: https://porter.sh/src/README.md#roadmap [pep]: https://porter.sh/docs/contribute/proposals/ -## Which branch to use +### Which branch to use Unless the issue specifically mentions a branch, please create your feature branch from the **main** branch. @@ -104,7 +108,7 @@ git pull git checkout -b MY_FEATURE_BRANCH main ``` -## When to open a pull request +### When to open a pull request It's OK to submit a PR directly for problems such as misspellings or other things where the motivation/problem is unambiguous. @@ -122,7 +126,7 @@ $ porter newcommand [OPTIONAL] [--someflag VALUE] example output ``` -## How to test your pull request +### How to test your pull request We recommend running the following every time: @@ -139,7 +143,7 @@ mage TestIntegration If you want to know _all_ the targets that the CI runs, look at . -## How to get your pull request reviewed fast +### How to get your pull request reviewed fast 🚧 If you aren't done yet, create a draft pull request or put WIP in the title so that reviewers wait for you to finish before commenting. @@ -163,7 +167,7 @@ tackle it in a reasonable amount of time in a subsequent pull request. If you can't get to it soon, please create an issue and link to it from the pull request comment so that we don't collectively forget. -## Signing your commits +### Signing your commits You can automatically sign your commits to meet the DCO requirement for this project by running the following command: `mage SetupDCO`. @@ -202,7 +206,7 @@ repository, you can amend your commit with the sign-off by running git commit --amend -s ``` -## The life of a pull request +### The life of a pull request 1. You create a draft or WIP pull request. Reviewers will ignore it mostly unless you mention someone and ask for help. Feel free to open one and use @@ -236,7 +240,7 @@ you have issues in GitHub assigned to you. [canary]: https://porter.sh/install/#canary [Contributors team]: https://github.com/orgs/getporter/teams/contributors -### Follow-on PR +#### Follow-on PR A follow-on PR is a pull request that finishes up suggestions from another pull request. @@ -252,7 +256,7 @@ pull requests that last for months, and in general we try to not let "perfect be the enemy of the good". It's no fun to watch your work sit in purgatory, and it kills contributor momentum. -# Contribution Ladder +## Contribution Ladder Our [contribution ladder][ladder] defines the roles and responsibilities for this project and how to participate with the goal of moving from a user to a @@ -260,9 +264,9 @@ maintainer. [ladder]: https://porter.sh/src/CONTRIBUTION_LADDER.md -# Developer Tasks +## Developer Tasks -## Initial setup +### Initial setup We have a [tutorial] that walks you through how to set up your developer environment, make a change and test it. @@ -281,11 +285,11 @@ clone directly from the project. You now have canary builds of porter and all the mixins installed. -## Magefile explained +### Magefile explained Porter uses a cross-platform make alternative called [mage](https://magefile.org), where the targets are written in Go. -### Mage Targets +#### Mage Targets Mage targets are not case-sensitive, but in our docs we use camel case to make it easier to read. You can run either `mage TestSmoke` or `mage testsmoke` for @@ -315,12 +319,12 @@ example. [golden files]: https://ieftimov.com/post/testing-in-go-golden-files/ -## Test Porter +### Test Porter We have a few different kinds of tests in Porter. You can run all tests types with `mage test`. -### Unit Tests +#### Unit Tests ``` mage TestUnit @@ -332,7 +336,7 @@ appropriate for unit tests. Fast! πŸŽπŸ’¨ This takes about 15s - 3 minutes, depending on your computer hardware. -### Integration Tests +#### Integration Tests ``` mage TestIntegration @@ -365,7 +369,7 @@ The first failure is the relevant one, and stopping immediately makes it faster [hello smoke test]: https://github.com/getporter/porter/blob/main/tests/smoke/hello_test.go [tests/tester]: https://github.com/getporter/porter/blob/main/tests/tester/main.go#L46 -### Smoke Tests +#### Smoke Tests ``` mage testSmoke @@ -377,7 +381,7 @@ If you intend to change Porter code (not docs), we recommend running smoke tests Short! We want this to always be something you can run in under 3 minutes. -## Install mixins +### Install mixins When you run `mage build`, the canary\* build of mixins are automatically installed into your bin directory in the root of the repository. You can use @@ -385,7 +389,7 @@ installed into your bin directory in the root of the repository. You can use \* canary = most recent successful build of the "main" branch -## Plugin Debugging +### Plugin Debugging If you are developing a [plugin](https://porter.sh/plugins/) and you want to debug it follow these steps: @@ -407,7 +411,7 @@ When porter is run it will start delve and attach it to the plugin process, this exposes the delve API so that any delve client can connect to the server and debug the plugin. -## Preview documentation +### Preview documentation We use [Hugo](https://gohugo.io) to build our documentation site, and it is hosted on [Netlify](https://netlify.com). You don't have to install Hugo locally because the @@ -427,7 +431,7 @@ or use only Hugo We welcome your contribution to improve our documentation, and we hope it is an easy process! ❀️ -## Write a blog post +### Write a blog post Thank you for writing a post for our blog! πŸ™‡β€β™€οΈ Here's what you need to do to create a new blog post and then preview it: @@ -464,7 +468,7 @@ a new blog post and then preview it: Our pull request preview and the live site will not show posts with a date in the future. If you don't see your post, change the date to today's date. -## View a trace of a Porter command +### View a trace of a Porter command Porter can send trace data about the commands run to an OpenTelemetry backend. It can be very helpful when figuring out why a command failed because you can see the values of variables and stack traces. @@ -500,7 +504,7 @@ The smoke and integration tests will run with telemetry enabled when the PORTER_ [otel-jaeger bundle]: https://porter.sh/examples/src/otel-jaeger -## Debug Smoke Tests +### Debug Smoke Tests If you want to attach a debugger to Porter when it is running in a smoke test, first install delve: @@ -520,14 +524,14 @@ The default debugger port is `55942` which you can override with the `PORTER_DEB 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. 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). -## Command Documentation +### Command Documentation Our commands are documented at and that documentation is generated by our CLI. You should regenerate that documentation when you change any files in **cmd/porter** by running `mage DocsGen` which is run every time you run `mage build`. -## Work on the Porter Operator +### Work on the Porter Operator Instructions for building the Porter Operator from source are located in its repository: https://github.com/getporter/operator. Sometimes you may need to make changes to Porter and work on the Operator at the same time. @@ -554,7 +558,7 @@ spec: serviceAccount: porter-agent ``` -# Code structure and practices +## Code structure and practices Carolyn Van Slyck gave a talk about the design of Porter, [Designing Command-Line Tools People Love][porter-design] that you may find helpful in @@ -563,7 +567,7 @@ dependency injection and testing strategies. [porter-design]: https://carolynvanslyck.com/talks/#gocli -## What is the general code layout? +### What is the general code layout? * **cmd**: go here to add a new command or flag to porter or one of the mixins in this repository @@ -596,7 +600,7 @@ dependency injection and testing strategies. * **install**: Porter [installation](https://porter.sh/install) scripts * **tests** have Go-based integration tests. -## Logging +### Logging **Print to the `Out` property for informational messages and send debug messages to the `Err` property.** @@ -622,7 +626,7 @@ we send regular command output to `Out` and debug information to `Err`. It allows us to then run the command and see the debug output separately, like so `porter schema --debug 2> err.log`. -### Tracing Sensitive Data +#### Tracing Sensitive Data 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. In this case, do not use fmt.Println and instead use the open telemetry trace logger to include the data in attributes. @@ -648,7 +652,7 @@ In order to debug your code and see the sensitive data, you need to: 2. [Enable tracing with Jaeger](#view-a-trace-of-a-porter-command) 3. Run a porter command and then view the sensitive attributes in the trace data sent to Jaeger. -## Breaking Changes +### Breaking Changes Some changes in Porter break our compatibility with previous versions of Porter. When that happens, we need to release that change with a new major version number to indicate to users that it contains breaking changes. @@ -662,23 +666,23 @@ Here are some examples of breaking changes: 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. -# Infrastructure +## Infrastructure This section includes overviews of infrastructure Porter relies on, mostly intended for maintainers. -## CDN Setup +### CDN Setup See the [CDN Setup Doc][cdn] for details on the services Porter uses to host and distribute its release binaries. -## Custom Windows CI Agent +### Custom Windows CI Agent Some of our tests need to run on Windows, like the Smoke Tests - Windows stage of our build pipeline. We use a custom Windows agent registered with Azure Pipelines that we build and maintain ourselves. See the [Custom Windows CI Agent] documentation for details on how the agent is created and configured. -## Releases +### Releases Our [version strategy] explains how we version the project, when you should expect breaking changes in a release, and the process for the v1 release. From e7fdd770defac1b7cf2b96e97a50c9152e9493e8 Mon Sep 17 00:00:00 2001 From: Kim Christensen <2461567+kichristensen@users.noreply.github.com> Date: Mon, 8 Apr 2024 21:55:36 +0200 Subject: [PATCH 04/10] Lint error when dependency with same is defined multiple times (#3068) * Add lint for dependencies with same name Having multiple dependencies with the same name results in undefined behaviour. This change introduces a lint to ensure that no dependencies share the same name. Signed-off-by: Kim Christensen --------- Signed-off-by: Kim Christensen --- docs/content/docs/references/linter.md | 11 ++++ go.sum | 4 -- pkg/linter/linter.go | 22 +++++++ pkg/linter/linter_test.go | 60 +++++++++++++++++++ tests/integration/lint_test.go | 12 ++++ .../porter.yaml | 40 +++++++++++++ 6 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 tests/integration/testdata/bundles/bundle-with-samenamedeps-lint-error/porter.yaml diff --git a/docs/content/docs/references/linter.md b/docs/content/docs/references/linter.md index 955c7412d..51e59550e 100644 --- a/docs/content/docs/references/linter.md +++ b/docs/content/docs/references/linter.md @@ -30,3 +30,14 @@ Using a reserved prefix can be problematic as it can overwrite a predefined para To fix the problem indicated by the porter-100 error, you should replace the prefix of any newly defined parameters to not start with "porter". You can find more information about parameters in following URL: https://porter.sh/quickstart/parameters/. + +## porter-102 + +The porter-102 error is a message generated by the porter lint command when it detects that multiple dependencies are defined with the same +name. + +Multiple dependencies with the same name results in undefined behaviour. + +To fix the problem, you should name ensure all dependencies have different names. + +You can find more information about dependencies in [Dependencies](/docs/development/authoring-a-bundle/working-with-dependencies/). diff --git a/go.sum b/go.sum index 4a2695a96..d4298ce4b 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -get.porter.sh/magefiles v0.6.2 h1:kHuurvykssL6iZsE5S2XLtTsps79h9D4rrxDSCiHOU8= -get.porter.sh/magefiles v0.6.2/go.mod h1:YsSlQWtGoXCGC4pdD7NxPpvh/FryM1bM0wzMWlJC+Bg= get.porter.sh/magefiles v0.6.3 h1:OE9YqCArn9fvM+VdanGlXNyIjy2F8W4yJGy5kcC/xD0= get.porter.sh/magefiles v0.6.3/go.mod h1:w37oTKICvvaEKR5KVB9UfN2EX30uYO9Qk0oRoz80DOU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= @@ -565,8 +563,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= diff --git a/pkg/linter/linter.go b/pkg/linter/linter.go index 20c8958b2..f96870415 100644 --- a/pkg/linter/linter.go +++ b/pkg/linter/linter.go @@ -186,6 +186,28 @@ func (l *Linter) Lint(ctx context.Context, m *manifest.Manifest) (Results, error ctx, span := tracing.StartSpan(ctx) defer span.EndSpan() + deps := make(map[string]interface{}, len(m.Dependencies.Requires)) + for _, dep := range m.Dependencies.Requires { + if _, exists := deps[dep.Name]; exists { + res := Result{ + Level: LevelError, + Location: Location{ + Action: "", + Mixin: "", + StepNumber: 0, + StepDescription: "", + }, + Code: "porter-102", + Title: "Dependency error", + Message: fmt.Sprintf("The dependency %s is defined multiple times", dep.Name), + URL: "https://porter.sh/reference/linter/#porter-102", + } + results = append(results, res) + } else { + deps[dep.Name] = nil + } + } + span.Debug("Running linters for each mixin used in the manifest...") q := query.New(l.Context, l.Mixins) responses, err := q.Execute(ctx, "lint", query.NewManifestGenerator(m)) diff --git a/pkg/linter/linter_test.go b/pkg/linter/linter_test.go index d29f55013..c8f3afe6b 100644 --- a/pkg/linter/linter_test.go +++ b/pkg/linter/linter_test.go @@ -173,3 +173,63 @@ func TestLinter_Lint(t *testing.T) { require.NotContains(t, results[0].String(), ": 0th step in the mixin ()") }) } + +func TestLinter_DependencyMultipleTimes(t *testing.T) { + t.Run("dependency defined multiple times", func(t *testing.T) { + cxt := portercontext.NewTestContext(t) + mixins := mixin.NewTestMixinProvider() + l := New(cxt.Context, mixins) + + m := &manifest.Manifest{ + Dependencies: manifest.Dependencies{ + Requires: []*manifest.Dependency{ + {Name: "mysql"}, + {Name: "mysql"}, + }, + }, + } + + expectedResult := Results{ + { + Code: "porter-102", + Title: "Dependency error", + Message: "The dependency mysql is defined multiple times", + URL: "https://porter.sh/reference/linter/#porter-102", + }, + } + + results, err := l.Lint(context.Background(), m) + require.NoError(t, err, "Lint failed") + require.Len(t, results, 1, "linter should have returned 1 result") + require.Equal(t, expectedResult, results, "unexpected lint results") + }) + t.Run("no dependency defined multiple times", func(t *testing.T) { + cxt := portercontext.NewTestContext(t) + mixins := mixin.NewTestMixinProvider() + l := New(cxt.Context, mixins) + + m := &manifest.Manifest{ + Dependencies: manifest.Dependencies{ + Requires: []*manifest.Dependency{ + {Name: "mysql"}, + {Name: "mongo"}, + }, + }, + } + + results, err := l.Lint(context.Background(), m) + require.NoError(t, err, "Lint failed") + require.Len(t, results, 0, "linter should have returned 0 result") + }) + t.Run("no dependencies", func(t *testing.T) { + cxt := portercontext.NewTestContext(t) + mixins := mixin.NewTestMixinProvider() + l := New(cxt.Context, mixins) + + m := &manifest.Manifest{} + + results, err := l.Lint(context.Background(), m) + require.NoError(t, err, "Lint failed") + require.Len(t, results, 0, "linter should have returned 0 result") + }) +} diff --git a/tests/integration/lint_test.go b/tests/integration/lint_test.go index 2f9cd2920..4d676110d 100644 --- a/tests/integration/lint_test.go +++ b/tests/integration/lint_test.go @@ -36,3 +36,15 @@ func TestLint(t *testing.T) { require.NotContains(t, output, "unknown command", "an unsupported mixin command should not be printed to the console in info") } + +func TestLint_DependenciesSameName(t *testing.T) { + test, err := tester.NewTest(t) + defer test.Close() + require.NoError(t, err, "test setup failed") + + _, output, _ := test.RunPorterWith(func(cmd *shx.PreparedCommand) { + cmd.Args("lint") + cmd.In(filepath.Join(test.RepoRoot, "tests/integration/testdata/bundles/bundle-with-samenamedeps-lint-error")) + }) + require.Contains(t, output, "error(porter-102) - Dependency error", "multiple dependencies with the same name should be an error") +} diff --git a/tests/integration/testdata/bundles/bundle-with-samenamedeps-lint-error/porter.yaml b/tests/integration/testdata/bundles/bundle-with-samenamedeps-lint-error/porter.yaml new file mode 100644 index 000000000..20168dd81 --- /dev/null +++ b/tests/integration/testdata/bundles/bundle-with-samenamedeps-lint-error/porter.yaml @@ -0,0 +1,40 @@ +# This bundle is designed to cause the porter lint/build commands to fail +schemaType: Bundle +schemaVersion: 1.0.1 +name: exec-mixin-lint-error +version: 0.1.0 +description: "This bundle is designed to cause the porter lint/build commands to fail, use --no-lint to use it anyway" +registry: "localhost:5000" + +mixins: + - exec + +dependencies: + requires: + - bundle: + reference: ghcr.io/getporter/porter-hello:v0.2.0 + name: samename + - bundle: + reference: ghcr.io/getporter/porter-hello:v0.2.0 + name: samename + +install: + - exec: + description: trigger a lint error + command: echo + arguments: + - install + +upgrade: + - exec: + description: "World 2.0" + command: echo + arguments: + - upgrade + +uninstall: + - exec: + description: "Uninstall Hello World" + command: echo + arguments: + - uninstall \ No newline at end of file From 40af48ccd3a01f1a2e91636c95b5842573ad18b5 Mon Sep 17 00:00:00 2001 From: schristoff <28318173+schristoff@users.noreply.github.com> Date: Mon, 8 Apr 2024 16:21:00 -0600 Subject: [PATCH 05/10] (chore): Add security documentation (#3047) * (chore): Add security documentation Signed-off-by: schristoff <28318173+schristoff@users.noreply.github.com> --------- Signed-off-by: schristoff <28318173+schristoff@users.noreply.github.com> --- SECURITY.md | 36 ++++++++++++++++++++++++++++++++++++ SECURITY_CONTACTS.md | 17 +++++++++++++++++ embargo-policy.md | 30 ++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 SECURITY.md create mode 100644 SECURITY_CONTACTS.md create mode 100644 embargo-policy.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..9e9697f2e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,36 @@ +# Security policy + +## Communication + +We will publish known vulnerabilities through a [GitHub Security Advisory](https://github.com/getporter/porter/security/advisories) once they have been addressed to inform the community of their potential scope, impact, and mitigation. + +## Reporting a vulnerability + +Porter and its maintainers takes the security of the project seriously, and we appreciate your efforts to responsibly disclose your findings to us. + +> **Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them through our [private vulnerability reporting](https://github.com/getporter/porter/security/advisories/new) form. + +It should contain: + * description of the problem + * precise and detailed steps (include screenshots) that created the + problem + * the affected version(s) + * any possible mitigations, if known + You will receive a reply from one of the maintainers within **3 days** + acknowledging receipt of the email. + + You may be contacted by a Porter project maintainerto further discuss the reported item. + Please bear with us as we seek to understand the breadth and scope of the + reported problem, recreate it, and confirm if there is a vulnerability + present. + + +This project follows a **10 disclosure timeline**. Refer to our [embargo policy](./embargo-policy.md) for more information. + +## Supported Versions + +Porter remains in the process of getting to a stable v1.0 release, and as such does not currently provide a long-term supported version. +We make a good faith effort to respond to security issues in a timely manner and will release version updates as needed to address them. +Users should expect to upgrade to the latest release version to stay current on security updates. \ No newline at end of file diff --git a/SECURITY_CONTACTS.md b/SECURITY_CONTACTS.md new file mode 100644 index 000000000..dd962b4d1 --- /dev/null +++ b/SECURITY_CONTACTS.md @@ -0,0 +1,17 @@ +# Security Contacts + +Defined below are the security persons of contact for this project. If you have +questions regarding the triaging and handling of incoming problems, they may be +contacted. + +The following security contacts have agreed to abide by the [Embargo Policy](./embargo-policy.md) +and will be removed and replaced if found to be in violation of that agreement. + +DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, USE THE +INSTRUCTIONS AT [VULNERABILITY REPORTING FORM](https://github.com/getporter/porter/security/advisories/new) + +Security Contacts: + +* [Sarah Christoff](https://github.com/schristoff) +* [Steven Gettys](https://github.com/sgettys) +* [Brian DeGeeter](https://github.com/bdegeeter) \ No newline at end of file diff --git a/embargo-policy.md b/embargo-policy.md new file mode 100644 index 000000000..75cc8d6ba --- /dev/null +++ b/embargo-policy.md @@ -0,0 +1,30 @@ +# Embargo Policy + +This policy forbids members of this project's [security contacts](./SECURITY_CONTACTS.md) and others +defined below from sharing information outside of the security contacts and this +listing without need-to-know and advance notice. + +The information members and others receive from the list defined below must: + +* not be made public, +* not be shared, +* not be hinted at +* must be kept confidential and close held + +Except with the list's explicit approval. This holds true until the public +disclosure date/time that was agreed upon by the list. + +If information is inadvertently shared beyond what is allowed by this policy, +you are REQUIRED to inform the [security contacts](./SECURITY_CONTACTS.md) of exactly what +information leaked and to whom. A retrospective will take place after the leak +so we can assess how to not make this mistake in the future. + +Violation of this policy will result in the immediate removal and subsequent +replacement of you from this list or the Security Contacts. + +## Disclosure Timeline + +This project sustains a **10 disclosure timeline** to ensure we provide a +quality, tested release. On some occasions, we may need to extend this timeline +due to complexity of the problem, lack of expertise available, or other reasons. +Submitters will be notified if an extension occurs. \ No newline at end of file From 76980c45f22fba15010b7fd5c147583e5a3bf91d Mon Sep 17 00:00:00 2001 From: schristoff <28318173+schristoff@users.noreply.github.com> Date: Mon, 8 Apr 2024 18:16:47 -0600 Subject: [PATCH 06/10] (chore): Update contribution ladder with roles (#3060) * (chore): Update contribution ladder with roles Signed-off-by: schristoff <28318173+schristoff@users.noreply.github.com> --------- Signed-off-by: schristoff <28318173+schristoff@users.noreply.github.com> --- CONTRIBUTION_LADDER.md | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/CONTRIBUTION_LADDER.md b/CONTRIBUTION_LADDER.md index 2f9bf8185..f45bb2600 100644 --- a/CONTRIBUTION_LADDER.md +++ b/CONTRIBUTION_LADDER.md @@ -1,6 +1,7 @@ # Contribution Ladder --- +* [Roles](#roles) * [Community Member](#community-member) * [Contributor](#contributor) * [How to become a contributor](#how-to-become-a-contributor) @@ -10,6 +11,8 @@ * [Stepping Down/Emeritus Process](#stepping-downemeritus-process) * [Admin](#admin) * [How to become an admin](#admin) +* [Release Manager](#release-manager) + * [How to become an release manager](#how-to-become-a-release-manager) --- Our ladder defines the roles and responsibilities for this project and how to @@ -17,6 +20,16 @@ participate with the goal of moving from a user to a maintainer. You will need to gain people's trust, demonstrate your competence and understanding, and meet the requirements of the role. +## Roles +* Community Member +* Contributor +* Maintainer + * Porter Maintainer + * Porter Operator Maintainer + * Porter Wesbite Maintainer + * Porter Triage Lead +* Release Manager + ## Community Member Everyone is a community member! πŸ˜„ You've read this far so you are already ahead. πŸ’― @@ -67,6 +80,13 @@ please reach out to one or more of the contributors or maintainers. * Review pull requests. * Merge pull requests. +There are three sub-types of specialization that maintainers can have: + * Porter Maintainer - This is someone who focuses on [Porter Core](https://github.com/getporter/porter) functionality + * Porter Operator Maintainer - This is someone who focuses on [Porter Operator](https://github.com/getporter/operator) functionality + * Porter Wesbite Maintainer - This is someone who helps our frontend, which leverages Hugo. + * Porter Community Lead - This is someone who handles the development of the community through scheduling meetings, encouraging Porter activties within the community (talks, blogposts, etc), and is the face of Porter + * Porter Mixin & Plugins Specialist - This is someone who builds and maintains the mixins used to help Porter work with other tooling. + Maintainers also have additional responsibilities beyond just merging code: * Help foster a safe and welcoming environment for all project participants. @@ -89,6 +109,32 @@ Maintainers will do their best to regularly discuss promoting contributors. But don’t be shy, if you feel that this is you, please reach out to one or more of the maintainers. +## Release Managers + +[Release Managers][release managers] can be either contributors or maintainers. +Porter releases on a quarterly candence, and a release manager handles kicking off +the release process & communicating the release. The release manager role is set **per** +release. + +Release Manager responsibilities are: +* Help foster a safe and welcoming environment for all project participants. + This will include understanding and enforcing our [Code of Conduct](CODE_OF_CONDUCT.md). +* Start, and if necessary, troubleshoot the [release process](./GOVERNANCE.md#release-process) for that release +* Communicate through channels (Slack, [Groups](https://groups.io/g/porter), and website) +with key achievements in that release +* Update [release documentation](./GOVERNANCE.md#release-process) with any new findings + + +[release managers]: https://github.com/orgs/getporter/teams/release + +### How to become a release manager + +Anyone can become a release manager, all you have to do is reach out to a maintainer +who will give you the proper documentation, help you identify the release date and be +available on the date of the release. It is recommended release managers try to sign up +for at least 2 (two) releases, so they can get comfortable with the release process. + + ## Inactivity It is important for maintainers to stay active to set an example and show commitment to the project. Inactivity is harmful to the project as it may lead to unexpected delays, contributor attrition, and a lost of trust in the project. From 7310b188dba017c3cc922b7ca86ed012d99e8ecd Mon Sep 17 00:00:00 2001 From: Kim Christensen <2461567+kichristensen@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:21:51 +0200 Subject: [PATCH 07/10] Improve error message on malformed step (#3052) Signed-off-by: Kim Christensen --- pkg/manifest/manifest.go | 7 ++++--- pkg/manifest/manifest_test.go | 14 +++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/pkg/manifest/manifest.go b/pkg/manifest/manifest.go index cdb487c09..d36184096 100644 --- a/pkg/manifest/manifest.go +++ b/pkg/manifest/manifest.go @@ -23,6 +23,7 @@ import ( "github.com/cbroglie/mustache" "github.com/cnabio/cnab-go/bundle" "github.com/cnabio/cnab-go/bundle/definition" + "github.com/dustin/go-humanize" "github.com/hashicorp/go-multierror" "github.com/opencontainers/go-digest" "go.opentelemetry.io/otel/attribute" @@ -986,10 +987,10 @@ type BundleOutput struct { type Steps []*Step func (s Steps) Validate(m *Manifest) error { - for _, step := range s { + for i, step := range s { err := step.Validate(m) if err != nil { - return err + return fmt.Errorf("failed to validate %s step: %s", humanize.Ordinal(i+1), err) } } return nil @@ -1007,7 +1008,7 @@ func (s *Step) Validate(m *Manifest) error { return errors.New("no mixin specified") } if len(s.Data) > 1 { - return errors.New("more than one mixin specified") + return errors.New("malformed step, possibly incorrect indentation") } mixinDeclared := false diff --git a/pkg/manifest/manifest_test.go b/pkg/manifest/manifest_test.go index 81cbf73b0..03af35007 100644 --- a/pkg/manifest/manifest_test.go +++ b/pkg/manifest/manifest_test.go @@ -144,7 +144,7 @@ func TestAction_Validate_RequireMixinDeclaration(t *testing.T) { m.Mixins = []MixinDeclaration{} err = m.Install.Validate(m) - assert.EqualError(t, err, "mixin (exec) was not declared") + assert.EqualError(t, err, "failed to validate 1st step: mixin (exec) was not declared") } func TestAction_Validate_RequireMixinData(t *testing.T) { @@ -159,7 +159,7 @@ func TestAction_Validate_RequireMixinData(t *testing.T) { m.Install[0].Data = nil err = m.Install.Validate(m) - assert.EqualError(t, err, "no mixin specified") + assert.EqualError(t, err, "failed to validate 1st step: no mixin specified") } func TestAction_Validate_RequireSingleMixinData(t *testing.T) { @@ -174,7 +174,7 @@ func TestAction_Validate_RequireSingleMixinData(t *testing.T) { m.Install[0].Data["rando-mixin"] = "" err = m.Install.Validate(m) - assert.EqualError(t, err, "more than one mixin specified") + assert.EqualError(t, err, "failed to validate 1st step: malformed step, possibly incorrect indentation") } func TestAction_Validate_RequireSingleMixinData_Actions(t *testing.T) { @@ -211,7 +211,7 @@ func TestAction_Validate_RequireSingleMixinData_Actions(t *testing.T) { (*step)[0].Data["rando-mixin"] = "" err = m.Validate(ctx, c.Config) - assert.ErrorContains(t, err, "more than one mixin specified") + assert.ErrorContains(t, err, "malformed step, possibly incorrect indentation") }) } } @@ -222,7 +222,7 @@ func TestManifest_Empty_Steps(t *testing.T) { c.TestContext.AddTestFile("testdata/empty-steps.yaml", config.Name) _, err := LoadManifestFrom(context.Background(), c.Config, config.Name) - assert.EqualError(t, err, "3 errors occurred:\n\t* validation of action \"install\" failed: found an empty step\n\t* validation of action \"uninstall\" failed: found an empty step\n\t* validation of action \"status\" failed: found an empty step\n\n") + assert.EqualError(t, err, "3 errors occurred:\n\t* validation of action \"install\" failed: failed to validate 2nd step: found an empty step\n\t* validation of action \"uninstall\" failed: failed to validate 2nd step: found an empty step\n\t* validation of action \"status\" failed: failed to validate 1st step: found an empty step\n\n") } func TestManifest_Validate_Name(t *testing.T) { @@ -240,7 +240,7 @@ func TestManifest_Validate_Description(t *testing.T) { c.TestContext.AddTestFile("testdata/porter-with-bad-description.yaml", config.Name) _, err := LoadManifestFrom(context.Background(), c.Config, config.Name) - assert.ErrorContains(t, err, "validation of action \"install\" failed: invalid description type (string) for mixin step (exec)") + assert.ErrorContains(t, err, "validation of action \"install\" failed: failed to validate 1st step: invalid description type (string) for mixin step (exec)") } func TestManifest_Validate_InvalidType(t *testing.T) { @@ -250,7 +250,7 @@ func TestManifest_Validate_InvalidType(t *testing.T) { assert.NotPanics(t, func() { _, err := LoadManifestFrom(context.Background(), c.Config, config.Name) - assert.ErrorContains(t, err, "validation of action \"install\" failed: invalid mixin type (string) for mixin step (exec)") + assert.ErrorContains(t, err, "validation of action \"install\" failed: failed to validate 1st step: invalid mixin type (string) for mixin step (exec)") }) } From e896bc343893bb12912289732e586d4402e42b99 Mon Sep 17 00:00:00 2001 From: Kim Christensen <2461567+kichristensen@users.noreply.github.com> Date: Wed, 10 Apr 2024 01:08:49 +0200 Subject: [PATCH 08/10] Reenable bundle reuse test (#3072) No matter what I try I cannot get this test to fail anymore. Tried to increase the iterations to 100 without getting any fails, not in Github Actions or locally. Based on that the test is reenabled, and then it should be monitored if the build becomes unstable again. Signed-off-by: Kim Christensen --- tests/integration/build_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/integration/build_test.go b/tests/integration/build_test.go index b6ac129db..dd9328c2b 100644 --- a/tests/integration/build_test.go +++ b/tests/integration/build_test.go @@ -125,11 +125,10 @@ func TestRebuild(t *testing.T) { // This is a regression test for a bug where the manifest would be considered out-of-date when nothing had changed // caused by us using a go map when comparing the mixins used in the bundle, which has inconsistent sort order... - //todo: This test is flaky still and upsetting CI - // for i := 0; i < 5; i++ { - // _, output = test.RequirePorter("explain") - // tests.RequireOutputContains(t, output, "Bundle is up-to-date!", "expected the previous build to be reused") - // } + for i := 0; i < 10; i++ { + _, output = test.RequirePorter("explain") + tests.RequireOutputContains(t, output, "Bundle is up-to-date!", "expected the previous build to be reused") + } bumpBundle() From 4f540b81c7851ddcb2728893b7f10293f498fd02 Mon Sep 17 00:00:00 2001 From: Kim Christensen <2461567+kichristensen@users.noreply.github.com> Date: Wed, 10 Apr 2024 01:11:19 +0200 Subject: [PATCH 09/10] Lint for parameters being used in actions to which they don't apply (#3034) * Lint for parameters being used in actions to which they don't apply Signed-off-by: Kim Christensen --------- Signed-off-by: Kim Christensen --- docs/content/docs/references/linter.md | 30 +++++ pkg/linter/linter.go | 76 +++++++++++ pkg/linter/linter_test.go | 123 ++++++++++++++++++ pkg/manifest/manifest.go | 34 ++++- tests/integration/lint_test.go | 11 ++ .../porter.yaml | 39 ++++++ 6 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 tests/integration/testdata/bundles/bundle-with-param-apply-lint-error/porter.yaml diff --git a/docs/content/docs/references/linter.md b/docs/content/docs/references/linter.md index 51e59550e..408e75ecf 100644 --- a/docs/content/docs/references/linter.md +++ b/docs/content/docs/references/linter.md @@ -6,6 +6,8 @@ weight: 9 - [exec-100](#exec-100) - [porter-100](#porter-100) +- [porter-101](#porter-101) +- [porter-102](#porter-102) ## exec-100 @@ -31,6 +33,33 @@ To fix the problem indicated by the porter-100 error, you should replace the pre You can find more information about parameters in following URL: https://porter.sh/quickstart/parameters/. +## porter-101 + +The porter-101 error suggests that an action uses a parameter that is not available to it. + +This is an of a manifest triggering the error (shorten for brevity): + +```yaml +parameters: + - name: uninstallParam + type: string + applyTo: + - uninstall # Notice the parameter only applies to the uninstall action + +install: + - exec: + description: "Install Hello World" + command: ./helpers.sh + arguments: + - install + - "${ bundle.parameters.uninstallParam }" +``` + +To fix the problem indicated by the porter-101 error, you should ensure that all parameters used in the action applies to the actions where +it is referenced. + +You can find more information about applyTo in the following URL: https://porter.sh/docs/bundle/manifest/#parameter-types. + ## porter-102 The porter-102 error is a message generated by the porter lint command when it detects that multiple dependencies are defined with the same @@ -41,3 +70,4 @@ Multiple dependencies with the same name results in undefined behaviour. To fix the problem, you should name ensure all dependencies have different names. You can find more information about dependencies in [Dependencies](/docs/development/authoring-a-bundle/working-with-dependencies/). + diff --git a/pkg/linter/linter.go b/pkg/linter/linter.go index f96870415..f5e67f8c3 100644 --- a/pkg/linter/linter.go +++ b/pkg/linter/linter.go @@ -11,6 +11,7 @@ import ( "get.porter.sh/porter/pkg/pkgmgmt" "get.porter.sh/porter/pkg/portercontext" "get.porter.sh/porter/pkg/tracing" + "get.porter.sh/porter/pkg/yaml" "github.com/dustin/go-humanize" ) @@ -154,6 +155,11 @@ func New(cxt *portercontext.Context, mixins pkgmgmt.PackageManager) *Linter { } } +type action struct { + name string + steps manifest.Steps +} + func (l *Linter) Lint(ctx context.Context, m *manifest.Manifest) (Results, error) { // Check for reserved porter prefix on parameter names reservedPrefixes := []string{"porter-", "porter_"} @@ -183,9 +189,29 @@ func (l *Linter) Lint(ctx context.Context, m *manifest.Manifest) (Results, error } } } + + // Check if parameters apply to the steps ctx, span := tracing.StartSpan(ctx) defer span.EndSpan() + span.Debug("Validating that parameters applies to the actions...") + tmplParams := m.GetTemplatedParameters() + actions := []action{ + {"install", m.Install}, + {"upgrade", m.Upgrade}, + {"uninstall", m.Uninstall}, + } + for actionName, steps := range m.CustomActions { + actions = append(actions, action{actionName, steps}) + } + for _, action := range actions { + res, err := validateParamsAppliesToAction(m, action.steps, tmplParams, action.name) + if err != nil { + return nil, span.Error(fmt.Errorf("error validating action: %s", action.name)) + } + results = append(results, res...) + } + deps := make(map[string]interface{}, len(m.Dependencies.Requires)) for _, dep := range m.Dependencies.Requires { if _, exists := deps[dep.Name]; exists { @@ -235,3 +261,53 @@ func (l *Linter) Lint(ctx context.Context, m *manifest.Manifest) (Results, error return results, nil } + +func validateParamsAppliesToAction(m *manifest.Manifest, steps manifest.Steps, tmplParams manifest.ParameterDefinitions, actionName string) (Results, error) { + var results Results + for stepNumber, step := range steps { + data, err := yaml.Marshal(step.Data) + if err != nil { + return nil, fmt.Errorf("error during marshalling: %w", err) + } + + tmplResult, err := m.ScanManifestTemplating(data) + if err != nil { + return nil, fmt.Errorf("error parsing templating: %w", err) + } + + for _, variable := range tmplResult.Variables { + paramName, ok := m.GetTemplateParameterName(variable) + if !ok { + continue + } + + for _, tmplParam := range tmplParams { + if tmplParam.Name != paramName { + continue + } + if !tmplParam.AppliesTo(actionName) { + description, err := step.GetDescription() + if err != nil { + return nil, fmt.Errorf("error getting step description: %w", err) + } + res := Result{ + Level: LevelError, + Location: Location{ + Action: actionName, + Mixin: step.GetMixinName(), + StepNumber: stepNumber + 1, + StepDescription: description, + }, + Code: "porter-101", + Title: "Parameter does not apply to action", + Message: fmt.Sprintf("Parameter %s does not apply to %s action", paramName, actionName), + URL: "https://porter.sh/docs/references/linter/#porter-101", + } + results = append(results, res) + } + } + } + } + + return results, nil +} diff --git a/pkg/linter/linter_test.go b/pkg/linter/linter_test.go index c8f3afe6b..b26239636 100644 --- a/pkg/linter/linter_test.go +++ b/pkg/linter/linter_test.go @@ -2,6 +2,7 @@ package linter import ( "context" + "fmt" "testing" "get.porter.sh/porter/pkg/manifest" @@ -174,6 +175,128 @@ func TestLinter_Lint(t *testing.T) { }) } +func TestLinter_Lint_ParameterDoesNotApplyTo(t *testing.T) { + ctx := context.Background() + testCases := []struct { + action string + setSteps func(*manifest.Manifest, manifest.Steps) + }{ + {"install", func(m *manifest.Manifest, steps manifest.Steps) { m.Install = steps }}, + {"upgrade", func(m *manifest.Manifest, steps manifest.Steps) { m.Upgrade = steps }}, + {"uninstall", func(m *manifest.Manifest, steps manifest.Steps) { m.Uninstall = steps }}, + {"customAction", func(m *manifest.Manifest, steps manifest.Steps) { + m.CustomActions = make(map[string]manifest.Steps) + m.CustomActions["customAction"] = steps + }}, + } + + for _, tc := range testCases { + t.Run(tc.action, func(t *testing.T) { + cxt := portercontext.NewTestContext(t) + mixins := mixin.NewTestMixinProvider() + l := New(cxt.Context, mixins) + + param := map[string]manifest.ParameterDefinition{ + "doesNotApply": { + Name: "doesNotApply", + ApplyTo: []string{"dummy"}, + }, + } + steps := manifest.Steps{ + &manifest.Step{ + Data: map[string]interface{}{ + "exec": map[string]interface{}{ + "description": "exec step", + "parameters": []string{ + "\"${ bundle.parameters.doesNotApply }\"", + }, + }, + }, + }, + } + m := &manifest.Manifest{ + SchemaVersion: "1.0.1", + TemplateVariables: []string{"bundle.parameters.doesNotApply"}, + Parameters: param, + } + tc.setSteps(m, steps) + + lintResults := Results{ + { + Level: LevelError, + Location: Location{ + Action: tc.action, + Mixin: "exec", + StepNumber: 1, + StepDescription: "exec step", + }, + Code: "porter-101", + Title: "Parameter does not apply to action", + Message: fmt.Sprintf("Parameter doesNotApply does not apply to %s action", tc.action), + URL: "https://porter.sh/docs/references/linter/#porter-101", + }, + } + results, err := l.Lint(ctx, m) + require.NoError(t, err, "Lint failed") + require.Len(t, results, 1, "linter should have returned 1 result") + require.Equal(t, lintResults, results, "unexpected lint results") + }) + } +} + +func TestLinter_Lint_ParameterAppliesTo(t *testing.T) { + ctx := context.Background() + testCases := []struct { + action string + setSteps func(*manifest.Manifest, manifest.Steps) + }{ + {"install", func(m *manifest.Manifest, steps manifest.Steps) { m.Install = steps }}, + {"upgrade", func(m *manifest.Manifest, steps manifest.Steps) { m.Upgrade = steps }}, + {"uninstall", func(m *manifest.Manifest, steps manifest.Steps) { m.Uninstall = steps }}, + {"customAction", func(m *manifest.Manifest, steps manifest.Steps) { + m.CustomActions = make(map[string]manifest.Steps) + m.CustomActions["customAction"] = steps + }}, + } + + for _, tc := range testCases { + t.Run(tc.action, func(t *testing.T) { + cxt := portercontext.NewTestContext(t) + mixins := mixin.NewTestMixinProvider() + l := New(cxt.Context, mixins) + + param := map[string]manifest.ParameterDefinition{ + "appliesTo": { + Name: "appliesTo", + ApplyTo: []string{tc.action}, + }, + } + steps := manifest.Steps{ + &manifest.Step{ + Data: map[string]interface{}{ + "exec": map[string]interface{}{ + "description": "exec step", + "parameters": []string{ + "\"${ bundle.parameters.appliesTo }\"", + }, + }, + }, + }, + } + m := &manifest.Manifest{ + SchemaVersion: "1.0.1", + TemplateVariables: []string{"bundle.parameters.appliesTo"}, + Parameters: param, + } + tc.setSteps(m, steps) + + results, err := l.Lint(ctx, m) + require.NoError(t, err, "Lint failed") + require.Len(t, results, 0, "linter should have returned 1 result") + }) + } +} + func TestLinter_DependencyMultipleTimes(t *testing.T) { t.Run("dependency defined multiple times", func(t *testing.T) { cxt := portercontext.NewTestContext(t) diff --git a/pkg/manifest/manifest.go b/pkg/manifest/manifest.go index d36184096..690565a7b 100644 --- a/pkg/manifest/manifest.go +++ b/pkg/manifest/manifest.go @@ -282,6 +282,19 @@ func (m *Manifest) getTemplateDependencyOutputName(value string) (string, string return dependencyName, outputName, true } +var templatedParameterRegex = regexp.MustCompile(`^bundle\.parameters\.(.+)$`) + +// GetTemplateParameterName returns the parameter name from the template variable. +func (m *Manifest) GetTemplateParameterName(value string) (string, bool) { + matches := templatedParameterRegex.FindStringSubmatch(value) + if len(matches) < 2 { + return "", false + } + + parameterName := matches[1] + return parameterName, true +} + // GetTemplatedOutputs returns the output definitions for any bundle level outputs // that have been templated, keyed by the output name. func (m *Manifest) GetTemplatedOutputs() OutputDefinitions { @@ -315,6 +328,23 @@ func (m *Manifest) GetTemplatedDependencyOutputs() DependencyOutputReferences { return outputs } +// GetTemplatedParameters returns the output definitions for any bundle level outputs +// that have been templated, keyed by the output name. +func (m *Manifest) GetTemplatedParameters() ParameterDefinitions { + parameters := make(ParameterDefinitions, len(m.TemplateVariables)) + for _, tmplVar := range m.TemplateVariables { + if name, ok := m.GetTemplateParameterName(tmplVar); ok { + parameterDef, ok := m.Parameters[name] + if !ok { + // Only return bundle level definitions + continue + } + parameters[name] = parameterDef + } + } + return parameters +} + // DetermineDependenciesExtensionUsed looks for how dependencies are used // by the bundle and which version of the dependency extension can be used. func (m *Manifest) DetermineDependenciesExtensionUsed() string { @@ -1258,7 +1288,7 @@ func ReadManifest(cxt *portercontext.Context, path string) (*Manifest, error) { return nil, fmt.Errorf("unsupported property set or a custom action is defined incorrectly: %w", err) } - tmplResult, err := m.scanManifestTemplating(data) + tmplResult, err := m.ScanManifestTemplating(data) if err != nil { return nil, err } @@ -1294,7 +1324,7 @@ func (m *Manifest) GetTemplatePrefix() string { return "" } -func (m *Manifest) scanManifestTemplating(data []byte) (templateScanResult, error) { +func (m *Manifest) ScanManifestTemplating(data []byte) (templateScanResult, error) { const disableHtmlEscaping = true templateSrc := m.GetTemplatePrefix() + string(data) tmpl, err := mustache.ParseStringRaw(templateSrc, disableHtmlEscaping) diff --git a/tests/integration/lint_test.go b/tests/integration/lint_test.go index 4d676110d..b06888298 100644 --- a/tests/integration/lint_test.go +++ b/tests/integration/lint_test.go @@ -34,7 +34,18 @@ func TestLint(t *testing.T) { cmd.Env("PORTER_VERBOSITY=info") }) require.NotContains(t, output, "unknown command", "an unsupported mixin command should not be printed to the console in info") +} + +func TestLint_ApplyToParam(t *testing.T) { + test, err := tester.NewTest(t) + defer test.Close() + require.NoError(t, err, "test setup failed") + _, output, _ := test.RunPorterWith(func(cmd *shx.PreparedCommand) { + cmd.Args("lint") + cmd.In(filepath.Join(test.RepoRoot, "tests/integration/testdata/bundles/bundle-with-param-apply-lint-error")) + }) + require.Contains(t, output, "error(porter-101) - Parameter does not apply to action", "parameters being used in actions to which they don't apply should be an error") } func TestLint_DependenciesSameName(t *testing.T) { diff --git a/tests/integration/testdata/bundles/bundle-with-param-apply-lint-error/porter.yaml b/tests/integration/testdata/bundles/bundle-with-param-apply-lint-error/porter.yaml new file mode 100644 index 000000000..b8ed6a64f --- /dev/null +++ b/tests/integration/testdata/bundles/bundle-with-param-apply-lint-error/porter.yaml @@ -0,0 +1,39 @@ +# This bundle is designed to cause the porter lint/build commands to fail +schemaType: Bundle +schemaVersion: 1.0.1 +name: exec-mixin-lint-error +version: 0.1.0 +description: "This bundle is designed to cause the porter lint/build commands to fail, use --no-lint to use it anyway" +registry: "localhost:5000" + +mixins: + - exec + +parameters: + - name: onlyApplyToUninstall + description: Only applies to uninstall + type: string + default: appliesToUninstall + applyTo: + - uninstall + +install: + - exec: + description: trigger a lint error + command: echo + arguments: + - ${ bundle.parameters.onlyApplyToUninstall } + +upgrade: + - exec: + description: "World 2.0" + command: echo + arguments: + - upgrade + +uninstall: + - exec: + description: "Uninstall Hello World" + command: echo + arguments: + - uninstall From 8e14d0dde102de9992936203d898163aa11dd68b Mon Sep 17 00:00:00 2001 From: Ihor Sychevskyi Date: Thu, 11 Apr 2024 04:22:18 +0300 Subject: [PATCH 10/10] Accessibility add link name to Cloud Native image (#3077) Signed-off-by: Arhell --- docs/layouts/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/layouts/index.html b/docs/layouts/index.html index be4432baa..2eeb30a1f 100644 --- a/docs/layouts/index.html +++ b/docs/layouts/index.html @@ -94,7 +94,7 @@

We are a Cloud Native Computing Foundation Sandbox Project

- + {{- partial "utils/icon.html" (dict "name" "cncf" "attributes" "width=350") -}}