Repository: GoogleContainerTools/kpt
Pull request #3152 (2022-05-13 01:18:38)

chore: upgrade golangci-lint to v1.46.1
chore: upgrade golangci-lint to v1.46.1
    
- Fix new lint failures

chore: re-enable fixed linters
    
- whitespace
- dogsled
- bodyclose

chore: replace deprecated linters
    
- Replace golint with revive
- Replace scopelint with exportloopref
- Remove deprecated interfacer (no replacement)
- Skip linting thirdparty, to keep it closer to upstream
- Reduce stuttering in names
- Remove redundant types
- Avoid returning private types from public functions
- Replace +=1 with ++
- Remove unnecessary array init from Stack & PkgStack



Patch:
diff --git a/.golangci.yml b/.golangci.yml
index 30562a61..f43546b4 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -2,46 +2,46 @@
 
 run:
   deadline: 5m
+  skip-dirs:
+    thirdparty/
 
 linters:
   # please, do not use `enable-all`: it's deprecated and will be removed soon.
   # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
   disable-all: true
   enable:
-# bodyclose appears to be broken
-#    - bodyclose
+    - bodyclose
     - deadcode
     - depguard
-#    - dogsled
+    - dogsled
     - dupl
     - errcheck
 # funlen triggers on test functions which it shouldn't
 #    - funlen
+    - exportloopref
     - gochecknoinits
     - goconst
     - gocritic
     - gocyclo
     - gofmt
     - goimports
-    - golint
 #    - gosec
     - gosimple
     - govet
     - ineffassign
-    - interfacer
     - lll
     - misspell
     - nakedret
-    - scopelint
     - staticcheck
     - structcheck
     - stylecheck
+    - revive
     - typecheck
     - unconvert
     - unparam
     - unused
     - varcheck
-#    - whitespace
+    - whitespace
 
 issues:
   exclude:
diff --git a/Makefile b/Makefile
index cd6be768..70eb9e51 100644
--- a/Makefile
+++ b/Makefile
@@ -59,10 +59,10 @@ tidy:
 	go mod tidy
 
 license:
-	GOBIN=$(GOBIN) scripts/update-license.sh
+	scripts/update-license.sh
 
 lint:
-	(which golangci-lint || go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.31.0)
+	go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.1
 	$(GOBIN)/golangci-lint run ./...
 
 license-check:
