get.porter.sh/porter@v1.3.0/tests/integration/build_test.go (about) 1 //go:build integration 2 3 package integration 4 5 import ( 6 "encoding/json" 7 "os" 8 "path/filepath" 9 "strings" 10 "testing" 11 12 "get.porter.sh/porter/pkg" 13 "get.porter.sh/porter/pkg/build" 14 "get.porter.sh/porter/pkg/cnab" 15 "get.porter.sh/porter/pkg/yaml" 16 "get.porter.sh/porter/tests" 17 "get.porter.sh/porter/tests/tester" 18 "github.com/Masterminds/semver/v3" 19 "github.com/stretchr/testify/require" 20 "github.com/uwu-tools/magex/shx" 21 ) 22 23 func TestBuild(t *testing.T) { 24 test, err := tester.NewTest(t) 25 defer test.Close() 26 require.NoError(t, err, "test setup failed") 27 28 bunPath := filepath.Join(test.RepoRoot, "tests/testdata/mybuns/*") 29 require.NoError(t, shx.Copy(bunPath, test.TestDir, shx.CopyRecursive)) 30 test.Chdir(test.TestDir) 31 32 // build the bundle 33 _, output := test.RequirePorter("build", "--custom", "customKey1=editedCustomValue1", "--no-lint", "--name=porter-test-build") 34 35 // Validate that the custom value defined in porter.yaml was injected into the build as a build argument 36 tests.RequireOutputContains(t, output, "CUSTOM_APP_VERSION=1.2.3") 37 38 // Validate that the bundle metadata contains the custom key specified by the user with --custom 39 bun, err := cnab.LoadBundle(test.TestContext.Context, build.LOCAL_BUNDLE) 40 require.NoError(t, err) 41 require.Equal(t, bun.Custom["customKey1"], "editedCustomValue1") 42 43 } 44 45 // This test uses build and the --no-lint flag, which is not a global flag defined on config.DataStore, 46 // to validate that when a flag value is set via the configuration file, environment variable or directly with the flag 47 // that the value binds properly to the variable. 48 // It is a regression test for our cobra+viper configuration setup and was created in response to this regression 49 // https://github.com/getporter/porter/issues/2735 50 func TestBuild_ConfigureNoLintThreeWays(t *testing.T) { 51 test, err := tester.NewTest(t) 52 defer test.Close() 53 require.NoError(t, err, "test setup failed") 54 55 // Use a bundle that will trigger a lint error, it can only be successfully built when --no-lint is set 56 require.NoError(t, shx.Copy("testdata/bundles/bundle-with-lint-error/porter.yaml", test.TestDir)) 57 test.Chdir(test.TestDir) 58 59 // Attempt to build the bundle, it should fail with a lint error 60 _, _, err = test.RunPorter("build") 61 require.ErrorContains(t, err, "lint errors were detected") 62 63 // Build the bundle and disable the linter with --no-lint 64 test.RequirePorter("build", "--no-lint") 65 66 // Build the bundle and disable the linter with PORTER_NO_LINT 67 _, _, err = test.RunPorterWith(func(cmd *shx.PreparedCommand) { 68 cmd.Args("build").Env("PORTER_NO_LINT=true") 69 }) 70 require.NoError(t, err, "expected the build to pass when PORTER_NO_LINT=true is specified") 71 72 // Build the bundle and disable the linter with the configuration file 73 disableAutoBuildCfg := []byte(`no-lint: true`) 74 err = os.WriteFile(filepath.Join(test.PorterHomeDir, "config.yaml"), disableAutoBuildCfg, pkg.FileModeWritable) 75 require.NoError(t, err, "Failed to write out the porter configuration file") 76 test.RequirePorter("build") 77 } 78 79 func TestRebuild(t *testing.T) { 80 test, err := tester.NewTest(t) 81 defer test.Close() 82 require.NoError(t, err, "test setup failed") 83 84 // Create a bundle 85 test.Chdir(test.TestDir) 86 test.RequirePorter("create") 87 88 // Edit the bundle to use more than one mixin 89 // This helps us test that when we calculate the manifestDigest that it consistently sorts used mixins 90 test.EditYaml("porter.yaml", func(yq *yaml.Editor) error { 91 n, err := yq.GetNode("mixins") 92 require.NoError(t, err, "could not get mixins node for porter.yaml") 93 testMixin := *n.Content[0] 94 testMixin.Value = "testmixin" 95 n.Content = append(n.Content, &testMixin) 96 return nil 97 }) 98 99 // Use a unique name with it so that if other tests install a newly created hello 100 // world bundle, they don't conflict 101 installationName := t.Name() 102 103 // Modify the porter.yaml to trigger a rebuild 104 bumpBundle := func() { 105 test.EditYaml("porter.yaml", func(yq *yaml.Editor) error { 106 orig, err := yq.GetValue("version") 107 require.NoError(t, err, "unable to read the bundle version from porter.yaml in order to bump it") 108 109 v, err := semver.NewVersion(orig) 110 require.NoErrorf(t, err, "error reading %s as a semver version", orig) 111 112 return yq.SetValue("version", v.IncPatch().String()) 113 }) 114 } 115 116 // Try to explain the bundle without building first, it should fail 117 _, output, err := test.RunPorter("explain", "--autobuild-disabled") 118 require.ErrorContains(t, err, "Attempted to use a bundle from source without building it first when --autobuild-disabled is set. Build the bundle and try again") 119 require.NotContains(t, output, "Building bundle ===>") 120 121 // Explain the bundle 122 _, output = test.RequirePorter("explain") 123 tests.RequireOutputContains(t, output, "Building bundle ===>", "expected a build before explain") 124 125 // Explain the bundle a bunch more times, it should not rebuild again. 126 // This is a regression test for a bug where the manifest would be considered out-of-date when nothing had changed 127 // caused by us using a go map when comparing the mixins used in the bundle, which has inconsistent sort order... 128 129 for i := 0; i < 10; i++ { 130 _, output = test.RequirePorter("explain") 131 tests.RequireOutputContains(t, output, "Bundle is up-to-date!", "expected the previous build to be reused") 132 } 133 134 bumpBundle() 135 136 // Explain the bundle, with --autobuild-disabled. It should work since the bundle has been built 137 explainJson, output := test.RequirePorter("explain", "--autobuild-disabled", "-o=json", "--verbosity=warn") 138 tests.RequireOutputContains(t, output, "WARNING: The bundle is out-of-date. Skipping autobuild because --autobuild-disabled was specified") 139 require.NotContains(t, output, "Building bundle ===>") 140 // todo(kichristensen): in the future this should be improved 141 explainJson = strings.ReplaceAll(explainJson, "WARNING: The bundle is out-of-date. Skipping autobuild because --autobuild-disabled was specified", "") 142 var explainResult map[string]interface{} 143 err = json.Unmarshal([]byte(explainJson), &explainResult) 144 require.NoError(t, err, "could not marshal explain output as json") 145 require.Equal(t, "0.1.0", explainResult["version"], "explain should show stale output because we used --autobuild-disabled") 146 147 // Inspect the bundle 148 _, output = test.RequirePorter("inspect") 149 tests.RequireOutputContains(t, output, "Building bundle ===>", "expected a build before inspect") 150 151 bumpBundle() 152 153 // Generate credentials for the bundle 154 _, output = test.RequirePorter("credentials", "generate", installationName) 155 tests.RequireOutputContains(t, output, "Building bundle ===>", "expected a build before credentials generate") 156 157 bumpBundle() 158 159 // Generate parameters for the bundle 160 _, output = test.RequirePorter("parameters", "generate", installationName) 161 tests.RequireOutputContains(t, output, "Building bundle ===>", "expected a build before parameters generate") 162 163 bumpBundle() 164 165 // Install the bundle 166 _, output = test.RequirePorter("install", installationName) 167 tests.RequireOutputContains(t, output, "Building bundle ===>", "expected a build before install") 168 169 bumpBundle() 170 171 // Upgrade the bundle 172 _, output = test.RequirePorter("upgrade", installationName) 173 tests.RequireOutputContains(t, output, "Building bundle ===>", "expected a rebuild before upgrade") 174 175 // Upgrade again, should not trigger a rebuild 176 _, output = test.RequirePorter("upgrade", installationName) 177 require.NotContains(t, output, "Building bundle ===>", "the second upgrade should not rebuild because the bundle wasn't changed") 178 179 bumpBundle() 180 181 // Uninstall the bundle 182 _, output = test.RequirePorter("uninstall", installationName) 183 tests.RequireOutputContains(t, output, "Building bundle ===>", "expected a rebuild before uninstall") 184 }