diff --git a/firebase/functions/.eslintrc.js b/firebase/functions/.eslintrc.js
index 973030b2..e4c237e3 100644
--- a/firebase/functions/.eslintrc.js
+++ b/firebase/functions/.eslintrc.js
@@ -1,3 +1,19 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 module.exports = {
   root: true,
   env: {
diff --git a/firebase/functions/index.js b/firebase/functions/index.js
index eba5298c..90ec6100 100644
--- a/firebase/functions/index.js
+++ b/firebase/functions/index.js
@@ -1,3 +1,19 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 const functions = require("firebase-functions");
 
 
diff --git a/go.mod b/go.mod
index 7214e381..1949a278 100644
--- a/go.mod
+++ b/go.mod
@@ -15,6 +15,7 @@ require (
 	github.com/stretchr/testify v1.7.1
 	github.com/xlab/treeprint v1.1.0
 	golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3
+	golang.org/x/text v0.3.7
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 	gotest.tools v2.2.0+incompatible
 	k8s.io/api v0.24.0
@@ -94,7 +95,6 @@ require (
 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
 	golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
 	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
-	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
diff --git a/internal/builtins/testData/pkg-with-existing-ctx/in.yaml b/internal/builtins/testdata/pkg-with-existing-ctx/in.yaml
similarity index 100%
rename from internal/builtins/testData/pkg-with-existing-ctx/in.yaml
rename to internal/builtins/testdata/pkg-with-existing-ctx/in.yaml
diff --git a/internal/builtins/testData/pkg-with-existing-ctx/out.yaml b/internal/builtins/testdata/pkg-with-existing-ctx/out.yaml
similarity index 100%
rename from internal/builtins/testData/pkg-with-existing-ctx/out.yaml
rename to internal/builtins/testdata/pkg-with-existing-ctx/out.yaml
diff --git a/internal/builtins/testData/pkg-with-nesting/in.yaml b/internal/builtins/testdata/pkg-with-nesting/in.yaml
similarity index 100%
rename from internal/builtins/testData/pkg-with-nesting/in.yaml
rename to internal/builtins/testdata/pkg-with-nesting/in.yaml
diff --git a/internal/builtins/testData/pkg-with-nesting/out.yaml b/internal/builtins/testdata/pkg-with-nesting/out.yaml
similarity index 100%
rename from internal/builtins/testData/pkg-with-nesting/out.yaml
rename to internal/builtins/testdata/pkg-with-nesting/out.yaml
diff --git a/internal/builtins/testData/pkg-wo-nesting/in.yaml b/internal/builtins/testdata/pkg-wo-nesting/in.yaml
similarity index 100%
rename from internal/builtins/testData/pkg-wo-nesting/in.yaml
rename to internal/builtins/testdata/pkg-wo-nesting/in.yaml
diff --git a/internal/builtins/testData/pkg-wo-nesting/out.yaml b/internal/builtins/testdata/pkg-wo-nesting/out.yaml
similarity index 100%
rename from internal/builtins/testData/pkg-wo-nesting/out.yaml
rename to internal/builtins/testdata/pkg-wo-nesting/out.yaml
diff --git a/internal/cmdapply/cmdapply.go b/internal/cmdapply/cmdapply.go
index 3a5b7842..dc737bbe 100644
--- a/internal/cmdapply/cmdapply.go
+++ b/internal/cmdapply/cmdapply.go
@@ -39,9 +39,11 @@ import (
 )
 
 // NewRunner returns a command runner
-func NewRunner(ctx context.Context, factory util.Factory,
-	ioStreams genericclioptions.IOStreams) *Runner {
-
+func NewRunner(
+	ctx context.Context,
+	factory util.Factory,
+	ioStreams genericclioptions.IOStreams,
+) *Runner {
 	r := &Runner{
 		ctx:         ctx,
 		ioStreams:   ioStreams,
diff --git a/internal/cmddestroy/cmddestroy.go b/internal/cmddestroy/cmddestroy.go
index 56d51559..e0580924 100644
--- a/internal/cmddestroy/cmddestroy.go
+++ b/internal/cmddestroy/cmddestroy.go
@@ -34,9 +34,11 @@ import (
 	"sigs.k8s.io/cli-utils/pkg/printers"
 )
 
-func NewRunner(ctx context.Context, factory util.Factory,
-	ioStreams genericclioptions.IOStreams) *Runner {
-
+func NewRunner(
+	ctx context.Context,
+	factory util.Factory,
+	ioStreams genericclioptions.IOStreams,
+) *Runner {
 	r := &Runner{
 		ctx:           ctx,
 		ioStreams:     ioStreams,
diff --git a/internal/cmddiff/cmddiff.go b/internal/cmddiff/cmddiff.go
index ccf9b9c8..d33f2f47 100644
--- a/internal/cmddiff/cmddiff.go
+++ b/internal/cmddiff/cmddiff.go
@@ -87,14 +87,14 @@ func (r *Runner) preRunE(_ *cobra.Command, args []string) error {
 	}
 	if r.diffType == "" {
 		// pick sensible defaults for diff-type
-		r.DiffType = diff.DiffTypeLocal
+		r.DiffType = diff.TypeLocal
 		if version != "" {
 			// if target version is specified, default to 'combined' diff-type.
 			// xref: https://github.com/GoogleContainerTools/kpt/issues/139
-			r.DiffType = diff.DiffTypeCombined
+			r.DiffType = diff.TypeCombined
 		}
 	} else {
-		r.DiffType = diff.DiffType(r.diffType)
+		r.DiffType = diff.Type(r.diffType)
 	}
 
 	resolvedPath, err := argutil.ResolveSymlink(r.ctx, dir)
diff --git a/internal/cmdinstallrg/cmdinstallrg.go b/internal/cmdinstallrg/cmdinstallrg.go
index 5355333f..bff3f5da 100644
--- a/internal/cmdinstallrg/cmdinstallrg.go
+++ b/internal/cmdinstallrg/cmdinstallrg.go
@@ -26,9 +26,11 @@ import (
 )
 
 // NewRunner returns a command runner
-func NewRunner(ctx context.Context, factory cmdutil.Factory,
-	ioStreams genericclioptions.IOStreams) *Runner {
-
+func NewRunner(
+	ctx context.Context,
+	factory cmdutil.Factory,
+	ioStreams genericclioptions.IOStreams,
+) *Runner {
 	r := &Runner{
 		ctx:       ctx,
 		ioStreams: ioStreams,
@@ -46,8 +48,11 @@ func NewRunner(ctx context.Context, factory cmdutil.Factory,
 	return r
 }
 
-func NewCommand(ctx context.Context, factory cmdutil.Factory,
-	ioStreams genericclioptions.IOStreams) *cobra.Command {
+func NewCommand(
+	ctx context.Context,
+	factory cmdutil.Factory,
+	ioStreams genericclioptions.IOStreams,
+) *cobra.Command {
 	return NewRunner(ctx, factory, ioStreams).Command
 }
 
diff --git a/internal/cmdmigrate/migratecmd.go b/internal/cmdmigrate/migratecmd.go
index 63fd29b6..39466c94 100644
--- a/internal/cmdmigrate/migratecmd.go
+++ b/internal/cmdmigrate/migratecmd.go
@@ -54,9 +54,12 @@ type MigrateRunner struct {
 }
 
 // NewRunner returns a pointer to an initial MigrateRunner structure.
-func NewRunner(ctx context.Context, factory util.Factory, cmLoader manifestreader.ManifestLoader,
-	ioStreams genericclioptions.IOStreams) *MigrateRunner {
-
+func NewRunner(
+	ctx context.Context,
+	factory util.Factory,
+	cmLoader manifestreader.ManifestLoader,
+	ioStreams genericclioptions.IOStreams,
+) *MigrateRunner {
 	r := &MigrateRunner{
 		ctx:             ctx,
 		factory:         factory,
diff --git a/internal/cmdrpkgclone/command.go b/internal/cmdrpkgclone/command.go
index aeea071f..4a2392bf 100644
--- a/internal/cmdrpkgclone/command.go
+++ b/internal/cmdrpkgclone/command.go
@@ -123,7 +123,7 @@ func (r *runner) preRunE(cmd *cobra.Command, args []string) error {
 
 	case strings.Contains(source, "/"):
 		if parse.HasGitSuffix(source) { // extra parsing required
-			repo, dir, ref, err := parse.ParseURL(source)
+			repo, dir, ref, err := parse.URL(source)
 			if err != nil {
 				return err
 			}
diff --git a/internal/errors/errors.go b/internal/errors/errors.go
index 4800ffbf..c1300992 100644
--- a/internal/errors/errors.go
+++ b/internal/errors/errors.go
@@ -269,4 +269,4 @@ func UnwrapErrors(err error) (error, bool) {
 // ErrAlreadyHandled is an error that is already handled by
 // a kpt command and nothing needs to be done by the global
 // error handler except to return a non-zero exit code.
-var ErrAlreadyHandled error = fmt.Errorf("already handled error")
+var ErrAlreadyHandled = fmt.Errorf("already handled error")
diff --git a/internal/fnruntime/runner.go b/internal/fnruntime/runner.go
index 1edf3c77..1e62b9a6 100644
--- a/internal/fnruntime/runner.go
+++ b/internal/fnruntime/runner.go
@@ -48,11 +48,15 @@ const (
 // NewRunner returns a kio.Filter given a specification of a function
 // and it's config.
 func NewRunner(
-	ctx context.Context, fsys filesys.FileSystem, f *kptfilev1.Function,
-	pkgPath types.UniquePath, fnResults *fnresult.ResultList,
-	imagePullPolicy ImagePullPolicy, setPkgPathAnnotation, displayResourceCount bool,
-	runtime fn.FunctionRuntime) (kio.Filter, error) {
-
+	ctx context.Context,
+	fsys filesys.FileSystem,
+	f *kptfilev1.Function,
+	pkgPath types.UniquePath,
+	fnResults *fnresult.ResultList,
+	imagePullPolicy ImagePullPolicy,
+	setPkgPathAnnotation, displayResourceCount bool,
+	runtime fn.FunctionRuntime,
+) (kio.Filter, error) {
 	config, err := newFnConfig(fsys, f, pkgPath)
 	if err != nil {
 		return nil, err
@@ -481,7 +485,7 @@ func (ri *multiLineFormatter) String() string {
 
 func newFnConfig(fsys filesys.FileSystem, f *kptfilev1.Function, pkgPath types.UniquePath) (*yaml.RNode, error) {
 	const op errors.Op = "fn.readConfig"
-	var fn errors.Fn = errors.Fn(f.Image)
+	fn := errors.Fn(f.Image)
 
 	var node *yaml.RNode
 	switch {
diff --git a/internal/gitutil/gitutil.go b/internal/gitutil/gitutil.go
index 91c98f14..0a37e4cb 100644
--- a/internal/gitutil/gitutil.go
+++ b/internal/gitutil/gitutil.go
@@ -266,9 +266,7 @@ func (gur *GitUpstreamRepo) GetDefaultBranch(ctx context.Context) (string, error
 // cached information about refs in the upstream repo. If the branch doesn't exist
 // in the upstream repo, the last return value will be false.
 func (gur *GitUpstreamRepo) ResolveBranch(branch string) (string, bool) {
-	if strings.HasPrefix(branch, "refs/heads/") {
-		branch = strings.TrimPrefix(branch, "refs/heads/")
-	}
+	branch = strings.TrimPrefix(branch, "refs/heads/")
 	for head, commit := range gur.Heads {
 		if head == branch {
 			return commit, true
@@ -281,9 +279,7 @@ func (gur *GitUpstreamRepo) ResolveBranch(branch string) (string, bool) {
 // cached information about refs in the upstream repo. If the tag doesn't exist
 // in the upstream repo, the last return value will be false.
 func (gur *GitUpstreamRepo) ResolveTag(tag string) (string, bool) {
-	if strings.HasPrefix(tag, "refs/tags/") {
-		tag = strings.TrimPrefix(tag, "refs/tags/")
-	}
+	tag = strings.TrimPrefix(tag, "refs/tags/")
 	for t, commit := range gur.Tags {
 		if t == tag {
 			return commit, true
diff --git a/internal/hook/executor.go b/internal/hook/executor.go
index 787df920..5282d635 100644
--- a/internal/hook/executor.go
+++ b/internal/hook/executor.go
@@ -32,7 +32,7 @@ import (
 
 // ErrAllowedExecNotSpecified indicates user need to authorize to invoke
 // exec binaries.
-var ErrAllowedExecNotSpecified error = fmt.Errorf("must run with `--allow-exec` option to allow running function binaries")
+var ErrAllowedExecNotSpecified = fmt.Errorf("must run with `--allow-exec` option to allow running function binaries")
 
 // Executor executes a hook.
 type Executor struct {
diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go
index 8332e2c3..6bcb3610 100644
--- a/internal/pkg/pkg.go
+++ b/internal/pkg/pkg.go
@@ -425,8 +425,6 @@ func Subpackages(fsys filesys.FileSystem, rootPath string, matcher SubpackageMat
 					}
 				case All:
 					packagePaths[path] = true
-				default:
-
 				}
 				if !recursive {
 					return filepath.SkipDir
diff --git a/internal/util/diff/diff.go b/internal/util/diff/diff.go
index 97bb4435..24bcf0f6 100644
--- a/internal/util/diff/diff.go
+++ b/internal/util/diff/diff.go
@@ -36,18 +36,18 @@ import (
 	"sigs.k8s.io/kustomize/kyaml/filesys"
 )
 
-// DiffType represents type of comparison to be performed.
-type DiffType string
+// Type represents type of diff comparison to be performed.
+type Type string
 
 const (
-	// DiffTypeLocal shows the changes in local pkg relative to upstream source pkg at original version
-	DiffTypeLocal DiffType = "local"
-	// DiffTypeRemote shows changes in the upstream source pkg between original and target version
-	DiffTypeRemote DiffType = "remote"
-	// DiffTypeCombined shows changes in local pkg relative to upstream source pkg at target version
-	DiffTypeCombined DiffType = "combined"
+	// TypeLocal shows the changes in local pkg relative to upstream source pkg at original version
+	TypeLocal Type = "local"
+	// TypeRemote shows changes in the upstream source pkg between original and target version
+	TypeRemote Type = "remote"
+	// TypeCombined shows changes in local pkg relative to upstream source pkg at target version
+	TypeCombined Type = "combined"
 	// 3way shows changes in local and remote changes side-by-side
-	DiffType3Way DiffType = "3way"
+	Type3Way Type = "3way"
 )
 
 // A collection of user-readable "source" definitions for diffed packages.
@@ -69,11 +69,11 @@ const (
 )
 
 // String implements Stringer.
-func (dt DiffType) String() string {
+func (dt Type) String() string {
 	return string(dt)
 }
 
-var SupportedDiffTypes = []DiffType{DiffTypeLocal, DiffTypeRemote, DiffTypeCombined, DiffType3Way}
+var SupportedDiffTypes = []Type{TypeLocal, TypeRemote, TypeCombined, Type3Way}
 
 func SupportedDiffTypesLabel() string {
 	var labels []string
@@ -93,7 +93,7 @@ type Command struct {
 	Ref string
 
 	// DiffType specifies the type of changes to show
-	DiffType DiffType
+	DiffType Type
 
 	// Difftool refers to diffing commandline tool for showing changes.
 	DiffTool string
@@ -176,9 +176,9 @@ func (c *Command) Run(ctx context.Context) error {
 		}
 	}
 
-	if c.DiffType == DiffTypeRemote ||
-		c.DiffType == DiffTypeCombined ||
-		c.DiffType == DiffType3Way {
+	if c.DiffType == TypeRemote ||
+		c.DiffType == TypeCombined ||
+		c.DiffType == Type3Way {
 		// get the upstream pkg at the target version
 		upstreamTargetPkgName := NameStagingDirectory(TargetRemotePackageSource,
 			c.Ref)
@@ -198,13 +198,13 @@ func (c *Command) Run(ctx context.Context) error {
 	}
 
 	switch c.DiffType {
-	case DiffTypeLocal:
+	case TypeLocal:
 		return c.PkgDiffer.Diff(currPkg, upstreamPkg)
-	case DiffTypeRemote:
+	case TypeRemote:
 		return c.PkgDiffer.Diff(upstreamPkg, upstreamTargetPkg)
-	case DiffTypeCombined:
+	case TypeCombined:
 		return c.PkgDiffer.Diff(currPkg, upstreamTargetPkg)
-	case DiffType3Way:
+	case Type3Way:
 		return c.PkgDiffer.Diff(currPkg, upstreamPkg, upstreamTargetPkg)
 	default:
 		return errors.Errorf("unsupported diff type '%s'", c.DiffType)
@@ -213,15 +213,15 @@ func (c *Command) Run(ctx context.Context) error {
 
 func (c *Command) Validate() error {
 	switch c.DiffType {
-	case DiffTypeLocal, DiffTypeCombined, DiffTypeRemote, DiffType3Way:
+	case TypeLocal, TypeCombined, TypeRemote, Type3Way:
 	default:
-		return errors.Errorf("invalid diff-type '%s'. Supported diff-types are: %s",
+		return errors.Errorf("invalid diff-type '%s': supported diff-types are: %s",
 			c.DiffType, SupportedDiffTypesLabel())
 	}
 
 	path, err := exec.LookPath(c.DiffTool)
 	if err != nil {
-		return errors.Errorf("diff-tool '%s' not found in the PATH.", c.DiffTool)
+		return errors.Errorf("diff-tool '%s' not found in the PATH", c.DiffTool)
 	}
 	c.DiffTool = path
 	return nil
@@ -253,7 +253,7 @@ type PkgDiffer interface {
 
 type defaultPkgDiffer struct {
 	// DiffType specifies the type of changes to show
-	DiffType DiffType
+	DiffType Type
 
 	// Difftool refers to diffing commandline tool for showing changes.
 	DiffTool string
diff --git a/internal/util/get/get.go b/internal/util/get/get.go
index 2296844a..414b68a9 100644
--- a/internal/util/get/get.go
+++ b/internal/util/get/get.go
@@ -20,7 +20,6 @@ import (
 	goerrors "errors"
 	"fmt"
 	"os"
-	"path"
 	"path/filepath"
 	"strings"
 
@@ -83,7 +82,9 @@ func (c Command) Run(ctx context.Context) error {
 	// normalize path to a filepath
 	repoDir := c.Git.Directory
 	if !strings.HasSuffix(repoDir, "file://") {
-		repoDir = filepath.Join(path.Split(repoDir))
+		// Convert from separator to slash and back.
+		// This ensures all separators are compatible with the local OS.
+		repoDir = filepath.FromSlash(filepath.ToSlash(repoDir))
 	}
 	c.Git.Directory = repoDir
 
@@ -162,7 +163,7 @@ func (c Command) fetchPackages(ctx context.Context, rootPkg *pkg.Pkg) error {
 		}
 
 		if kf.Upstream != nil && kf.UpstreamLock == nil {
-			packageCount += 1
+			packageCount++
 			pr.PrintPackage(p, !(p == rootPkg))
 			pr.Printf("Fetching %s@%s\n", kf.Upstream.Git.Repo, kf.Upstream.Git.Ref)
 			err := (&fetch.Command{
diff --git a/internal/util/man/man.go b/internal/util/man/man.go
index e1ba0711..abb43d1f 100644
--- a/internal/util/man/man.go
+++ b/internal/util/man/man.go
@@ -21,7 +21,6 @@ import (
 	"io/ioutil"
 	"os"
 	"os/exec"
-	"path"
 	"path/filepath"
 	"strings"
 
@@ -72,12 +71,12 @@ func (m Command) Run() error {
 		if err != nil {
 			return errors.Errorf("no manual entry for %q", m.Path)
 		}
-		k.Info.Man = filepath.Join(ManFilename)
+		k.Info.Man = ManFilename
 	}
 
-	// the path separator needs to converted to the OS path.
-	// e.g. the separator will be different for windows.
-	p := filepath.Join(path.Split(k.Info.Man))
+	// Convert from separator to slash and back.
+	// This ensures all separators are compatible with the local OS.
+	p := filepath.FromSlash(filepath.ToSlash(k.Info.Man))
 
 	// verify the man page is in the package
 	apPkg, err := filepath.Abs(m.Path)
diff --git a/internal/util/parse/parse.go b/internal/util/parse/parse.go
index 1cd9d5ab..f9d63566 100644
--- a/internal/util/parse/parse.go
+++ b/internal/util/parse/parse.go
@@ -89,7 +89,7 @@ func GitParseArgs(ctx context.Context, args []string) (Target, error) {
 // targetFromPkgURL parses a pkg url and destination into kptfile git info and local destination Target
 func targetFromPkgURL(ctx context.Context, pkgURL string, dest string) (Target, error) {
 	g := Target{}
-	repo, dir, ref, err := ParseURL(pkgURL)
+	repo, dir, ref, err := URL(pkgURL)
 	if err != nil {
 		return g, err
 	}
@@ -118,8 +118,8 @@ func targetFromPkgURL(ctx context.Context, pkgURL string, dest string) (Target,
 	return g, nil
 }
 
-// ParseURL parses a pkg url (must contain ".git") and returns the repo, directory, and version
-func ParseURL(pkgURL string) (repo string, dir string, ref string, err error) {
+// URL parses a pkg url (must contain ".git") and returns the repo, directory, and version
+func URL(pkgURL string) (repo string, dir string, ref string, err error) {
 	parts := regexp.MustCompile(gitSuffixRegexp).Split(pkgURL, 2)
 	index := strings.Index(pkgURL, parts[0])
 	repo = strings.Join([]string{pkgURL[:index], parts[0]}, "")
diff --git a/internal/util/porch/approval.go b/internal/util/porch/approval.go
index 1a5eb66a..19e49798 100644
--- a/internal/util/porch/approval.go
+++ b/internal/util/porch/approval.go
@@ -1,3 +1,17 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package porch
 
 import (
diff --git a/internal/util/render/executor.go b/internal/util/render/executor.go
index c443e0cc..1e130502 100644
--- a/internal/util/render/executor.go
+++ b/internal/util/render/executor.go
@@ -40,7 +40,7 @@ import (
 	"sigs.k8s.io/kustomize/kyaml/yaml"
 )
 
-var errAllowedExecNotSpecified error = fmt.Errorf("must run with `--allow-exec` option to allow running function binaries")
+var errAllowedExecNotSpecified = fmt.Errorf("must run with `--allow-exec` option to allow running function binaries")
 
 // Renderer hydrates a given pkg by running the functions in the input pipeline
 type Renderer struct {
@@ -433,7 +433,7 @@ func (pn *pkgNode) runMutators(ctx context.Context, hctx *hydrationContext, inpu
 		if err != nil {
 			return nil, err
 		}
-		hctx.executedFunctionCnt += 1
+		hctx.executedFunctionCnt++
 
 		if len(selectors) > 0 || len(exclusions) > 0 {
 			// merge the output resources with input resources
diff --git a/internal/util/stack/stack.go b/internal/util/stack/stack.go
index 2e57e833..3d10984f 100644
--- a/internal/util/stack/stack.go
+++ b/internal/util/stack/stack.go
@@ -21,21 +21,19 @@ import (
 )
 
 // New returns a new stack for elements of string type.
-func New() *stack {
-	return &stack{
-		slice: make([]string, 0),
-	}
+func New() *Stack {
+	return &Stack{}
 }
 
-type stack struct {
+type Stack struct {
 	slice []string
 }
 
-func (s *stack) Push(str string) {
+func (s *Stack) Push(str string) {
 	s.slice = append(s.slice, str)
 }
 
-func (s *stack) Pop() string {
+func (s *Stack) Pop() string {
 	l := len(s.slice)
 	if l == 0 {
 		panic(fmt.Errorf("can't pop an empty stack"))
@@ -45,33 +43,31 @@ func (s *stack) Pop() string {
 	return str
 }
 
-func (s *stack) Len() int {
+func (s *Stack) Len() int {
 	return len(s.slice)
 }
 
 // NewPkgStack returns a new stack for elements of *pkg.Pkg type.
-func NewPkgStack() *pkgStack {
-	return &pkgStack{
-		slice: make([]*pkg.Pkg, 0),
-	}
+func NewPkgStack() *PkgStack {
+	return &PkgStack{}
 }
 
-type pkgStack struct {
+type PkgStack struct {
 	slice []*pkg.Pkg
 }
 
-func (ps *pkgStack) Push(p *pkg.Pkg) {
+func (ps *PkgStack) Push(p *pkg.Pkg) {
 	ps.slice = append(ps.slice, p)
 }
 
-func (ps *pkgStack) PushAll(pkgs []*pkg.Pkg) {
+func (ps *PkgStack) PushAll(pkgs []*pkg.Pkg) {
 	for i := range pkgs {
 		p := pkgs[i]
 		ps.Push(p)
 	}
 }
 
-func (ps *pkgStack) Pop() *pkg.Pkg {
+func (ps *PkgStack) Pop() *pkg.Pkg {
 	l := len(ps.slice)
 	if l == 0 {
 		panic(fmt.Errorf("can't pop an empty stack"))
@@ -81,6 +77,6 @@ func (ps *pkgStack) Pop() *pkg.Pkg {
 	return p
 }
 
-func (ps *pkgStack) Len() int {
+func (ps *PkgStack) Len() int {
 	return len(ps.slice)
 }
diff --git a/internal/util/update/fastforward.go b/internal/util/update/fastforward.go
index b94d85c8..b4413f58 100644
--- a/internal/util/update/fastforward.go
+++ b/internal/util/update/fastforward.go
@@ -43,7 +43,7 @@ var kptfileSet = func() sets.String {
 }()
 
 // We should try to pull the common code up into the Update command.
-func (u FastForwardUpdater) Update(options UpdateOptions) error {
+func (u FastForwardUpdater) Update(options Options) error {
 	const op errors.Op = "update.Update"
 	// Verify that there are no local changes that would prevent us from
 	// using the FastForward strategy.
diff --git a/internal/util/update/replace.go b/internal/util/update/replace.go
index 92fcf564..db943ff9 100644
--- a/internal/util/update/replace.go
+++ b/internal/util/update/replace.go
@@ -30,7 +30,7 @@ import (
 // delete the local package.  This will wipe all local changes.
 type ReplaceUpdater struct{}
 
-func (u ReplaceUpdater) Update(options UpdateOptions) error {
+func (u ReplaceUpdater) Update(options Options) error {
 	const op errors.Op = "update.Update"
 	paths, err := pkgutil.FindSubpackagesForPaths(pkg.Local, true, options.LocalPath, options.UpdatedPath)
 	if err != nil {
@@ -61,7 +61,6 @@ func (u ReplaceUpdater) Update(options UpdateOptions) error {
 				return errors.E(op, types.UniquePath(localSubPkgPath), err)
 			}
 		} else {
-
 			if err = pkgutil.CopyPackage(updatedSubPkgPath, localSubPkgPath, !isRootPkg, pkg.None); err != nil {
 				return errors.E(op, types.UniquePath(localSubPkgPath), err)
 			}
diff --git a/internal/util/update/resource-merge.go b/internal/util/update/resource-merge.go
index da20a990..32d1aebf 100644
--- a/internal/util/update/resource-merge.go
+++ b/internal/util/update/resource-merge.go
@@ -39,7 +39,7 @@ import (
 // packages, and performing a 3-way merge of the Resources.
 type ResourceMergeUpdater struct{}
 
-func (u ResourceMergeUpdater) Update(options UpdateOptions) error {
+func (u ResourceMergeUpdater) Update(options Options) error {
 	const op errors.Op = "update.Update"
 	if !options.IsRoot {
 		hasChanges, err := PkgHasUpdatedUpstream(options.LocalPath, options.OriginPath)
diff --git a/internal/util/update/update.go b/internal/util/update/update.go
index 98e6b9b5..df0658c3 100644
--- a/internal/util/update/update.go
+++ b/internal/util/update/update.go
@@ -59,7 +59,7 @@ func (p *PkgRepoDirtyError) Error() string {
 	return fmt.Sprintf("package %q contains uncommitted changes", p.Path.String())
 }
 
-type UpdateOptions struct {
+type Options struct {
 	// RelPackagePath is the relative path of a subpackage to the root. If the
 	// package is root, the value here will be ".".
 	RelPackagePath string
@@ -83,7 +83,7 @@ type UpdateOptions struct {
 
 // Updater updates a local package
 type Updater interface {
-	Update(options UpdateOptions) error
+	Update(options Options) error
 }
 
 var strategies = map[kptfilev1.UpdateStrategyType]func() Updater{
@@ -143,7 +143,7 @@ func (u Command) Run(ctx context.Context) error {
 
 	for s.Len() > 0 {
 		p := s.Pop()
-		packageCount += 1
+		packageCount++
 
 		if err := u.updateRootPackage(ctx, p); err != nil {
 			return errors.E(op, p.UniquePath, err)
@@ -452,7 +452,7 @@ func (u Command) mergePackage(ctx context.Context, localPath, updatedPath, origi
 			fmt.Errorf("unrecognized update strategy %s", u.Strategy))
 	}
 	pr.Printf("Updating package %q with strategy %q.\n", packageName(localPath), pkgKf.Upstream.UpdateStrategy)
-	if err := updater().Update(UpdateOptions{
+	if err := updater().Update(Options{
 		RelPackagePath: relPath,
 		LocalPath:      localPath,
 		UpdatedPath:    updatedPath,
diff --git a/mdtogo/cmddocs/cmddocs.go b/mdtogo/cmddocs/cmddocs.go
index 2f7035a0..3ef7918e 100644
--- a/mdtogo/cmddocs/cmddocs.go
+++ b/mdtogo/cmddocs/cmddocs.go
@@ -23,6 +23,9 @@ import (
 	"path/filepath"
 	"regexp"
 	"strings"
+
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
 )
 
 func ParseCmdDocs(files []string) []doc {
@@ -61,7 +64,6 @@ func parse(path, value string) []doc {
 	docsByName := make(map[string]doc)
 	var docBuilder doc
 	for _, match := range matches {
-
 		if match[1] == "" {
 			docBuilder = docsByName[name]
 			docBuilder.Name = name
@@ -94,7 +96,7 @@ func parse(path, value string) []doc {
 }
 
 func cleanName(name string) string {
-	name = strings.Title(name)
+	name = cases.Title(language.English).String(name)
 	name = strings.ReplaceAll(name, "-", "")
 	return name
 }
diff --git a/mdtogo/common/common.go b/mdtogo/common/common.go
index 55074fdc..aaa10c2b 100644
--- a/mdtogo/common/common.go
+++ b/mdtogo/common/common.go
@@ -40,7 +40,6 @@ func ReadFiles(source string, recursive bool) ([]string, error) {
 	} else {
 		if filepath.Ext(source) == markdownExtension {
 			filePaths = append(filePaths, source)
-
 		} else {
 			files, err := ioutil.ReadDir(source)
 			if err != nil {
diff --git a/package-examples/tenant/namespace.yaml b/package-examples/tenant/namespace.yaml
index 72503847..853aab02 100644
--- a/package-examples/tenant/namespace.yaml
+++ b/package-examples/tenant/namespace.yaml
@@ -1,3 +1,17 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 apiVersion: v1
 kind: Namespace
 metadata:
diff --git a/package-examples/tenant/ns-invariant.yaml b/package-examples/tenant/ns-invariant.yaml
index 42070ff5..48761843 100644
--- a/package-examples/tenant/ns-invariant.yaml
+++ b/package-examples/tenant/ns-invariant.yaml
@@ -1,3 +1,17 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 apiVersion: fn.kpt.dev/v1alpha1
 kind: StarlarkRun
 metadata:
@@ -7,7 +21,7 @@ source: |
     num_ns = 0
     for resource in resource_list["items"]:
       if resource["apiVersion"] == "v1" and resource["kind"] == "Namespace":
-        num_ns += 1
+        num_ns++
     # only one namespace is allowed
     if num_ns > 1:
       fail("pkg must contain single namespace") 
diff --git a/package-examples/tenant/quota.yaml b/package-examples/tenant/quota.yaml
index 181e211f..5337fe70 100644
--- a/package-examples/tenant/quota.yaml
+++ b/package-examples/tenant/quota.yaml
@@ -1,3 +1,17 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 apiVersion: v1
 kind: ResourceQuota
 metadata:
diff --git a/package-examples/tenant/role-binding.yaml b/package-examples/tenant/role-binding.yaml
index 7de67282..d5cbb5e2 100644
--- a/package-examples/tenant/role-binding.yaml
+++ b/package-examples/tenant/role-binding.yaml
@@ -1,3 +1,17 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 apiVersion: rbac.authorization.k8s.io/v1beta1
 kind: RoleBinding
 metadata:
diff --git a/package-examples/tenant/service-account.yaml b/package-examples/tenant/service-account.yaml
index 7390ee13..48f5fc88 100644
--- a/package-examples/tenant/service-account.yaml
+++ b/package-examples/tenant/service-account.yaml
@@ -1,3 +1,17 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 apiVersion: v1
 kind: ServiceAccount
 metadata:
diff --git a/pkg/debug/formatter.go b/pkg/debug/formatter.go
index 2b8e3b77..874e06b4 100644
--- a/pkg/debug/formatter.go
+++ b/pkg/debug/formatter.go
@@ -19,14 +19,14 @@ import (
 	"fmt"
 )
 
-// deferredJSON is a helper that delays JSON formatting until/unless it is needed.
-type deferredJSON struct {
-	o interface{}
+// DeferredJSON is a helper that delays JSON formatting until/unless it is needed.
+type DeferredJSON struct {
+	O interface{}
 }
 
 // String is the method that is called to format the object.
-func (d deferredJSON) String() string {
-	b, err := json.Marshal(d.o)
+func (d DeferredJSON) String() string {
+	b, err := json.Marshal(d.O)
 	if err != nil {
 		return fmt.Sprintf("<error: %v>", err)
 	}
@@ -35,6 +35,6 @@ func (d deferredJSON) String() string {
 
 // JSON is a helper that prints the object in JSON format.
 // We use lazy-evaluation to avoid calling json.Marshal unless it is actually needed.
-func JSON(o interface{}) deferredJSON {
-	return deferredJSON{o}
+func JSON(o interface{}) DeferredJSON {
+	return DeferredJSON{o}
 }
diff --git a/pkg/kptpkg/init.go b/pkg/kptpkg/init.go
index b8d131b0..419f8850 100644
--- a/pkg/kptpkg/init.go
+++ b/pkg/kptpkg/init.go
@@ -52,8 +52,11 @@ type InitOptions struct {
 // DefaultInitilizer implements Initializer interface.
 type DefaultInitializer struct{}
 
-func (i *DefaultInitializer) Initialize(ctx context.Context, fsys filesys.FileSystem, opts InitOptions) error {
-
+func (i *DefaultInitializer) Initialize(
+	ctx context.Context,
+	fsys filesys.FileSystem,
+	opts InitOptions,
+) error {
 	p, err := pkg.New(fsys, opts.PkgPath)
 	if err != nil {
 		return err
diff --git a/pkg/live/load.go b/pkg/live/load.go
index 363d700d..722ac48f 100644
--- a/pkg/live/load.go
+++ b/pkg/live/load.go
@@ -113,7 +113,6 @@ func loadFromStream(f util.Factory, r io.Reader, rgfile string) ([]*unstructured
 		if diskInv.IsValid() {
 			invInfo = diskInv
 		}
-
 	}
 
 	// Stream does not contain a valid inventory and no local inventory does not exist, or is not valid.
diff --git a/porch/Makefile b/porch/Makefile
index 1ce66f32..ec23b981 100644
--- a/porch/Makefile
+++ b/porch/Makefile
@@ -152,8 +152,7 @@ porch:
 
 .PHONY: fix-headers
 fix-headers:
-	# TODO: switch to google/addlicense once we have https://github.com/google/addlicense/pull/104
-	go run github.com/justinsb/addlicense@v1.0.1 -c "Google LLC" -l apache --ignore ".build/**" --ignore "**/testdata/**" . 2>/dev/null
+	../scripts/update-license.sh
 
 .PHONY: fix-all
 fix-all: fix-headers fmt tidy
diff --git a/porch/pkg/kpt/pkgupdate.go b/porch/pkg/kpt/pkgupdate.go
index 7f9408d3..e6263845 100644
--- a/porch/pkg/kpt/pkgupdate.go
+++ b/porch/pkg/kpt/pkgupdate.go
@@ -170,7 +170,7 @@ func PkgUpdate(ctx context.Context, ref string, packageDir string, opts PkgUpdat
 		// 	return errors.E(op, p.UniquePath, err)
 		// }
 
-		updateOptions := update.UpdateOptions{
+		updateOptions := update.Options{
 			RelPackagePath: relPath,
 			LocalPath:      localPath,
 			UpdatedPath:    updatedPath,
diff --git a/scripts/update-license.sh b/scripts/update-license.sh
index a2e3b73a..05a9710f 100755
--- a/scripts/update-license.sh
+++ b/scripts/update-license.sh
@@ -1,3 +1,4 @@
+#!/usr/bin/env bash
 # Copyright 2019 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,13 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# don't add licenses to the site directory, it will break the docs
-# and will add them to the theme which is a submodule (bad)
-which addlicense || go install github.com/google/addlicense@latest
-find . -type f \
-! -path "./site/*" \
-! -path "./docs/*" \
-! -path "**/.expected/results.yaml" \
-! -path "**/testData/*" \
-! -path "**/generated/*" \
-| xargs $GOBIN/addlicense -y 2021 -l apache
+set -o nounset
+set -o errexit
+set -o pipefail
+
+# TODO: switch to google/addlicense once we have https://github.com/google/addlicense/pull/104
+go run github.com/justinsb/addlicense@v1.0.1 \
+  -c "Google LLC" -l apache \
+  --ignore ".build/**" \
+  --ignore "site/**" \
+  --ignore "docs/**" \
+  --ignore "**/.expected/results.yaml" \
+  --ignore "**/testdata/**" \
+  --ignore "**/generated/**" \
+  . 2>&1 | ( grep -v "skipping: " || true )
diff --git a/site/guides/porch-ui-installation.md b/site/guides/porch-ui-installation.md
index e69de29b..9c20df4f 100644
--- a/site/guides/porch-ui-installation.md
+++ b/site/guides/porch-ui-installation.md
@@ -0,0 +1,52 @@
+# Accessing the Configuration as Data UI
+
+The easiest way to access the Configuration as Data UI is running by a docker
+container on your local machine where you'll be able to access the UI with your
+browser. Running the container locally simplifies the overall setup by allowing
+the UI to use your local kubeconfig and Google credentials to access the GKE
+cluster with Porch installed. This guide will show you how to do this.
+
+## Prerequisites
+
+To access the Configuration as Data UI with a docker container, you will need:
+
+*   [Porch](guides/porch-installation.md) installed on a GKE cluster
+*   [kubectl](https://kubernetes.io/docs/tasks/tools/) targeting the GKE cluster
+    with Porch installed
+*   [git](https://git-scm.com/)
+*   [docker](https://docs.docker.com/get-docker/)
+
+## Running locally in a container
+
+First, clone the
+[kpt-backstage-plugins](https://github.com/GoogleContainerTools/kpt-backstage-plugins)
+repository.
+
+```sh
+git clone https://github.com/GoogleContainerTools/kpt-backstage-plugins.git
+cd kpt-backstage-plugins
+```
+
+Next, build the kpt-backstage-plugins image.
+
+```sh
+docker build --target backstage-app-local --tag kpt-backstage-plugins .
+```
+
+And create a new container using the kpt-backstage-plugins image. The two
+attached volumnes allows the UI to connect to your GKE using your local Google
+credentials, and the UI will be exposed over port 7007.
+
+```sh
+docker run -v ~/.kube/config:/root/.kube/config -v ~/.config/gcloud:/root/.config/gcloud -p 7007:7007 kpt-backstage-plugins
+```
+
+And now access the Configuration as Data UI by opening your browser to
+http://localhost:7007/config-as-data.
+
+## Running in Backstage
+
+The Configuration as Data UI can be added to an existing
+[Backstage](https://backstage.io) application by following the instructions on
+the
+[Configuration as Data Plugin README](https://github.com/GoogleContainerTools/kpt-backstage-plugins/tree/main/plugins/cad/README.md).
diff --git a/site/installation/README.md b/site/installation/README.md
index 4c2f4062..019b44ca 100644
--- a/site/installation/README.md
+++ b/site/installation/README.md
@@ -4,4 +4,5 @@ Please follow the links below to install `kpt` components:
 
 - [kpt CLI](/installation/kpt-cli.md)
 - [Package Orchestrator](/guides/porch-installation.md)
-- [Config Sync](https://github.com/GoogleContainerTools/kpt-config-sync/blob/main/docs/installation.md)
\ No newline at end of file
+- [Config Sync](https://github.com/GoogleContainerTools/kpt-config-sync/blob/main/docs/installation.md)
+- [Configuration as Data UI](/guides/porch-ui-installation.md)
diff --git a/thirdparty/cmdconfig/commands/cmdeval/cmdeval.go b/thirdparty/cmdconfig/commands/cmdeval/cmdeval.go
index 080b15cb..3ee09311 100644
--- a/thirdparty/cmdconfig/commands/cmdeval/cmdeval.go
+++ b/thirdparty/cmdconfig/commands/cmdeval/cmdeval.go
@@ -267,9 +267,7 @@ func (r *EvalFnRunner) SaveFnToKptfile() {
 
 // getCLIFunctionConfig parses the commandline flags and arguments into explicit
 // function config
-func (r *EvalFnRunner) getCLIFunctionConfig(dataItems []string) (
-	*yaml.RNode, error) {
-
+func (r *EvalFnRunner) getCLIFunctionConfig(dataItems []string) (*yaml.RNode, error) {
 	if r.Image == "" && r.Exec == "" {
 		return nil, nil
 	}
@@ -351,7 +349,6 @@ func (r *EvalFnRunner) getFunctionSpec() (*runtimeutil.FunctionSpec, []string, e
 			fn.Exec.Path = s[0]
 			execArgs = s[1:]
 		}
-
 	}
 	return fn, execArgs, nil
 }
diff --git a/thirdparty/cmdconfig/commands/cmdtree/tree.go b/thirdparty/cmdconfig/commands/cmdtree/tree.go
index 0c010ef2..b636161d 100644
--- a/thirdparty/cmdconfig/commands/cmdtree/tree.go
+++ b/thirdparty/cmdconfig/commands/cmdtree/tree.go
@@ -128,20 +128,26 @@ func (p TreeWriter) Write(nodes []*yaml.RNode) error {
 }
 
 // node wraps a tree node, and any children nodes
-//nolint
+//nolint:unused
 type node struct {
 	p TreeWriter
 	*yaml.RNode
 	children []*node
 }
 
-func (a node) Len() int      { return len(a.children) }
+//nolint:unused
+func (a node) Len() int { return len(a.children) }
+
+//nolint:unused
 func (a node) Swap(i, j int) { a.children[i], a.children[j] = a.children[j], a.children[i] }
+
+//nolint:unused
 func (a node) Less(i, j int) bool {
 	return compareNodes(a.children[i].RNode, a.children[j].RNode)
 }
 
 // Tree adds this node to the root
+//nolint:unused
 func (a node) Tree(root treeprint.Tree) error {
 	sort.Sort(a)
 	branch := root


Test patch:
diff --git a/e2e/testdata/fn-eval/save-fn/custom-pkg-path/.expected/diff.patch b/e2e/testdata/fn-eval/save-fn/custom-pkg-path/.expected/diff.patch
index 6b29730d..d05d59be 100644
--- a/e2e/testdata/fn-eval/save-fn/custom-pkg-path/.expected/diff.patch
+++ b/e2e/testdata/fn-eval/save-fn/custom-pkg-path/.expected/diff.patch
@@ -12,15 +12,10 @@ index d9e2f05..93c547b 100644
 +    - image: gcr.io/kpt-fn/set-namespace:v0.1.3
 +      configPath: fn-config.yaml
 diff --git a/sub-pkg/fn-config.yaml b/sub-pkg/fn-config.yaml
-index 3b3dc0f..670db5a 100644
+index 6db3003..a04940f 100644
 --- a/sub-pkg/fn-config.yaml
 +++ b/sub-pkg/fn-config.yaml
-@@ -11,10 +11,10 @@
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
--
- apiVersion: v1
+@@ -2,5 +2,6 @@ apiVersion: v1
  kind: ConfigMap
  metadata:
    name: fn-config
diff --git a/internal/builtins/pkg_context_test.go b/internal/builtins/pkg_context_test.go
index ac5bb69d..c1a6334f 100644
--- a/internal/builtins/pkg_context_test.go
+++ b/internal/builtins/pkg_context_test.go
@@ -52,10 +52,10 @@ func TestPkgContextGenerator(t *testing.T) {
 			pkgCtxGenerator := &PackageContextGenerator{}
 			out := &bytes.Buffer{}
 
-			in, err := ioutil.ReadFile(filepath.Join("testData", test.dir, "in.yaml"))
+			in, err := ioutil.ReadFile(filepath.Join("testdata", test.dir, "in.yaml"))
 			assert.NoError(t, err)
 
-			exp, err := ioutil.ReadFile(filepath.Join("testData", test.dir, "out.yaml"))
+			exp, err := ioutil.ReadFile(filepath.Join("testdata", test.dir, "out.yaml"))
 			assert.NoError(t, err)
 
 			err = pkgCtxGenerator.Run(bytes.NewReader(in), out)
diff --git a/internal/cmddiff/cmddiff_test.go b/internal/cmddiff/cmddiff_test.go
index 7efd816b..f70db5bb 100644
--- a/internal/cmddiff/cmddiff_test.go
+++ b/internal/cmddiff/cmddiff_test.go
@@ -37,7 +37,7 @@ func TestCmdInvalidDiffType(t *testing.T) {
 	err := runner.C.Execute()
 	assert.EqualError(t,
 		err,
-		"invalid diff-type 'invalid'. Supported diff-types are: local, remote, combined, 3way")
+		"invalid diff-type 'invalid': supported diff-types are: local, remote, combined, 3way")
 }
 
 func TestCmdInvalidDiffTool(t *testing.T) {
@@ -46,7 +46,7 @@ func TestCmdInvalidDiffTool(t *testing.T) {
 	err := runner.C.Execute()
 	assert.EqualError(t,
 		err,
-		"diff-tool 'nodiff' not found in the PATH.")
+		"diff-tool 'nodiff' not found in the PATH")
 }
 
 func TestCmdExecute(t *testing.T) {
diff --git a/internal/cmdget/cmdget_test.go b/internal/cmdget/cmdget_test.go
index 88345393..4fcfb883 100644
--- a/internal/cmdget/cmdget_test.go
+++ b/internal/cmdget/cmdget_test.go
@@ -148,7 +148,6 @@ func TestCmdMainBranch_execute(t *testing.T) {
 			},
 		},
 	})
-
 }
 
 // TestCmd_fail verifies that that command returns an error rather than exiting the process
diff --git a/internal/fnruntime/fnerrors_test.go b/internal/fnruntime/fnerrors_test.go
index b308d721..cc1b4459 100644
--- a/internal/fnruntime/fnerrors_test.go
+++ b/internal/fnruntime/fnerrors_test.go
@@ -141,7 +141,6 @@ error message`,
 }
 
 func TestDockerCLIOutputFilter(t *testing.T) {
-
 	testcases := []struct {
 		name     string
 		input    string
diff --git a/internal/fnruntime/runner_test.go b/internal/fnruntime/runner_test.go
index 37bbe218..80e6a51c 100644
--- a/internal/fnruntime/runner_test.go
+++ b/internal/fnruntime/runner_test.go
@@ -101,7 +101,6 @@ data: {foo: bar}
 }
 
 func TestMultilineFormatter(t *testing.T) {
-
 	type testcase struct {
 		ml       *multiLineFormatter
 		expected string
diff --git a/internal/util/diff/diff_test.go b/internal/util/diff/diff_test.go
index 312a52cd..ae4b4269 100644
--- a/internal/util/diff/diff_test.go
+++ b/internal/util/diff/diff_test.go
@@ -40,7 +40,7 @@ func TestCommand_Diff(t *testing.T) {
 		updatedLocal              testutil.Content
 		fetchRef                  string
 		diffRef                   string
-		diffType                  DiffType
+		diffType                  Type
 		diffTool                  string
 		diffOpts                  string
 		expDiff                   string
@@ -68,7 +68,7 @@ func TestCommand_Diff(t *testing.T) {
 			},
 			fetchRef: "v2",
 			diffRef:  "master",
-			diffType: DiffTypeRemote,
+			diffType: TypeRemote,
 			diffTool: "diff",
 			diffOpts: "-r -i -w",
 			expDiff: `
@@ -108,7 +108,7 @@ func TestCommand_Diff(t *testing.T) {
 			},
 			fetchRef: "v2",
 			diffRef:  "master",
-			diffType: DiffTypeCombined,
+			diffType: TypeCombined,
 			diffTool: "diff",
 			diffOpts: "-r -i -w",
 			expDiff: `
@@ -149,7 +149,7 @@ func TestCommand_Diff(t *testing.T) {
 			},
 			fetchRef: "v2",
 			diffRef:  "master",
-			diffType: DiffTypeCombined,
+			diffType: TypeCombined,
 			diffTool: "diff",
 			diffOpts: "-r -i -w",
 			expDiff: `
@@ -195,7 +195,7 @@ func TestCommand_Diff(t *testing.T) {
 			},
 			fetchRef: "main",
 			diffRef:  "main",
-			diffType: DiffTypeCombined,
+			diffType: TypeCombined,
 			diffTool: "diff",
 			diffOpts: "-r -i -w",
 			expDiff: `
@@ -246,7 +246,7 @@ locally changed: foo
 			},
 			fetchRef: "main",
 			diffRef:  "main",
-			diffType: DiffTypeCombined,
+			diffType: TypeCombined,
 			diffTool: "diff",
 			diffOpts: "-r -i -w",
 			expDiff: `
@@ -301,7 +301,7 @@ locally changed: foo
 			},
 			fetchRef: "main",
 			diffRef:  "main",
-			diffType: DiffTypeCombined,
+			diffType: TypeCombined,
 			diffTool: "diff",
 			diffOpts: "-r -i -w",
 			expDiff: `
@@ -382,7 +382,7 @@ func TestCommand_InvalidRef(t *testing.T) {
 	err := (&Command{
 		Path:         g.LocalWorkspace.FullPackagePath(),
 		Ref:          "hurdygurdy", // ref should not exist in upstream
-		DiffType:     DiffTypeCombined,
+		DiffType:     TypeCombined,
 		DiffTool:     "diff",
 		DiffToolOpts: "-r -i -w",
 		Output:       diffOutput,
@@ -422,7 +422,7 @@ func TestCommand_Diff3Parameters(t *testing.T) {
 	err := (&Command{
 		Path:         g.LocalWorkspace.FullPackagePath(),
 		Ref:          "master",
-		DiffType:     DiffType3Way,
+		DiffType:     Type3Way,
 		DiffTool:     "echo", // this is a proxy for 3 way diffing to validate we pass proper values
 		DiffToolOpts: "",
 		Output:       diffOutput,
@@ -456,7 +456,7 @@ func TestCommand_NotAKptDirectory(t *testing.T) {
 			cmdErr := (&Command{
 				Path:         tc.directory,
 				Ref:          "master",
-				DiffType:     DiffTypeCombined,
+				DiffType:     TypeCombined,
 				DiffTool:     "diff",
 				DiffToolOpts: "-r -i -w",
 				Output:       diffOutput,
diff --git a/internal/util/fetch/fetch_test.go b/internal/util/fetch/fetch_test.go
index e3f4ecb7..0df81df2 100644
--- a/internal/util/fetch/fetch_test.go
+++ b/internal/util/fetch/fetch_test.go
@@ -477,7 +477,6 @@ func TestCommand_Run_subdir_at_tag(t *testing.T) {
 		},
 	}
 	for tn, tc := range testCases {
-
 		t.Run(tn, func(t *testing.T) {
 			expectedName := "expected"
 			repos, rw, clean := testutil.SetupReposAndWorkspace(t, map[string][]testutil.Content{
diff --git a/internal/util/merge/merge3_test.go b/internal/util/merge/merge3_test.go
index 79bd84d6..65d398a1 100644
--- a/internal/util/merge/merge3_test.go
+++ b/internal/util/merge/merge3_test.go
@@ -571,7 +571,6 @@ spec:
 
 	for tn, tc := range testCases {
 		t.Run(tn, func(t *testing.T) {
-
 			// setup the local directory
 			dir := t.TempDir()
 
diff --git a/internal/util/parse/parse_test.go b/internal/util/parse/parse_test.go
index 47799d9d..c0bbef4a 100644
--- a/internal/util/parse/parse_test.go
+++ b/internal/util/parse/parse_test.go
@@ -211,7 +211,7 @@ func Test_parseURL(t *testing.T) {
 	for name, test := range tests {
 		test := test // capture range variable
 		t.Run(name, func(t *testing.T) {
-			repo, dir, version, err := ParseURL(test.ghURL)
+			repo, dir, version, err := URL(test.ghURL)
 			assert.NoError(t, err)
 			assert.Equal(t, expected{repo: repo, dir: dir, version: version}, test.expected)
 		})
diff --git a/internal/util/update/fastforward_test.go b/internal/util/update/fastforward_test.go
index bebd2b24..815c3cdb 100644
--- a/internal/util/update/fastforward_test.go
+++ b/internal/util/update/fastforward_test.go
@@ -172,7 +172,7 @@ func TestUpdate_FastForward(t *testing.T) {
 
 			updater := &FastForwardUpdater{}
 
-			err := updater.Update(UpdateOptions{
+			err := updater.Update(Options{
 				RelPackagePath: tc.relPackagePath,
 				OriginPath:     filepath.Join(origin, tc.relPackagePath),
 				LocalPath:      filepath.Join(local, tc.relPackagePath),
diff --git a/internal/util/update/replace_test.go b/internal/util/update/replace_test.go
index 8770be3b..e3cf3dc7 100644
--- a/internal/util/update/replace_test.go
+++ b/internal/util/update/replace_test.go
@@ -172,7 +172,7 @@ func TestUpdate_Replace(t *testing.T) {
 
 			updater := &ReplaceUpdater{}
 
-			err := updater.Update(UpdateOptions{
+			err := updater.Update(Options{
 				RelPackagePath: tc.relPackagePath,
 				OriginPath:     filepath.Join(origin, tc.relPackagePath),
 				LocalPath:      filepath.Join(local, tc.relPackagePath),
diff --git a/internal/util/update/resource-merge_test.go b/internal/util/update/resource-merge_test.go
index 4cc19616..61b148f9 100644
--- a/internal/util/update/resource-merge_test.go
+++ b/internal/util/update/resource-merge_test.go
@@ -285,7 +285,7 @@ func TestUpdate_ResourceMerge(t *testing.T) {
 
 			updater := &ResourceMergeUpdater{}
 
-			err := updater.Update(UpdateOptions{
+			err := updater.Update(Options{
 				RelPackagePath: tc.relPackagePath,
 				OriginPath:     filepath.Join(origin, tc.relPackagePath),
 				LocalPath:      filepath.Join(local, tc.relPackagePath),
diff --git a/internal/util/update/update_test.go b/internal/util/update/update_test.go
index e1b383cd..e1ea14e5 100644
--- a/internal/util/update/update_test.go
+++ b/internal/util/update/update_test.go
@@ -952,7 +952,6 @@ func TestCommand_Run_noUpstreamReference(t *testing.T) {
 	}.Run(fake.CtxWithDefaultPrinter())
 
 	assert.Contains(t, err.Error(), "must have an upstream reference")
-
 }
 
 // TestCommand_Run_failInvalidPath verifies Run fails if the path is invalid
@@ -3773,7 +3772,7 @@ func TestReplaceNonKRMFiles(t *testing.T) {
 			err = ReplaceNonKRMFiles(updated, original, local)
 			assert.NoError(t, err)
 			tg := testutil.TestGitRepo{}
-			tg.AssertEqual(t, local, filepath.Join(expectedLocal), false)
+			tg.AssertEqual(t, local, expectedLocal, false)
 		})
 	}
 }
diff --git a/mdtogo/cmddocs/cmddocs_test.go b/mdtogo/cmddocs/cmddocs_test.go
index 9d69e314..a33de379 100644
--- a/mdtogo/cmddocs/cmddocs_test.go
+++ b/mdtogo/cmddocs/cmddocs_test.go
@@ -32,7 +32,7 @@ func TestParsingDocWithNameFromFolder(t *testing.T) {
 	exampleMd, err := ioutil.TempFile(testDir, "_index.md")
 	assert.NoError(t, err)
 
-	testData := []byte(`
+	testdata := []byte(`
 <!--mdtogo:Short
 Short documentation.
 -->
@@ -58,7 +58,7 @@ example_bin arg1
 <!--mdtogo-->
 	`)
 
-	err = ioutil.WriteFile(exampleMd.Name(), testData, os.ModePerm)
+	err = ioutil.WriteFile(exampleMd.Name(), testdata, os.ModePerm)
 	assert.NoError(t, err)
 
 	docs := cmddocs.ParseCmdDocs([]string{exampleMd.Name()})
@@ -76,7 +76,7 @@ func TestParsingDocWithBackticks(t *testing.T) {
 	exampleMd, err := ioutil.TempFile(testDir, "_index.md")
 	assert.NoError(t, err)
 
-	testData := []byte(`
+	testdata := []byte(`
 <!--mdtogo:Short
 Short ` +
 		"`documentation`" +
@@ -90,7 +90,7 @@ Test document.
 <!--mdtogo-->
 	`)
 
-	err = ioutil.WriteFile(exampleMd.Name(), testData, os.ModePerm)
+	err = ioutil.WriteFile(exampleMd.Name(), testdata, os.ModePerm)
 	assert.NoError(t, err)
 
 	docs := cmddocs.ParseCmdDocs([]string{exampleMd.Name()})
@@ -107,7 +107,7 @@ func TestParsingDocWithNameFromComment(t *testing.T) {
 	exampleMd, err := ioutil.TempFile(testDir, "_index.md")
 	assert.NoError(t, err)
 
-	testData := []byte(`
+	testdata := []byte(`
 <!--mdtogo:FirstShort
 First short documentation.
 -->
@@ -136,7 +136,7 @@ example_bin arg1
 <!--mdtogo-->
 	`)
 
-	err = ioutil.WriteFile(exampleMd.Name(), testData, os.ModePerm)
+	err = ioutil.WriteFile(exampleMd.Name(), testdata, os.ModePerm)
 	assert.NoError(t, err)
 
 	docs := cmddocs.ParseCmdDocs([]string{exampleMd.Name()})
diff --git a/pkg/api/kptfile/v1/validation_test.go b/pkg/api/kptfile/v1/validation_test.go
index fee67a65..e256e0a6 100644
--- a/pkg/api/kptfile/v1/validation_test.go
+++ b/pkg/api/kptfile/v1/validation_test.go
@@ -162,7 +162,6 @@ func TestKptfileValidate(t *testing.T) {
 				t.Fatal("kptfile should not be valid")
 			}
 		})
-
 	}
 }
 
@@ -249,7 +248,6 @@ func TestValidateFunctionName(t *testing.T) {
 				t.Fatalf("function name %s should not be valid", n.Name)
 			}
 		})
-
 	}
 }
 
diff --git a/pkg/test/live/runner.go b/pkg/test/live/runner.go
index 304644ab..26ddcf2c 100644
--- a/pkg/test/live/runner.go
+++ b/pkg/test/live/runner.go
@@ -153,7 +153,6 @@ func (r *Runner) VerifyInventory(t *testing.T, name, namespace string) {
 	sort.Slice(inventory, inventorySortFunc(inventory))
 
 	assert.Equal(t, expectedInventory, inventory)
-
 }
 
 func inventorySortFunc(inv []InventoryEntry) func(i, j int) bool {
diff --git a/pkg/test/runner/runner.go b/pkg/test/runner/runner.go
index 5bccd10b..b9b74c00 100644
--- a/pkg/test/runner/runner.go
+++ b/pkg/test/runner/runner.go
@@ -391,7 +391,6 @@ func (r *Runner) runFnRender() error {
 		if fnErr != nil {
 			break
 		}
-
 	}
 	return nil
 }
diff --git a/thirdparty/cmdconfig/commands/cmdeval/cmdeval_test.go b/thirdparty/cmdconfig/commands/cmdeval/cmdeval_test.go
index bc2c0e61..fa8ec881 100644
--- a/thirdparty/cmdconfig/commands/cmdeval/cmdeval_test.go
+++ b/thirdparty/cmdconfig/commands/cmdeval/cmdeval_test.go
@@ -435,7 +435,6 @@ apiVersion: v1
 					t.FailNow()
 				}
 			}
-
 		})
 	}
 }
diff --git a/thirdparty/cmdconfig/commands/cmdsource/cmdsource_test.go b/thirdparty/cmdconfig/commands/cmdsource/cmdsource_test.go
index a517fe64..a5d0f13f 100644
--- a/thirdparty/cmdconfig/commands/cmdsource/cmdsource_test.go
+++ b/thirdparty/cmdconfig/commands/cmdsource/cmdsource_test.go
@@ -281,7 +281,6 @@ spec:
 	if !assert.Equal(t, `invalid input for --output flag "foo/bar", must be "stdout" or "unwrap"`, err.Error()) {
 		t.FailNow()
 	}
-
 }
 
 func TestSourceCommand_DefaultDir(t *testing.T) {