Repository: knative/pkg
Pull request #1857 (2020-10-27 20:27:14)

Return context.Canceled error in pkg/signals
Return a typed `context.Canceled` error following the context package
semantic.

Closes: #1854

Might break existing users if they rely on the current error string
being returned with string matching, which is unlikely though.

Signed-off-by: Michael Gasch <mgasch@vmware.com>

knative-prow-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/pkg/pull/1857#" title="Author self-approved">embano1</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **vagababov** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @vagababov` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fpkg).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/knative/pkg/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["vagababov"]} -->
knative-prow-robot: Welcome @embano1! It looks like this is your first PR to knative/pkg 🎉
knative-prow-robot: Hi @embano1. Thanks for your PR.

I'm waiting for a [knative](https://github.com/orgs/knative/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/knative/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=knative%2Fpkg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

vagababov: /ok-to-test
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/pkg/pull/1857?src=pr&el=h1) Report
> Merging [#1857](https://codecov.io/gh/knative/pkg/pull/1857?src=pr&el=desc) into [master](https://codecov.io/gh/knative/pkg/commit/4ce8016d707c468b446db9fe5058753afccbf4bd?el=desc) will **decrease** coverage by `0.05%`.
> The diff coverage is `50.00%`.

[![Impacted file tree graph](https://codecov.io/gh/knative/pkg/pull/1857/graphs/tree.svg?width=650&height=150&src=pr&token=rlqpDnfxbO)](https://codecov.io/gh/knative/pkg/pull/1857?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1857      +/-   ##
==========================================
- Coverage   68.15%   68.09%   -0.06%     
==========================================
  Files         222      223       +1     
  Lines        9429     9457      +28     
==========================================
+ Hits         6426     6440      +14     
- Misses       2683     2692       +9     
- Partials      320      325       +5     
```


| [Impacted Files](https://codecov.io/gh/knative/pkg/pull/1857?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [logging/config.go](https://codecov.io/gh/knative/pkg/pull/1857/diff?src=pr&el=tree#diff-bG9nZ2luZy9jb25maWcuZ28=) | `87.50% <ø> (+3.50%)` | :arrow_up: |
| [tracing/config/tracing.go](https://codecov.io/gh/knative/pkg/pull/1857/diff?src=pr&el=tree#diff-dHJhY2luZy9jb25maWcvdHJhY2luZy5nbw==) | `75.00% <ø> (+4.68%)` | :arrow_up: |
| [depcheck/depcheck.go](https://codecov.io/gh/knative/pkg/pull/1857/diff?src=pr&el=tree#diff-ZGVwY2hlY2svZGVwY2hlY2suZ28=) | `50.00% <50.00%> (ø)` | |
| [test/gcs/mock/mock.go](https://codecov.io/gh/knative/pkg/pull/1857/diff?src=pr&el=tree#diff-dGVzdC9nY3MvbW9jay9tb2NrLmdv) | `90.32% <0.00%> (-2.16%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/pkg/pull/1857?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative/pkg/pull/1857?src=pr&el=footer). Last update [2fd5431...1cdee7e](https://codecov.io/gh/knative/pkg/pull/1857?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

vagababov: /lgtm
knative-prow-robot: @embano1: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-pkg-unit-tests | 1cdee7e588290f5949e9ac3bed81e29af94ced8d | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_pkg/1857/pull-knative-pkg-unit-tests/1321188158158671873) | `/test pull-knative-pkg-unit-tests`

[Full PR test history](https://gubernator.knative.dev/pr/knative_pkg/1857). [Your PR dashboard](https://gubernator.knative.dev/pr/embano1).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/RELEASE-LEADS.md b/RELEASE-LEADS.md
index 2ac26dc7a..eeb5daee1 100644
--- a/RELEASE-LEADS.md
+++ b/RELEASE-LEADS.md
@@ -56,7 +56,7 @@ This roster is seeded with all approvers from Eventing workgroups.
 | v0.25   | 2021-08-10   | vagababov      | grantr          | 2021-06-30  | 2021-08-03 |
 | v0.26   | 2021-09-21   | JRBANCEL       | ...             | 2021-08-11  | 2021-09-14 |
 
-__NOTE:__ v0.20 is moved by 3 weeks for end of year holidays
+**NOTE:** v0.20 is moved by 3 weeks for end of year holidays
 
 # Release instruction
 
diff --git a/apis/duck/patch.go b/apis/duck/patch.go
index 943ff6bb3..8fe57b888 100644
--- a/apis/duck/patch.go
+++ b/apis/duck/patch.go
@@ -19,8 +19,8 @@ package duck
 import (
 	"encoding/json"
 
-	jsonmergepatch "github.com/evanphx/json-patch"
 	jsonpatch "gomodules.xyz/jsonpatch/v2"
+	jsonmergepatch "gopkg.in/evanphx/json-patch.v4"
 )
 
 func marshallBeforeAfter(before, after interface{}) ([]byte, []byte, error) {
diff --git a/depcheck/depcheck.go b/depcheck/depcheck.go
index 18a091ad3..8febf632f 100644
--- a/depcheck/depcheck.go
+++ b/depcheck/depcheck.go
@@ -39,6 +39,15 @@ func (g graph) contains(name string) bool {
 	return ok
 }
 
+func (g graph) order() []string {
+	order := make(sort.StringSlice, 0, len(g))
+	for k := range g {
+		order = append(order, k)
+	}
+	order.Sort()
+	return order
+}
+
 // path constructs an examplary path that looks something like:
 //    knative.dev/pkg/apis/duck
 //    knative.dev/pkg/apis  # Also: [knative.dev/pkg/kmeta knative.dev/pkg/tracker]
@@ -90,21 +99,70 @@ func buildGraph(importpaths ...string) (graph, error) {
 	return g, nil
 }
 
+// CheckNoDependency checks that the given import paths (ip) does not
+// depend (transitively) on certain banned imports.
+func CheckNoDependency(ip string, banned []string) error {
+	g, err := buildGraph(ip)
+	if err != nil {
+		return fmt.Errorf("buildGraph(queue) = %v", err)
+	}
+	for _, dip := range banned {
+		if g.contains(dip) {
+			return fmt.Errorf("%s depends on banned dependency %s\n%s", ip, dip,
+				strings.Join(g.path(dip), "\n"))
+		}
+	}
+	return nil
+}
+
 // AssertNoDependency checks that the given import paths (the keys) do not
 // depend (transitively) on certain banned imports (the values)
 func AssertNoDependency(t *testing.T, banned map[string][]string) {
 	t.Helper()
 	for ip, banned := range banned {
 		t.Run(ip, func(t *testing.T) {
-			g, err := buildGraph(ip)
-			if err != nil {
-				t.Fatal("buildGraph(queue) =", err)
+			if err := CheckNoDependency(ip, banned); err != nil {
+				t.Error("CheckNoDependency() =", err)
 			}
-			for _, dip := range banned {
-				if g.contains(dip) {
-					t.Errorf("%s depends on banned dependency %s\n%s", ip, dip,
-						strings.Join(g.path(dip), "\n"))
-				}
+		})
+	}
+}
+
+// CheckOnlyDependencies checks that the given import path only
+// depends (transitively) on certain allowed imports.
+// Note: while perhaps counterintuitive we allow the value to be a superset
+// of the actual imports to that folks can use a constant that holds blessed
+// import paths.
+func CheckOnlyDependencies(ip string, allowed map[string]struct{}) error {
+	g, err := buildGraph(ip)
+	if err != nil {
+		return fmt.Errorf("buildGraph(queue) = %v", err)
+	}
+	for _, name := range g.order() {
+		if _, ok := allowed[name]; !ok {
+			return fmt.Errorf("dependency %s of %s is not explicitly allowed\n%s", name, ip,
+				strings.Join(g.path(name), "\n"))
+		}
+	}
+	return nil
+}
+
+// AssertOnlyDependencies checks that the given import paths (the keys) only
+// depend (transitively) on certain allowed imports (the values).
+// Note: while perhaps counterintuitive we allow the value to be a superset
+// of the actual imports to that folks can use a constant that holds blessed
+// import paths.
+func AssertOnlyDependencies(t *testing.T, allowed map[string][]string) {
+	t.Helper()
+	for ip, allow := range allowed {
+		// Always include our own package in the set of allowed dependencies.
+		allowed := make(map[string]struct{}, len(allow)+1)
+		for _, x := range append(allow, ip) {
+			allowed[x] = struct{}{}
+		}
+		t.Run(ip, func(t *testing.T) {
+			if err := CheckOnlyDependencies(ip, allowed); err != nil {
+				t.Error("CheckOnlyDependencies() =", err)
 			}
 		})
 	}
diff --git a/depcheck/heavy.go b/depcheck/heavy.go
new file mode 100644
index 000000000..de5e81178
--- /dev/null
+++ b/depcheck/heavy.go
@@ -0,0 +1,28 @@
+/*
+Copyright 2020 The Knative Authors
+
+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 depcheck
+
+var (
+	KnownHeavyDependencies = []string{
+		"k8s.io/apimachinery/pkg/api/apitesting/fuzzer",
+
+		// As of 2020/10/27 this adds about 13MB to overall binary size.
+		"k8s.io/client-go/kubernetes",
+		// As of 2020/10/27 this adds about 7MB to overall binary size.
+		"contrib.go.opencensus.io/exporter/stackdriver",
+	}
+)
diff --git a/go.mod b/go.mod
index f6535a091..774320432 100644
--- a/go.mod
+++ b/go.mod
@@ -9,10 +9,9 @@ require (
 	contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0
 	contrib.go.opencensus.io/exporter/stackdriver v0.13.2
 	contrib.go.opencensus.io/exporter/zipkin v0.1.1
-	github.com/blang/semver v3.5.1+incompatible
+	github.com/blang/semver/v4 v4.0.0
 	github.com/census-instrumentation/opencensus-proto v0.3.0
 	github.com/davecgh/go-spew v1.1.1
-	github.com/evanphx/json-patch v4.5.0+incompatible
 	github.com/ghodss/yaml v1.0.0
 	github.com/go-logr/logr v0.1.0
 	github.com/golang/protobuf v1.4.2
@@ -37,16 +36,19 @@ require (
 	go.uber.org/automaxprocs v1.3.0
 	go.uber.org/multierr v1.5.0
 	go.uber.org/zap v1.15.0
+	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect
 	golang.org/x/net v0.0.0-20200904194848-62affa334b73
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
 	golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
 	golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f // indirect
+	golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
 	golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3
 	gomodules.xyz/jsonpatch/v2 v2.1.0
 	google.golang.org/api v0.31.0
 	google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d
 	google.golang.org/grpc v1.31.1
 	google.golang.org/protobuf v1.25.0
+	gopkg.in/evanphx/json-patch.v4 v4.9.0
 	gopkg.in/yaml.v2 v2.3.0
 	gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
 	honnef.co/go/tools v0.0.1-2020.1.5 // indirect
@@ -57,7 +59,8 @@ require (
 	k8s.io/code-generator v0.18.8
 	k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12
 	k8s.io/klog v1.0.0
-	knative.dev/test-infra v0.0.0-20201026182042-46291de4ab66
+	k8s.io/test-infra v0.0.0-20200803112140-d8aa4e063646 // indirect
+	knative.dev/hack v0.0.0-20201027201633-1763a666eb41
 	sigs.k8s.io/boskos v0.0.0-20200729174948-794df80db9c9
 )
 
diff --git a/go.sum b/go.sum
index 5b489a5aa..f5ac3b526 100644
--- a/go.sum
+++ b/go.sum
@@ -24,8 +24,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
 cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
 cloud.google.com/go v0.60.0 h1:R+tDlceO7Ss+zyvtsdhTxacDyZ1k99xwskQ4FT7ruoM=
 cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU=
-cloud.google.com/go v0.61.0 h1:NLQf5e1OMspfNT1RAHOB3ublr1TW3YTXO8OiWwVjK2U=
-cloud.google.com/go v0.61.0/go.mod h1:XukKJg4Y7QsUu0Hxg3qQKUWR4VuWivmyMK2+rUyxAqw=
 cloud.google.com/go v0.62.0 h1:RmDygqvj27Zf3fCQjQRtLyC7KwFcHkeJitcO0OoGOcA=
 cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
 cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
@@ -48,7 +46,6 @@ cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680
 cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
 cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
 cloud.google.com/go/pubsub v1.4.0/go.mod h1:LFrqilwgdw4X2cJS9ALgzYmMu+ULyrUN6IHV3CPK4TM=
-cloud.google.com/go/pubsub v1.6.1/go.mod h1:kvW9rcn9OLEx6eTIzMBbWbpB8YsK3vu9jxgPolVz+p4=
 cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
 cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
 cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8=
@@ -103,7 +100,6 @@ github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxS
 github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest v14.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
-github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
 github.com/Azure/go-autorest/autorest v0.2.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
@@ -116,16 +112,13 @@ github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S
 github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
 github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
 github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
-github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
 github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
 github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
 github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
 github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
-github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
 github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
 github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
 github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
-github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
 github.com/Azure/go-autorest/autorest/to v0.1.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
 github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
 github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
@@ -134,7 +127,6 @@ github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRY
 github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
 github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
 github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
-github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@@ -220,7 +212,6 @@ github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi
 github.com/aws/aws-sdk-go v1.23.22/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
-github.com/aws/aws-sdk-go v1.28.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.29.32/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
 github.com/aws/aws-sdk-go v1.29.34/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
 github.com/aws/aws-sdk-go v1.30.4/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
@@ -245,6 +236,7 @@ github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
 github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
 github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
 github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
 github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE=
@@ -382,7 +374,6 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
 github.com/frankban/quicktest v1.8.1/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
@@ -402,10 +393,6 @@ github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0
 github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I=
 github.com/go-critic/go-critic v0.4.1/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g=
 github.com/go-critic/go-critic v0.4.3/go.mod h1:j4O3D4RoIwRqlZw5jJpx0BNfXWWbpcJoKu5cYSe4YmQ=
-github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
-github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
-github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -605,7 +592,6 @@ github.com/google/go-containerregistry v0.0.0-20200115214256-379933c9c22b/go.mod
 github.com/google/go-containerregistry v0.0.0-20200123184029-53ce695e4179/go.mod h1:Wtl/v6YdQxv397EREtzwgd9+Ud7Q5D8XMbi3Zazgkrs=
 github.com/google/go-containerregistry v0.0.0-20200331213917-3d03ed9b1ca2/go.mod h1:pD1UFYs7MCAx+ZLShBdttcaOSbyc8F9Na/9IZLNwJeA=
 github.com/google/go-containerregistry v0.1.1/go.mod h1:npTSyywOeILcgWqd+rvtzGWflIPPcBQhYoOONaY4ltM=
-github.com/google/go-containerregistry v0.1.4/go.mod h1:6EGiuQp36pL82lX6rFN0s9AJOVL0Mlgx/DAsYZW5X3s=
 github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
 github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
 github.com/google/go-github/v27 v27.0.6 h1:oiOZuBmGHvrGM1X9uNUAUlLgp5r1UUO/M/KnbHnLRlQ=
@@ -625,7 +611,6 @@ github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
 github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/licenseclassifier v0.0.0-20190926221455-842c0d70d702/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M=
 github.com/google/licenseclassifier v0.0.0-20200402202327-879cb1424de0/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M=
-github.com/google/licenseclassifier v0.0.0-20200708223521-3d09a0ea2f39/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M=
 github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3 h1:/o5e44nTD/QEEiWPGSFT3bSqcq3Qg7q27N9bv4gKh5M=
 github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g=
 github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
@@ -1225,7 +1210,6 @@ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV
 github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo=
 github.com/vdemeester/k8s-pkg-credentialprovider v1.13.12-1/go.mod h1:Fko0rTxEtDW2kju5Ky7yFJNS3IcNvW8IPsp4/e9oev0=
 github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c=
-github.com/vdemeester/k8s-pkg-credentialprovider v1.18.1-0.20201019120933-f1d16962a4db/go.mod h1:grWy0bkr1XO6hqbaaCKaPXqkBVlMGHYG6PGykktwbJc=
 github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
 github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
 github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
@@ -1509,8 +1493,6 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200802091954-4b90ce9b60b3 h1:qDJKu1y/1SjhWac4BQZjLljqvqiWUhjmDMnonmVGDAU=
-golang.org/x/sys v0.0.0-20200802091954-4b90ce9b60b3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc=
@@ -1618,8 +1600,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200701000337-a32c0cb1d5b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200709181711-e327e1019dfe/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200725200936-102e7d357031/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
@@ -1725,11 +1705,7 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
 google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200701001935-0939c5918c31/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200709005830-7a2ca40e9dc3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200726014623-da3ae01ef02d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200731012542-8145dea6a485 h1:wTk5DQB3+1darAz4Ldomo0r5bUOCKX7gilxQ4sb2kno=
-google.golang.org/genproto v0.0.0-20200731012542-8145dea6a485/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -1784,6 +1760,8 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/evanphx/json-patch.v4 v4.9.0 h1:T7W7A7+DTEpLTC11pkf8yfaeRfqhRj/gOPf+LtaJdNY=
+gopkg.in/evanphx/json-patch.v4 v4.9.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
 gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
@@ -1850,7 +1828,6 @@ k8s.io/client-go v0.18.8 h1:SdbLpIxk5j5YbFr1b7fq8S7mDgDjYmUxSbszyoesoDM=
 k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
 k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE=
 k8s.io/cloud-provider v0.17.4/go.mod h1:XEjKDzfD+b9MTLXQFlDGkk6Ho8SGMpaU8Uugx/KNK9U=
-k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs=
 k8s.io/code-generator v0.18.8 h1:lgO1P1wjikEtzNvj7ia+x1VC4svJ28a/r0wnOLhhOTU=
 k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
 k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
@@ -1859,7 +1836,6 @@ k8s.io/component-base v0.17.4/go.mod h1:5BRqHMbbQPm2kKu35v3G+CpVq4K0RJKC7TRioF0I
 k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
 k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls=
 k8s.io/csi-translation-lib v0.17.4/go.mod h1:CsxmjwxEI0tTNMzffIAcgR9lX4wOh6AKHdxQrT7L0oo=
-k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20190306031000-7a1b7fb0289f/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20191108084044-e500ee069b5c/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@@ -1885,7 +1861,6 @@ k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
 k8s.io/kubernetes v1.14.7/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
 k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8=
 k8s.io/legacy-cloud-providers v0.17.4/go.mod h1:FikRNoD64ECjkxO36gkDgJeiQWwyZTuBkhu+yxOc1Js=
-k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGPF4on0IyICQE=
 k8s.io/metrics v0.17.2/go.mod h1:3TkNHET4ROd+NfzNxkjoVfQ0Ob4iZnaHmSEA4vYpwLw=
 k8s.io/test-infra v0.0.0-20181019233642-2e10a0bbe9b3/go.mod h1:2NzXB13Ji0nqpyublHeiPC4FZwU0TknfvyaaNfl/BTA=
 k8s.io/test-infra v0.0.0-20191212060232-70b0b49fe247/go.mod h1:d8SKryJBXAwfCFVL4wieRez47J2NOOAb9d029sWLseQ=
@@ -1907,6 +1882,8 @@ knative.dev/caching v0.0.0-20190719140829-2032732871ff/go.mod h1:dHXFU6CGlLlbzaW
 knative.dev/caching v0.0.0-20200116200605-67bca2c83dfa/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
 knative.dev/eventing-contrib v0.6.1-0.20190723221543-5ce18048c08b/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
 knative.dev/eventing-contrib v0.11.2/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
+knative.dev/hack v0.0.0-20201027201633-1763a666eb41 h1:rr7i0FRR6oUgjK4s4kwudJR6i3AT1Ca/81h7NiWJyhU=
+knative.dev/hack v0.0.0-20201027201633-1763a666eb41/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
 knative.dev/pkg v0.0.0-20191101194912-56c2594e4f11/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
 knative.dev/pkg v0.0.0-20191111150521-6d806b998379/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
 knative.dev/pkg v0.0.0-20200207155214-fef852970f43/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
@@ -1920,8 +1897,6 @@ knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55/go.mod h1:WqF1Azka+FxP
 knative.dev/test-infra v0.0.0-20200513011557-d03429a76034/go.mod h1:aMif0KXL4g19YCYwsy4Ocjjz5xgPlseYV+B95Oo4JGE=
 knative.dev/test-infra v0.0.0-20200519015156-82551620b0a9/go.mod h1:A5b2OAXTOeHT3hHhVQm3dmtbuWvIDP7qzgtqxA3/2pE=
 knative.dev/test-infra v0.0.0-20200707183444-aed09e56ddc7/go.mod h1:RjYAhXnZqeHw9+B0zsbqSPlae0lCvjekO/nw5ZMpLCs=
-knative.dev/test-infra v0.0.0-20201026182042-46291de4ab66 h1:4GjjfWLzfsxN7xm+vkdC4AWqgTlw5mSQmTdSqPVfjlM=
-knative.dev/test-infra v0.0.0-20201026182042-46291de4ab66/go.mod h1:84HgSlMIp+oCx//g2Js61OxSVgdvrRYQMfMMr9kSSn4=
 mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
 mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
 mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
diff --git a/hack/tools.go b/hack/tools.go
index 22763c5a8..60a01af8b 100644
--- a/hack/tools.go
+++ b/hack/tools.go
@@ -27,6 +27,6 @@ import (
 	_ "k8s.io/code-generator/cmd/informer-gen"
 	_ "k8s.io/code-generator/cmd/lister-gen"
 
+	_ "knative.dev/hack"
 	_ "knative.dev/pkg/codegen/cmd/injection-gen"
-	_ "knative.dev/test-infra/scripts"
 )
diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh
index 0743ad689..8ba165d1e 100755
--- a/hack/update-codegen.sh
+++ b/hack/update-codegen.sh
@@ -26,7 +26,7 @@ if [ -z "${GOPATH:-}" ]; then
   export GOPATH=$(go env GOPATH)
 fi
 
-source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/library.sh
+source $(dirname $0)/../vendor/knative.dev/hack/library.sh
 
 CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
 
diff --git a/hack/update-deps.sh b/hack/update-deps.sh
index 0d69b87c8..68bfa5f6a 100755
--- a/hack/update-deps.sh
+++ b/hack/update-deps.sh
@@ -18,6 +18,6 @@ set -o errexit
 set -o nounset
 set -o pipefail
 
-source $(dirname "$0")/../vendor/knative.dev/test-infra/scripts/library.sh
+source $(dirname "$0")/../vendor/knative.dev/hack/library.sh
 
 go_update_deps "$@"
diff --git a/hack/verify-codegen.sh b/hack/verify-codegen.sh
index 055a1091a..59fbeea85 100755
--- a/hack/verify-codegen.sh
+++ b/hack/verify-codegen.sh
@@ -18,7 +18,7 @@ set -o errexit
 set -o nounset
 set -o pipefail
 
-source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/library.sh
+source $(dirname $0)/../vendor/knative.dev/hack/library.sh
 
 readonly TMP_DIFFROOT="$(mktemp -d ${REPO_ROOT_DIR}/tmpdiffroot.XXXXXX)"
 
diff --git a/signals/signal.go b/signals/signal.go
index b9ba9eaf3..65bab4253 100644
--- a/signals/signal.go
+++ b/signals/signal.go
@@ -18,7 +18,6 @@ package signals
 
 import (
 	"context"
-	"errors"
 	"os"
 	"os/signal"
 	"time"
@@ -65,12 +64,14 @@ func (scc *signalContext) Done() <-chan struct{} {
 	return scc.stopCh
 }
 
-// Err implements context.Context
+// Err implements context.Context. If the underlying stop channel is closed, Err
+// always returns context.Canceled, and nil otherwise.
 func (scc *signalContext) Err() error {
 	select {
 	case _, ok := <-scc.Done():
 		if !ok {
-			return errors.New("received a termination signal")
+			// TODO: revisit this behavior when Deadline() implementation is changed
+			return context.Canceled
 		}
 	default:
 	}
diff --git a/third_party/VENDOR-LICENSE/github.com/blang/semver/LICENSE b/third_party/VENDOR-LICENSE/github.com/blang/semver/v4/LICENSE
similarity index 100%
rename from third_party/VENDOR-LICENSE/github.com/blang/semver/LICENSE
rename to third_party/VENDOR-LICENSE/github.com/blang/semver/v4/LICENSE
diff --git a/third_party/VENDOR-LICENSE/gopkg.in/evanphx/json-patch.v4/LICENSE b/third_party/VENDOR-LICENSE/gopkg.in/evanphx/json-patch.v4/LICENSE
new file mode 100644
index 000000000..df76d7d77
--- /dev/null
+++ b/third_party/VENDOR-LICENSE/gopkg.in/evanphx/json-patch.v4/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2014, Evan Phoenix
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the Evan Phoenix nor the names of its contributors 
+  may be used to endorse or promote products derived from this software 
+  without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/blang/semver/.travis.yml b/vendor/github.com/blang/semver/.travis.yml
deleted file mode 100644
index 102fb9a69..000000000
--- a/vendor/github.com/blang/semver/.travis.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-language: go
-matrix:
-  include:
-  - go: 1.4.3
-  - go: 1.5.4
-  - go: 1.6.3
-  - go: 1.7
-  - go: tip
-  allow_failures:
-  - go: tip
-install:
-- go get golang.org/x/tools/cmd/cover
-- go get github.com/mattn/goveralls
-script:
-- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
-  -repotoken $COVERALLS_TOKEN
-- echo "Build examples" ; cd examples && go build
-- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
-env:
-  global:
-    secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=
diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md
deleted file mode 100644
index 08b2e4a3d..000000000
--- a/vendor/github.com/blang/semver/README.md
+++ /dev/null
@@ -1,194 +0,0 @@
-semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master)
-======
-
-semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
-
-Usage
------
-```bash
-$ go get github.com/blang/semver
-```
-Note: Always vendor your dependencies or fix on a specific version tag.
-
-```go
-import github.com/blang/semver
-v1, err := semver.Make("1.0.0-beta")
-v2, err := semver.Make("2.0.0-beta")
-v1.Compare(v2)
-```
-
-Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
-
-Why should I use this lib?
------
-
-- Fully spec compatible
-- No reflection
-- No regex
-- Fully tested (Coverage >99%)
-- Readable parsing/validation errors
-- Fast (See [Benchmarks](#benchmarks))
-- Only Stdlib
-- Uses values instead of pointers
-- Many features, see below
-
-
-Features
------
-
-- Parsing and validation at all levels
-- Comparator-like comparisons
-- Compare Helper Methods
-- InPlace manipulation
-- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
-- Wildcards `>=1.x`, `<=2.5.x`
-- Sortable (implements sort.Interface)
-- database/sql compatible (sql.Scanner/Valuer)
-- encoding/json compatible (json.Marshaler/Unmarshaler)
-
-Ranges
-------
-
-A `Range` is a set of conditions which specify which versions satisfy the range.
-
-A condition is composed of an operator and a version. The supported operators are:
-
-- `<1.0.0` Less than `1.0.0`
-- `<=1.0.0` Less than or equal to `1.0.0`
-- `>1.0.0` Greater than `1.0.0`
-- `>=1.0.0` Greater than or equal to `1.0.0`
-- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
-- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
-
-Note that spaces between the operator and the version will be gracefully tolerated.
-
-A `Range` can link multiple `Ranges` separated by space:
-
-Ranges can be linked by logical AND:
-
-  - `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
-  - `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
-
-Ranges can also be linked by logical OR:
-
-  - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
-
-AND has a higher precedence than OR. It's not possible to use brackets.
-
-Ranges can be combined by both AND and OR
-
-  - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
-
-Range usage:
-
-```
-v, err := semver.Parse("1.2.3")
-range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
-if range(v) {
-    //valid
-}
-
-```
-
-Example
------
-
-Have a look at full examples in [examples/main.go](examples/main.go)
-
-```go
-import github.com/blang/semver
-
-v, err := semver.Make("0.0.1-alpha.preview+123.github")
-fmt.Printf("Major: %d\n", v.Major)
-fmt.Printf("Minor: %d\n", v.Minor)
-fmt.Printf("Patch: %d\n", v.Patch)
-fmt.Printf("Pre: %s\n", v.Pre)
-fmt.Printf("Build: %s\n", v.Build)
-
-// Prerelease versions array
-if len(v.Pre) > 0 {
-    fmt.Println("Prerelease versions:")
-    for i, pre := range v.Pre {
-        fmt.Printf("%d: %q\n", i, pre)
-    }
-}
-
-// Build meta data array
-if len(v.Build) > 0 {
-    fmt.Println("Build meta data:")
-    for i, build := range v.Build {
-        fmt.Printf("%d: %q\n", i, build)
-    }
-}
-
-v001, err := semver.Make("0.0.1")
-// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
-v001.GT(v) == true
-v.LT(v001) == true
-v.GTE(v) == true
-v.LTE(v) == true
-
-// Or use v.Compare(v2) for comparisons (-1, 0, 1):
-v001.Compare(v) == 1
-v.Compare(v001) == -1
-v.Compare(v) == 0
-
-// Manipulate Version in place:
-v.Pre[0], err = semver.NewPRVersion("beta")
-if err != nil {
-    fmt.Printf("Error parsing pre release version: %q", err)
-}
-
-fmt.Println("\nValidate versions:")
-v.Build[0] = "?"
-
-err = v.Validate()
-if err != nil {
-    fmt.Printf("Validation failed: %s\n", err)
-}
-```
-
-
-Benchmarks
------
-
-    BenchmarkParseSimple-4           5000000    390    ns/op    48 B/op   1 allocs/op
-    BenchmarkParseComplex-4          1000000   1813    ns/op   256 B/op   7 allocs/op
-    BenchmarkParseAverage-4          1000000   1171    ns/op   163 B/op   4 allocs/op
-    BenchmarkStringSimple-4         20000000    119    ns/op    16 B/op   1 allocs/op
-    BenchmarkStringLarger-4         10000000    206    ns/op    32 B/op   2 allocs/op
-    BenchmarkStringComplex-4         5000000    324    ns/op    80 B/op   3 allocs/op
-    BenchmarkStringAverage-4         5000000    273    ns/op    53 B/op   2 allocs/op
-    BenchmarkValidateSimple-4      200000000      9.33 ns/op     0 B/op   0 allocs/op
-    BenchmarkValidateComplex-4       3000000    469    ns/op     0 B/op   0 allocs/op
-    BenchmarkValidateAverage-4       5000000    256    ns/op     0 B/op   0 allocs/op
-    BenchmarkCompareSimple-4       100000000     11.8  ns/op     0 B/op   0 allocs/op
-    BenchmarkCompareComplex-4       50000000     30.8  ns/op     0 B/op   0 allocs/op
-    BenchmarkCompareAverage-4       30000000     41.5  ns/op     0 B/op   0 allocs/op
-    BenchmarkSort-4                  3000000    419    ns/op   256 B/op   2 allocs/op
-    BenchmarkRangeParseSimple-4      2000000    850    ns/op   192 B/op   5 allocs/op
-    BenchmarkRangeParseAverage-4     1000000   1677    ns/op   400 B/op  10 allocs/op
-    BenchmarkRangeParseComplex-4      300000   5214    ns/op  1440 B/op  30 allocs/op
-    BenchmarkRangeMatchSimple-4     50000000     25.6  ns/op     0 B/op   0 allocs/op
-    BenchmarkRangeMatchAverage-4    30000000     56.4  ns/op     0 B/op   0 allocs/op
-    BenchmarkRangeMatchComplex-4    10000000    153    ns/op     0 B/op   0 allocs/op
-
-See benchmark cases at [semver_test.go](semver_test.go)
-
-
-Motivation
------
-
-I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
-
-
-Contribution
------
-
-Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
-
-
-License
------
-
-See [LICENSE](LICENSE) file.
diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json
deleted file mode 100644
index 1cf8ebdd9..000000000
--- a/vendor/github.com/blang/semver/package.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "author": "blang",
-  "bugs": {
-    "URL": "https://github.com/blang/semver/issues",
-    "url": "https://github.com/blang/semver/issues"
-  },
-  "gx": {
-    "dvcsimport": "github.com/blang/semver"
-  },
-  "gxVersion": "0.10.0",
-  "language": "go",
-  "license": "MIT",
-  "name": "semver",
-  "releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
-  "version": "3.5.1"
-}
-
diff --git a/vendor/github.com/blang/semver/LICENSE b/vendor/github.com/blang/semver/v4/LICENSE
similarity index 100%
rename from vendor/github.com/blang/semver/LICENSE
rename to vendor/github.com/blang/semver/v4/LICENSE
diff --git a/vendor/github.com/blang/semver/v4/go.mod b/vendor/github.com/blang/semver/v4/go.mod
new file mode 100644
index 000000000..06d262218
--- /dev/null
+++ b/vendor/github.com/blang/semver/v4/go.mod
@@ -0,0 +1,3 @@
+module github.com/blang/semver/v4
+
+go 1.14
diff --git a/vendor/github.com/blang/semver/json.go b/vendor/github.com/blang/semver/v4/json.go
similarity index 100%
rename from vendor/github.com/blang/semver/json.go
rename to vendor/github.com/blang/semver/v4/json.go
diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/v4/range.go
similarity index 99%
rename from vendor/github.com/blang/semver/range.go
rename to vendor/github.com/blang/semver/v4/range.go
index fca406d47..95f7139b9 100644
--- a/vendor/github.com/blang/semver/range.go
+++ b/vendor/github.com/blang/semver/v4/range.go
@@ -327,7 +327,7 @@ func expandWildcardVersion(parts [][]string) ([][]string, error) {
 	for _, p := range parts {
 		var newParts []string
 		for _, ap := range p {
-			if strings.Index(ap, "x") != -1 {
+			if strings.Contains(ap, "x") {
 				opStr, vStr, err := splitComparatorVersion(ap)
 				if err != nil {
 					return nil, err
diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/v4/semver.go
similarity index 85%
rename from vendor/github.com/blang/semver/semver.go
rename to vendor/github.com/blang/semver/v4/semver.go
index 8ee0842e6..307de610f 100644
--- a/vendor/github.com/blang/semver/semver.go
+++ b/vendor/github.com/blang/semver/v4/semver.go
@@ -26,7 +26,7 @@ type Version struct {
 	Minor uint64
 	Patch uint64
 	Pre   []PRVersion
-	Build []string //No Precendence
+	Build []string //No Precedence
 }
 
 // Version to string
@@ -61,6 +61,18 @@ func (v Version) String() string {
 	return string(b)
 }
 
+// FinalizeVersion discards prerelease and build number and only returns
+// major, minor and patch number.
+func (v Version) FinalizeVersion() string {
+	b := make([]byte, 0, 5)
+	b = strconv.AppendUint(b, v.Major, 10)
+	b = append(b, '.')
+	b = strconv.AppendUint(b, v.Minor, 10)
+	b = append(b, '.')
+	b = strconv.AppendUint(b, v.Patch, 10)
+	return string(b)
+}
+
 // Equals checks if v is equal to o.
 func (v Version) Equals(o Version) bool {
 	return (v.Compare(o) == 0)
@@ -161,6 +173,27 @@ func (v Version) Compare(o Version) int {
 
 }
 
+// IncrementPatch increments the patch version
+func (v *Version) IncrementPatch() error {
+	v.Patch++
+	return nil
+}
+
+// IncrementMinor increments the minor version
+func (v *Version) IncrementMinor() error {
+	v.Minor++
+	v.Patch = 0
+	return nil
+}
+
+// IncrementMajor increments the major version
+func (v *Version) IncrementMajor() error {
+	v.Major++
+	v.Minor = 0
+	v.Patch = 0
+	return nil
+}
+
 // Validate validates v and returns error in case
 func (v Version) Validate() error {
 	// Major, Minor, Patch already validated using uint64
@@ -189,10 +222,10 @@ func (v Version) Validate() error {
 }
 
 // New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
-func New(s string) (vp *Version, err error) {
+func New(s string) (*Version, error) {
 	v, err := Parse(s)
-	vp = &v
-	return
+	vp := &v
+	return vp, err
 }
 
 // Make is an alias for Parse, parses version string and returns a validated Version or error
@@ -202,14 +235,25 @@ func Make(s string) (Version, error) {
 
 // ParseTolerant allows for certain version specifications that do not strictly adhere to semver
 // specs to be parsed by this library. It does so by normalizing versions before passing them to
-// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
-// with only major and minor components specified
+// Parse(). It currently trims spaces, removes a "v" prefix, adds a 0 patch number to versions
+// with only major and minor components specified, and removes leading 0s.
 func ParseTolerant(s string) (Version, error) {
 	s = strings.TrimSpace(s)
 	s = strings.TrimPrefix(s, "v")
 
 	// Split into major.minor.(patch+pr+meta)
 	parts := strings.SplitN(s, ".", 3)
+	// Remove leading zeros.
+	for i, p := range parts {
+		if len(p) > 1 {
+			p = strings.TrimLeft(p, "0")
+			if len(p) == 0 || !strings.ContainsAny(p[0:1], "0123456789") {
+				p = "0" + p
+			}
+			parts[i] = p
+		}
+	}
+	// Fill up shortened versions.
 	if len(parts) < 3 {
 		if strings.ContainsAny(parts[len(parts)-1], "+-") {
 			return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
@@ -217,8 +261,8 @@ func ParseTolerant(s string) (Version, error) {
 		for len(parts) < 3 {
 			parts = append(parts, "0")
 		}
-		s = strings.Join(parts, ".")
 	}
+	s = strings.Join(parts, ".")
 
 	return Parse(s)
 }
@@ -416,3 +460,17 @@ func NewBuildVersion(s string) (string, error) {
 	}
 	return s, nil
 }
+
+// FinalizeVersion returns the major, minor and patch number only and discards
+// prerelease and build number.
+func FinalizeVersion(s string) (string, error) {
+	v, err := Parse(s)
+	if err != nil {
+		return "", err
+	}
+	v.Pre = nil
+	v.Build = nil
+
+	finalVer := v.String()
+	return finalVer, nil
+}
diff --git a/vendor/github.com/blang/semver/sort.go b/vendor/github.com/blang/semver/v4/sort.go
similarity index 100%
rename from vendor/github.com/blang/semver/sort.go
rename to vendor/github.com/blang/semver/v4/sort.go
diff --git a/vendor/github.com/blang/semver/sql.go b/vendor/github.com/blang/semver/v4/sql.go
similarity index 87%
rename from vendor/github.com/blang/semver/sql.go
rename to vendor/github.com/blang/semver/v4/sql.go
index eb4d80266..db958134f 100644
--- a/vendor/github.com/blang/semver/sql.go
+++ b/vendor/github.com/blang/semver/v4/sql.go
@@ -14,7 +14,7 @@ func (v *Version) Scan(src interface{}) (err error) {
 	case []byte:
 		str = string(src)
 	default:
-		return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
+		return fmt.Errorf("version.Scan: cannot convert %T to string", src)
 	}
 
 	if t, err := Parse(str); err == nil {
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/.travis.yml b/vendor/gopkg.in/evanphx/json-patch.v4/.travis.yml
new file mode 100644
index 000000000..50e4afd19
--- /dev/null
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/.travis.yml
@@ -0,0 +1,19 @@
+language: go
+
+go:
+  - 1.14
+  - 1.13
+
+install:
+  - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
+  - go get github.com/jessevdk/go-flags
+
+script:
+  - go get
+  - go test -cover ./...
+  - cd ./v5
+  - go get
+  - go test -cover ./...
+
+notifications:
+  email: false
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/LICENSE b/vendor/gopkg.in/evanphx/json-patch.v4/LICENSE
new file mode 100644
index 000000000..df76d7d77
--- /dev/null
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2014, Evan Phoenix
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the Evan Phoenix nor the names of its contributors 
+  may be used to endorse or promote products derived from this software 
+  without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/README.md b/vendor/gopkg.in/evanphx/json-patch.v4/README.md
new file mode 100644
index 000000000..121b039db
--- /dev/null
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/README.md
@@ -0,0 +1,298 @@
+# JSON-Patch
+`jsonpatch` is a library which provides functionality for both applying
+[RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902) against documents, as
+well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).
+
+[![GoDoc](https://godoc.org/github.com/evanphx/json-patch?status.svg)](http://godoc.org/github.com/evanphx/json-patch)
+[![Build Status](https://travis-ci.org/evanphx/json-patch.svg?branch=master)](https://travis-ci.org/evanphx/json-patch)
+[![Report Card](https://goreportcard.com/badge/github.com/evanphx/json-patch)](https://goreportcard.com/report/github.com/evanphx/json-patch)
+
+# Get It!
+
+**Latest and greatest**: 
+```bash
+go get -u github.com/evanphx/json-patch/v5
+```
+
+**Stable Versions**:
+* Version 5: `go get -u gopkg.in/evanphx/json-patch.v5`
+* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`
+
+(previous versions below `v3` are unavailable)
+
+# Use It!
+* [Create and apply a merge patch](#create-and-apply-a-merge-patch)
+* [Create and apply a JSON Patch](#create-and-apply-a-json-patch)
+* [Comparing JSON documents](#comparing-json-documents)
+* [Combine merge patches](#combine-merge-patches)
+
+
+# Configuration
+
+* There is a global configuration variable `jsonpatch.SupportNegativeIndices`.
+  This defaults to `true` and enables the non-standard practice of allowing
+  negative indices to mean indices starting at the end of an array. This
+  functionality can be disabled by setting `jsonpatch.SupportNegativeIndices =
+  false`.
+
+* There is a global configuration variable `jsonpatch.AccumulatedCopySizeLimit`,
+  which limits the total size increase in bytes caused by "copy" operations in a
+  patch. It defaults to 0, which means there is no limit.
+
+## Create and apply a merge patch
+Given both an original JSON document and a modified JSON document, you can create
+a [Merge Patch](https://tools.ietf.org/html/rfc7396) document. 
+
+It can describe the changes needed to convert from the original to the 
+modified JSON document.
+
+Once you have a merge patch, you can apply it to other JSON documents using the
+`jsonpatch.MergePatch(document, patch)` function.
+
+```go
+package main
+
+import (
+	"fmt"
+
+	jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+	// Let's create a merge patch from these two documents...
+	original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+	target := []byte(`{"name": "Jane", "age": 24}`)
+
+	patch, err := jsonpatch.CreateMergePatch(original, target)
+	if err != nil {
+		panic(err)
+	}
+
+	// Now lets apply the patch against a different JSON document...
+
+	alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`)
+	modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch)
+
+	fmt.Printf("patch document:   %s\n", patch)
+	fmt.Printf("updated alternative doc: %s\n", modifiedAlternative)
+}
+```
+
+When ran, you get the following output:
+
+```bash
+$ go run main.go
+patch document:   {"height":null,"name":"Jane"}
+updated alternative doc: {"age":28,"name":"Jane"}
+```
+
+## Create and apply a JSON Patch
+You can create patch objects using `DecodePatch([]byte)`, which can then 
+be applied against JSON documents.
+
+The following is an example of creating a patch from two operations, and
+applying it against a JSON document.
+
+```go
+package main
+
+import (
+	"fmt"
+
+	jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+	original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+	patchJSON := []byte(`[
+		{"op": "replace", "path": "/name", "value": "Jane"},
+		{"op": "remove", "path": "/height"}
+	]`)
+
+	patch, err := jsonpatch.DecodePatch(patchJSON)
+	if err != nil {
+		panic(err)
+	}
+
+	modified, err := patch.Apply(original)
+	if err != nil {
+		panic(err)
+	}
+
+	fmt.Printf("Original document: %s\n", original)
+	fmt.Printf("Modified document: %s\n", modified)
+}
+```
+
+When ran, you get the following output:
+
+```bash
+$ go run main.go
+Original document: {"name": "John", "age": 24, "height": 3.21}
+Modified document: {"age":24,"name":"Jane"}
+```
+
+## Comparing JSON documents
+Due to potential whitespace and ordering differences, one cannot simply compare
+JSON strings or byte-arrays directly. 
+
+As such, you can instead use `jsonpatch.Equal(document1, document2)` to 
+determine if two JSON documents are _structurally_ equal. This ignores
+whitespace differences, and key-value ordering.
+
+```go
+package main
+
+import (
+	"fmt"
+
+	jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+	original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+	similar := []byte(`
+		{
+			"age": 24,
+			"height": 3.21,
+			"name": "John"
+		}
+	`)
+	different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`)
+
+	if jsonpatch.Equal(original, similar) {
+		fmt.Println(`"original" is structurally equal to "similar"`)
+	}
+
+	if !jsonpatch.Equal(original, different) {
+		fmt.Println(`"original" is _not_ structurally equal to "different"`)
+	}
+}
+```
+
+When ran, you get the following output:
+```bash
+$ go run main.go
+"original" is structurally equal to "similar"
+"original" is _not_ structurally equal to "different"
+```
+
+## Combine merge patches
+Given two JSON merge patch documents, it is possible to combine them into a 
+single merge patch which can describe both set of changes.
+
+The resulting merge patch can be used such that applying it results in a
+document structurally similar as merging each merge patch to the document
+in succession. 
+
+```go
+package main
+
+import (
+	"fmt"
+
+	jsonpatch "github.com/evanphx/json-patch"
+)
+
+func main() {
+	original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
+
+	nameAndHeight := []byte(`{"height":null,"name":"Jane"}`)
+	ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`)
+
+	// Let's combine these merge patch documents...
+	combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes)
+	if err != nil {
+		panic(err)
+	}
+
+	// Apply each patch individual against the original document
+	withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight)
+	if err != nil {
+		panic(err)
+	}
+
+	withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes)
+	if err != nil {
+		panic(err)
+	}
+
+	// Apply the combined patch against the original document
+
+	withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch)
+	if err != nil {
+		panic(err)
+	}
+
+	// Do both result in the same thing? They should!
+	if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) {
+		fmt.Println("Both JSON documents are structurally the same!")
+	}
+
+	fmt.Printf("combined merge patch: %s", combinedPatch)
+}
+```
+
+When ran, you get the following output:
+```bash
+$ go run main.go
+Both JSON documents are structurally the same!
+combined merge patch: {"age":4.23,"eyes":"blue","height":null,"name":"Jane"}
+```
+
+# CLI for comparing JSON documents
+You can install the commandline program `json-patch`.
+
+This program can take multiple JSON patch documents as arguments, 
+and fed a JSON document from `stdin`. It will apply the patch(es) against 
+the document and output the modified doc.
+
+**patch.1.json**
+```json
+[
+    {"op": "replace", "path": "/name", "value": "Jane"},
+    {"op": "remove", "path": "/height"}
+]
+```
+
+**patch.2.json**
+```json
+[
+    {"op": "add", "path": "/address", "value": "123 Main St"},
+    {"op": "replace", "path": "/age", "value": "21"}
+]
+```
+
+**document.json**
+```json
+{
+    "name": "John",
+    "age": 24,
+    "height": 3.21
+}
+```
+
+You can then run:
+
+```bash
+$ go install github.com/evanphx/json-patch/cmd/json-patch
+$ cat document.json | json-patch -p patch.1.json -p patch.2.json
+{"address":"123 Main St","age":"21","name":"Jane"}
+```
+
+# Help It!
+Contributions are welcomed! Leave [an issue](https://github.com/evanphx/json-patch/issues)
+or [create a PR](https://github.com/evanphx/json-patch/compare).
+
+
+Before creating a pull request, we'd ask that you make sure tests are passing
+and that you have added new tests when applicable.
+
+Contributors can run tests using:
+
+```bash
+go test -cover ./...
+```
+
+Builds for pull requests are tested automatically 
+using [TravisCI](https://travis-ci.org/evanphx/json-patch).
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/errors.go b/vendor/gopkg.in/evanphx/json-patch.v4/errors.go
new file mode 100644
index 000000000..75304b443
--- /dev/null
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/errors.go
@@ -0,0 +1,38 @@
+package jsonpatch
+
+import "fmt"
+
+// AccumulatedCopySizeError is an error type returned when the accumulated size
+// increase caused by copy operations in a patch operation has exceeded the
+// limit.
+type AccumulatedCopySizeError struct {
+	limit       int64
+	accumulated int64
+}
+
+// NewAccumulatedCopySizeError returns an AccumulatedCopySizeError.
+func NewAccumulatedCopySizeError(l, a int64) *AccumulatedCopySizeError {
+	return &AccumulatedCopySizeError{limit: l, accumulated: a}
+}
+
+// Error implements the error interface.
+func (a *AccumulatedCopySizeError) Error() string {
+	return fmt.Sprintf("Unable to complete the copy, the accumulated size increase of copy is %d, exceeding the limit %d", a.accumulated, a.limit)
+}
+
+// ArraySizeError is an error type returned when the array size has exceeded
+// the limit.
+type ArraySizeError struct {
+	limit int
+	size  int
+}
+
+// NewArraySizeError returns an ArraySizeError.
+func NewArraySizeError(l, s int) *ArraySizeError {
+	return &ArraySizeError{limit: l, size: s}
+}
+
+// Error implements the error interface.
+func (a *ArraySizeError) Error() string {
+	return fmt.Sprintf("Unable to create array of size %d, limit is %d", a.size, a.limit)
+}
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/merge.go b/vendor/gopkg.in/evanphx/json-patch.v4/merge.go
new file mode 100644
index 000000000..14e8bb5ce
--- /dev/null
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/merge.go
@@ -0,0 +1,386 @@
+package jsonpatch
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"reflect"
+)
+
+func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode {
+	curDoc, err := cur.intoDoc()
+
+	if err != nil {
+		pruneNulls(patch)
+		return patch
+	}
+
+	patchDoc, err := patch.intoDoc()
+
+	if err != nil {
+		return patch
+	}
+
+	mergeDocs(curDoc, patchDoc, mergeMerge)
+
+	return cur
+}
+
+func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
+	for k, v := range *patch {
+		if v == nil {
+			if mergeMerge {
+				(*doc)[k] = nil
+			} else {
+				delete(*doc, k)
+			}
+		} else {
+			cur, ok := (*doc)[k]
+
+			if !ok || cur == nil {
+				pruneNulls(v)
+				(*doc)[k] = v
+			} else {
+				(*doc)[k] = merge(cur, v, mergeMerge)
+			}
+		}
+	}
+}
+
+func pruneNulls(n *lazyNode) {
+	sub, err := n.intoDoc()
+
+	if err == nil {
+		pruneDocNulls(sub)
+	} else {
+		ary, err := n.intoAry()
+
+		if err == nil {
+			pruneAryNulls(ary)
+		}
+	}
+}
+
+func pruneDocNulls(doc *partialDoc) *partialDoc {
+	for k, v := range *doc {
+		if v == nil {
+			delete(*doc, k)
+		} else {
+			pruneNulls(v)
+		}
+	}
+
+	return doc
+}
+
+func pruneAryNulls(ary *partialArray) *partialArray {
+	newAry := []*lazyNode{}
+
+	for _, v := range *ary {
+		if v != nil {
+			pruneNulls(v)
+			newAry = append(newAry, v)
+		}
+	}
+
+	*ary = newAry
+
+	return ary
+}
+
+var errBadJSONDoc = fmt.Errorf("Invalid JSON Document")
+var errBadJSONPatch = fmt.Errorf("Invalid JSON Patch")
+var errBadMergeTypes = fmt.Errorf("Mismatched JSON Documents")
+
+// MergeMergePatches merges two merge patches together, such that
+// applying this resulting merged merge patch to a document yields the same
+// as merging each merge patch to the document in succession.
+func MergeMergePatches(patch1Data, patch2Data []byte) ([]byte, error) {
+	return doMergePatch(patch1Data, patch2Data, true)
+}
+
+// MergePatch merges the patchData into the docData.
+func MergePatch(docData, patchData []byte) ([]byte, error) {
+	return doMergePatch(docData, patchData, false)
+}
+
+func doMergePatch(docData, patchData []byte, mergeMerge bool) ([]byte, error) {
+	doc := &partialDoc{}
+
+	docErr := json.Unmarshal(docData, doc)
+
+	patch := &partialDoc{}
+
+	patchErr := json.Unmarshal(patchData, patch)
+
+	if _, ok := docErr.(*json.SyntaxError); ok {
+		return nil, errBadJSONDoc
+	}
+
+	if _, ok := patchErr.(*json.SyntaxError); ok {
+		return nil, errBadJSONPatch
+	}
+
+	if docErr == nil && *doc == nil {
+		return nil, errBadJSONDoc
+	}
+
+	if patchErr == nil && *patch == nil {
+		return nil, errBadJSONPatch
+	}
+
+	if docErr != nil || patchErr != nil {
+		// Not an error, just not a doc, so we turn straight into the patch
+		if patchErr == nil {
+			if mergeMerge {
+				doc = patch
+			} else {
+				doc = pruneDocNulls(patch)
+			}
+		} else {
+			patchAry := &partialArray{}
+			patchErr = json.Unmarshal(patchData, patchAry)
+
+			if patchErr != nil {
+				return nil, errBadJSONPatch
+			}
+
+			pruneAryNulls(patchAry)
+
+			out, patchErr := json.Marshal(patchAry)
+
+			if patchErr != nil {
+				return nil, errBadJSONPatch
+			}
+
+			return out, nil
+		}
+	} else {
+		mergeDocs(doc, patch, mergeMerge)
+	}
+
+	return json.Marshal(doc)
+}
+
+// resemblesJSONArray indicates whether the byte-slice "appears" to be
+// a JSON array or not.
+// False-positives are possible, as this function does not check the internal
+// structure of the array. It only checks that the outer syntax is present and
+// correct.
+func resemblesJSONArray(input []byte) bool {
+	input = bytes.TrimSpace(input)
+
+	hasPrefix := bytes.HasPrefix(input, []byte("["))
+	hasSuffix := bytes.HasSuffix(input, []byte("]"))
+
+	return hasPrefix && hasSuffix
+}
+
+// CreateMergePatch will return a merge patch document capable of converting
+// the original document(s) to the modified document(s).
+// The parameters can be bytes of either two JSON Documents, or two arrays of
+// JSON documents.
+// The merge patch returned follows the specification defined at http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch-07
+func CreateMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
+	originalResemblesArray := resemblesJSONArray(originalJSON)
+	modifiedResemblesArray := resemblesJSONArray(modifiedJSON)
+
+	// Do both byte-slices seem like JSON arrays?
+	if originalResemblesArray && modifiedResemblesArray {
+		return createArrayMergePatch(originalJSON, modifiedJSON)
+	}
+
+	// Are both byte-slices are not arrays? Then they are likely JSON objects...
+	if !originalResemblesArray && !modifiedResemblesArray {
+		return createObjectMergePatch(originalJSON, modifiedJSON)
+	}
+
+	// None of the above? Then return an error because of mismatched types.
+	return nil, errBadMergeTypes
+}
+
+// createObjectMergePatch will return a merge-patch document capable of
+// converting the original document to the modified document.
+func createObjectMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
+	originalDoc := map[string]interface{}{}
+	modifiedDoc := map[string]interface{}{}
+
+	err := json.Unmarshal(originalJSON, &originalDoc)
+	if err != nil {
+		return nil, errBadJSONDoc
+	}
+
+	err = json.Unmarshal(modifiedJSON, &modifiedDoc)
+	if err != nil {
+		return nil, errBadJSONDoc
+	}
+
+	dest, err := getDiff(originalDoc, modifiedDoc)
+	if err != nil {
+		return nil, err
+	}
+
+	return json.Marshal(dest)
+}
+
+// createArrayMergePatch will return an array of merge-patch documents capable
+// of converting the original document to the modified document for each
+// pair of JSON documents provided in the arrays.
+// Arrays of mismatched sizes will result in an error.
+func createArrayMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
+	originalDocs := []json.RawMessage{}
+	modifiedDocs := []json.RawMessage{}
+
+	err := json.Unmarshal(originalJSON, &originalDocs)
+	if err != nil {
+		return nil, errBadJSONDoc
+	}
+
+	err = json.Unmarshal(modifiedJSON, &modifiedDocs)
+	if err != nil {
+		return nil, errBadJSONDoc
+	}
+
+	total := len(originalDocs)
+	if len(modifiedDocs) != total {
+		return nil, errBadJSONDoc
+	}
+
+	result := []json.RawMessage{}
+	for i := 0; i < len(originalDocs); i++ {
+		original := originalDocs[i]
+		modified := modifiedDocs[i]
+
+		patch, err := createObjectMergePatch(original, modified)
+		if err != nil {
+			return nil, err
+		}
+
+		result = append(result, json.RawMessage(patch))
+	}
+
+	return json.Marshal(result)
+}
+
+// Returns true if the array matches (must be json types).
+// As is idiomatic for go, an empty array is not the same as a nil array.
+func matchesArray(a, b []interface{}) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	if (a == nil && b != nil) || (a != nil && b == nil) {
+		return false
+	}
+	for i := range a {
+		if !matchesValue(a[i], b[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+// Returns true if the values matches (must be json types)
+// The types of the values must match, otherwise it will always return false
+// If two map[string]interface{} are given, all elements must match.
+func matchesValue(av, bv interface{}) bool {
+	if reflect.TypeOf(av) != reflect.TypeOf(bv) {
+		return false
+	}
+	switch at := av.(type) {
+	case string:
+		bt := bv.(string)
+		if bt == at {
+			return true
+		}
+	case float64:
+		bt := bv.(float64)
+		if bt == at {
+			return true
+		}
+	case bool:
+		bt := bv.(bool)
+		if bt == at {
+			return true
+		}
+	case nil:
+		// Both nil, fine.
+		return true
+	case map[string]interface{}:
+		bt := bv.(map[string]interface{})
+		if len(bt) != len(at) {
+			return false
+		}
+		for key := range bt {
+			av, aOK := at[key]
+			bv, bOK := bt[key]
+			if aOK != bOK {
+				return false
+			}
+			if !matchesValue(av, bv) {
+				return false
+			}
+		}
+		return true
+	case []interface{}:
+		bt := bv.([]interface{})
+		return matchesArray(at, bt)
+	}
+	return false
+}
+
+// getDiff returns the (recursive) difference between a and b as a map[string]interface{}.
+func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
+	into := map[string]interface{}{}
+	for key, bv := range b {
+		av, ok := a[key]
+		// value was added
+		if !ok {
+			into[key] = bv
+			continue
+		}
+		// If types have changed, replace completely
+		if reflect.TypeOf(av) != reflect.TypeOf(bv) {
+			into[key] = bv
+			continue
+		}
+		// Types are the same, compare values
+		switch at := av.(type) {
+		case map[string]interface{}:
+			bt := bv.(map[string]interface{})
+			dst := make(map[string]interface{}, len(bt))
+			dst, err := getDiff(at, bt)
+			if err != nil {
+				return nil, err
+			}
+			if len(dst) > 0 {
+				into[key] = dst
+			}
+		case string, float64, bool:
+			if !matchesValue(av, bv) {
+				into[key] = bv
+			}
+		case []interface{}:
+			bt := bv.([]interface{})
+			if !matchesArray(at, bt) {
+				into[key] = bv
+			}
+		case nil:
+			switch bv.(type) {
+			case nil:
+				// Both nil, fine.
+			default:
+				into[key] = bv
+			}
+		default:
+			panic(fmt.Sprintf("Unknown type:%T in key %s", av, key))
+		}
+	}
+	// Now add all deleted values as nil
+	for key := range a {
+		_, found := b[key]
+		if !found {
+			into[key] = nil
+		}
+	}
+	return into, nil
+}
diff --git a/vendor/gopkg.in/evanphx/json-patch.v4/patch.go b/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
new file mode 100644
index 000000000..f185a45b2
--- /dev/null
+++ b/vendor/gopkg.in/evanphx/json-patch.v4/patch.go
@@ -0,0 +1,784 @@
+package jsonpatch
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"strconv"
+	"strings"
+
+	"github.com/pkg/errors"
+)
+
+const (
+	eRaw = iota
+	eDoc
+	eAry
+)
+
+var (
+	// SupportNegativeIndices decides whether to support non-standard practice of
+	// allowing negative indices to mean indices starting at the end of an array.
+	// Default to true.
+	SupportNegativeIndices bool = true
+	// AccumulatedCopySizeLimit limits the total size increase in bytes caused by
+	// "copy" operations in a patch.
+	AccumulatedCopySizeLimit int64 = 0
+)
+
+var (
+	ErrTestFailed   = errors.New("test failed")
+	ErrMissing      = errors.New("missing value")
+	ErrUnknownType  = errors.New("unknown object type")
+	ErrInvalid      = errors.New("invalid state detected")
+	ErrInvalidIndex = errors.New("invalid index referenced")
+)
+
+type lazyNode struct {
+	raw   *json.RawMessage
+	doc   partialDoc
+	ary   partialArray
+	which int
+}
+
+// Operation is a single JSON-Patch step, such as a single 'add' operation.
+type Operation map[string]*json.RawMessage
+
+// Patch is an ordered collection of Operations.
+type Patch []Operation
+
+type partialDoc map[string]*lazyNode
+type partialArray []*lazyNode
+
+type container interface {
+	get(key string) (*lazyNode, error)
+	set(key string, val *lazyNode) error
+	add(key string, val *lazyNode) error
+	remove(key string) error
+}
+
+func newLazyNode(raw *json.RawMessage) *lazyNode {
+	return &lazyNode{raw: raw, doc: nil, ary: nil, which: eRaw}
+}
+
+func (n *lazyNode) MarshalJSON() ([]byte, error) {
+	switch n.which {
+	case eRaw:
+		return json.Marshal(n.raw)
+	case eDoc:
+		return json.Marshal(n.doc)
+	case eAry:
+		return json.Marshal(n.ary)
+	default:
+		return nil, ErrUnknownType
+	}
+}
+
+func (n *lazyNode) UnmarshalJSON(data []byte) error {
+	dest := make(json.RawMessage, len(data))
+	copy(dest, data)
+	n.raw = &dest
+	n.which = eRaw
+	return nil
+}
+
+func deepCopy(src *lazyNode) (*lazyNode, int, error) {
+	if src == nil {
+		return nil, 0, nil
+	}
+	a, err := src.MarshalJSON()
+	if err != nil {
+		return nil, 0, err
+	}
+	sz := len(a)
+	ra := make(json.RawMessage, sz)
+	copy(ra, a)
+	return newLazyNode(&ra), sz, nil
+}
+
+func (n *lazyNode) intoDoc() (*partialDoc, error) {
+	if n.which == eDoc {
+		return &n.doc, nil
+	}
+
+	if n.raw == nil {
+		return nil, ErrInvalid
+	}
+
+	err := json.Unmarshal(*n.raw, &n.doc)
+
+	if err != nil {
+		return nil, err
+	}
+
+	n.which = eDoc
+	return &n.doc, nil
+}
+
+func (n *lazyNode) intoAry() (*partialArray, error) {
+	if n.which == eAry {
+		return &n.ary, nil
+	}
+
+	if n.raw == nil {
+		return nil, ErrInvalid
+	}
+
+	err := json.Unmarshal(*n.raw, &n.ary)
+
+	if err != nil {
+		return nil, err
+	}
+
+	n.which = eAry
+	return &n.ary, nil
+}
+
+func (n *lazyNode) compact() []byte {
+	buf := &bytes.Buffer{}
+
+	if n.raw == nil {
+		return nil
+	}
+
+	err := json.Compact(buf, *n.raw)
+
+	if err != nil {
+		return *n.raw
+	}
+
+	return buf.Bytes()
+}
+
+func (n *lazyNode) tryDoc() bool {
+	if n.raw == nil {
+		return false
+	}
+
+	err := json.Unmarshal(*n.raw, &n.doc)
+
+	if err != nil {
+		return false
+	}
+
+	n.which = eDoc
+	return true
+}
+
+func (n *lazyNode) tryAry() bool {
+	if n.raw == nil {
+		return false
+	}
+
+	err := json.Unmarshal(*n.raw, &n.ary)
+
+	if err != nil {
+		return false
+	}
+
+	n.which = eAry
+	return true
+}
+
+func (n *lazyNode) equal(o *lazyNode) bool {
+	if n.which == eRaw {
+		if !n.tryDoc() && !n.tryAry() {
+			if o.which != eRaw {
+				return false
+			}
+
+			return bytes.Equal(n.compact(), o.compact())
+		}
+	}
+
+	if n.which == eDoc {
+		if o.which == eRaw {
+			if !o.tryDoc() {
+				return false
+			}
+		}
+
+		if o.which != eDoc {
+			return false
+		}
+
+		if len(n.doc) != len(o.doc) {
+			return false
+		}
+
+		for k, v := range n.doc {
+			ov, ok := o.doc[k]
+
+			if !ok {
+				return false
+			}
+
+			if (v == nil) != (ov == nil) {
+				return false
+			}
+
+			if v == nil && ov == nil {
+				continue
+			}
+
+			if !v.equal(ov) {
+				return false
+			}
+		}
+
+		return true
+	}
+
+	if o.which != eAry && !o.tryAry() {
+		return false
+	}
+
+	if len(n.ary) != len(o.ary) {
+		return false
+	}
+
+	for idx, val := range n.ary {
+		if !val.equal(o.ary[idx]) {
+			return false
+		}
+	}
+
+	return true
+}
+
+// Kind reads the "op" field of the Operation.
+func (o Operation) Kind() string {
+	if obj, ok := o["op"]; ok && obj != nil {
+		var op string
+
+		err := json.Unmarshal(*obj, &op)
+
+		if err != nil {
+			return "unknown"
+		}
+
+		return op
+	}
+
+	return "unknown"
+}
+
+// Path reads the "path" field of the Operation.
+func (o Operation) Path() (string, error) {
+	if obj, ok := o["path"]; ok && obj != nil {
+		var op string
+
+		err := json.Unmarshal(*obj, &op)
+
+		if err != nil {
+			return "unknown", err
+		}
+
+		return op, nil
+	}
+
+	return "unknown", errors.Wrapf(ErrMissing, "operation missing path field")
+}
+
+// From reads the "from" field of the Operation.
+func (o Operation) From() (string, error) {
+	if obj, ok := o["from"]; ok && obj != nil {
+		var op string
+
+		err := json.Unmarshal(*obj, &op)
+
+		if err != nil {
+			return "unknown", err
+		}
+
+		return op, nil
+	}
+
+	return "unknown", errors.Wrapf(ErrMissing, "operation, missing from field")
+}
+
+func (o Operation) value() *lazyNode {
+	if obj, ok := o["value"]; ok {
+		return newLazyNode(obj)
+	}
+
+	return nil
+}
+
+// ValueInterface decodes the operation value into an interface.
+func (o Operation) ValueInterface() (interface{}, error) {
+	if obj, ok := o["value"]; ok && obj != nil {
+		var v interface{}
+
+		err := json.Unmarshal(*obj, &v)
+
+		if err != nil {
+			return nil, err
+		}
+
+		return v, nil
+	}
+
+	return nil, errors.Wrapf(ErrMissing, "operation, missing value field")
+}
+
+func isArray(buf []byte) bool {
+Loop:
+	for _, c := range buf {
+		switch c {
+		case ' ':
+		case '\n':
+		case '\t':
+			continue
+		case '[':
+			return true
+		default:
+			break Loop
+		}
+	}
+
+	return false
+}
+
+func findObject(pd *container, path string) (container, string) {
+	doc := *pd
+
+	split := strings.Split(path, "/")
+
+	if len(split) < 2 {
+		return nil, ""
+	}
+
+	parts := split[1 : len(split)-1]
+
+	key := split[len(split)-1]
+
+	var err error
+
+	for _, part := range parts {
+
+		next, ok := doc.get(decodePatchKey(part))
+
+		if next == nil || ok != nil {
+			return nil, ""
+		}
+
+		if isArray(*next.raw) {
+			doc, err = next.intoAry()
+
+			if err != nil {
+				return nil, ""
+			}
+		} else {
+			doc, err = next.intoDoc()
+
+			if err != nil {
+				return nil, ""
+			}
+		}
+	}
+
+	return doc, decodePatchKey(key)
+}
+
+func (d *partialDoc) set(key string, val *lazyNode) error {
+	(*d)[key] = val
+	return nil
+}
+
+func (d *partialDoc) add(key string, val *lazyNode) error {
+	(*d)[key] = val
+	return nil
+}
+
+func (d *partialDoc) get(key string) (*lazyNode, error) {
+	return (*d)[key], nil
+}
+
+func (d *partialDoc) remove(key string) error {
+	_, ok := (*d)[key]
+	if !ok {
+		return errors.Wrapf(ErrMissing, "Unable to remove nonexistent key: %s", key)
+	}
+
+	delete(*d, key)
+	return nil
+}
+
+// set should only be used to implement the "replace" operation, so "key" must
+// be an already existing index in "d".
+func (d *partialArray) set(key string, val *lazyNode) error {
+	idx, err := strconv.Atoi(key)
+	if err != nil {
+		return err
+	}
+	(*d)[idx] = val
+	return nil
+}
+
+func (d *partialArray) add(key string, val *lazyNode) error {
+	if key == "-" {
+		*d = append(*d, val)
+		return nil
+	}
+
+	idx, err := strconv.Atoi(key)
+	if err != nil {
+		return errors.Wrapf(err, "value was not a proper array index: '%s'", key)
+	}
+
+	sz := len(*d) + 1
+
+	ary := make([]*lazyNode, sz)
+
+	cur := *d
+
+	if idx >= len(ary) {
+		return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+	}
+
+	if idx < 0 {
+		if !SupportNegativeIndices {
+			return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+		}
+		if idx < -len(ary) {
+			return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+		}
+		idx += len(ary)
+	}
+
+	copy(ary[0:idx], cur[0:idx])
+	ary[idx] = val
+	copy(ary[idx+1:], cur[idx:])
+
+	*d = ary
+	return nil
+}
+
+func (d *partialArray) get(key string) (*lazyNode, error) {
+	idx, err := strconv.Atoi(key)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if idx >= len(*d) {
+		return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+	}
+
+	return (*d)[idx], nil
+}
+
+func (d *partialArray) remove(key string) error {
+	idx, err := strconv.Atoi(key)
+	if err != nil {
+		return err
+	}
+
+	cur := *d
+
+	if idx >= len(cur) {
+		return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+	}
+
+	if idx < 0 {
+		if !SupportNegativeIndices {
+			return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+		}
+		if idx < -len(cur) {
+			return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
+		}
+		idx += len(cur)
+	}
+
+	ary := make([]*lazyNode, len(cur)-1)
+
+	copy(ary[0:idx], cur[0:idx])
+	copy(ary[idx:], cur[idx+1:])
+
+	*d = ary
+	return nil
+
+}
+
+func (p Patch) add(doc *container, op Operation) error {
+	path, err := op.Path()
+	if err != nil {
+		return errors.Wrapf(ErrMissing, "add operation failed to decode path")
+	}
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "add operation does not apply: doc is missing path: \"%s\"", path)
+	}
+
+	err = con.add(key, op.value())
+	if err != nil {
+		return errors.Wrapf(err, "error in add for path: '%s'", path)
+	}
+
+	return nil
+}
+
+func (p Patch) remove(doc *container, op Operation) error {
+	path, err := op.Path()
+	if err != nil {
+		return errors.Wrapf(ErrMissing, "remove operation failed to decode path")
+	}
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "remove operation does not apply: doc is missing path: \"%s\"", path)
+	}
+
+	err = con.remove(key)
+	if err != nil {
+		return errors.Wrapf(err, "error in remove for path: '%s'", path)
+	}
+
+	return nil
+}
+
+func (p Patch) replace(doc *container, op Operation) error {
+	path, err := op.Path()
+	if err != nil {
+		return errors.Wrapf(err, "replace operation failed to decode path")
+	}
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing path: %s", path)
+	}
+
+	_, ok := con.get(key)
+	if ok != nil {
+		return errors.Wrapf(ErrMissing, "replace operation does not apply: doc is missing key: %s", path)
+	}
+
+	err = con.set(key, op.value())
+	if err != nil {
+		return errors.Wrapf(err, "error in remove for path: '%s'", path)
+	}
+
+	return nil
+}
+
+func (p Patch) move(doc *container, op Operation) error {
+	from, err := op.From()
+	if err != nil {
+		return errors.Wrapf(err, "move operation failed to decode from")
+	}
+
+	con, key := findObject(doc, from)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing from path: %s", from)
+	}
+
+	val, err := con.get(key)
+	if err != nil {
+		return errors.Wrapf(err, "error in move for path: '%s'", key)
+	}
+
+	err = con.remove(key)
+	if err != nil {
+		return errors.Wrapf(err, "error in move for path: '%s'", key)
+	}
+
+	path, err := op.Path()
+	if err != nil {
+		return errors.Wrapf(err, "move operation failed to decode path")
+	}
+
+	con, key = findObject(doc, path)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "move operation does not apply: doc is missing destination path: %s", path)
+	}
+
+	err = con.add(key, val)
+	if err != nil {
+		return errors.Wrapf(err, "error in move for path: '%s'", path)
+	}
+
+	return nil
+}
+
+func (p Patch) test(doc *container, op Operation) error {
+	path, err := op.Path()
+	if err != nil {
+		return errors.Wrapf(err, "test operation failed to decode path")
+	}
+
+	con, key := findObject(doc, path)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "test operation does not apply: is missing path: %s", path)
+	}
+
+	val, err := con.get(key)
+	if err != nil {
+		return errors.Wrapf(err, "error in test for path: '%s'", path)
+	}
+
+	if val == nil {
+		if op.value().raw == nil {
+			return nil
+		}
+		return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+	} else if op.value() == nil {
+		return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+	}
+
+	if val.equal(op.value()) {
+		return nil
+	}
+
+	return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
+}
+
+func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64) error {
+	from, err := op.From()
+	if err != nil {
+		return errors.Wrapf(err, "copy operation failed to decode from")
+	}
+
+	con, key := findObject(doc, from)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing from path: %s", from)
+	}
+
+	val, err := con.get(key)
+	if err != nil {
+		return errors.Wrapf(err, "error in copy for from: '%s'", from)
+	}
+
+	path, err := op.Path()
+	if err != nil {
+		return errors.Wrapf(ErrMissing, "copy operation failed to decode path")
+	}
+
+	con, key = findObject(doc, path)
+
+	if con == nil {
+		return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing destination path: %s", path)
+	}
+
+	valCopy, sz, err := deepCopy(val)
+	if err != nil {
+		return errors.Wrapf(err, "error while performing deep copy")
+	}
+
+	(*accumulatedCopySize) += int64(sz)
+	if AccumulatedCopySizeLimit > 0 && *accumulatedCopySize > AccumulatedCopySizeLimit {
+		return NewAccumulatedCopySizeError(AccumulatedCopySizeLimit, *accumulatedCopySize)
+	}
+
+	err = con.add(key, valCopy)
+	if err != nil {
+		return errors.Wrapf(err, "error while adding value during copy")
+	}
+
+	return nil
+}
+
+// Equal indicates if 2 JSON documents have the same structural equality.
+func Equal(a, b []byte) bool {
+	ra := make(json.RawMessage, len(a))
+	copy(ra, a)
+	la := newLazyNode(&ra)
+
+	rb := make(json.RawMessage, len(b))
+	copy(rb, b)
+	lb := newLazyNode(&rb)
+
+	return la.equal(lb)
+}
+
+// DecodePatch decodes the passed JSON document as an RFC 6902 patch.
+func DecodePatch(buf []byte) (Patch, error) {
+	var p Patch
+
+	err := json.Unmarshal(buf, &p)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return p, nil
+}
+
+// Apply mutates a JSON document according to the patch, and returns the new
+// document.
+func (p Patch) Apply(doc []byte) ([]byte, error) {
+	return p.ApplyIndent(doc, "")
+}
+
+// ApplyIndent mutates a JSON document according to the patch, and returns the new
+// document indented.
+func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
+	var pd container
+	if doc[0] == '[' {
+		pd = &partialArray{}
+	} else {
+		pd = &partialDoc{}
+	}
+
+	err := json.Unmarshal(doc, pd)
+
+	if err != nil {
+		return nil, err
+	}
+
+	err = nil
+
+	var accumulatedCopySize int64
+
+	for _, op := range p {
+		switch op.Kind() {
+		case "add":
+			err = p.add(&pd, op)
+		case "remove":
+			err = p.remove(&pd, op)
+		case "replace":
+			err = p.replace(&pd, op)
+		case "move":
+			err = p.move(&pd, op)
+		case "test":
+			err = p.test(&pd, op)
+		case "copy":
+			err = p.copy(&pd, op, &accumulatedCopySize)
+		default:
+			err = fmt.Errorf("Unexpected kind: %s", op.Kind())
+		}
+
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if indent != "" {
+		return json.MarshalIndent(pd, "", indent)
+	}
+
+	return json.Marshal(pd)
+}
+
+// From http://tools.ietf.org/html/rfc6901#section-4 :
+//
+// Evaluation of each reference token begins by decoding any escaped
+// character sequence.  This is performed by first transforming any
+// occurrence of the sequence '~1' to '/', and then transforming any
+// occurrence of the sequence '~0' to '~'.
+
+var (
+	rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
+)
+
+func decodePatchKey(k string) string {
+	return rfc6901Decoder.Replace(k)
+}
diff --git a/vendor/knative.dev/hack/CODE_OF_CONDUCT.md b/vendor/knative.dev/hack/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..4649e6aed
--- /dev/null
+++ b/vendor/knative.dev/hack/CODE_OF_CONDUCT.md
@@ -0,0 +1,4 @@
+# Contributor Covenant Code of Conduct
+
+Please see the Knative Community
+[Contributor Covenant Code of Conduct](https://www.knative.dev/contributing/code-of-conduct/).
diff --git a/vendor/knative.dev/test-infra/scripts/e2e-tests.sh b/vendor/knative.dev/hack/e2e-tests.sh
similarity index 100%
rename from vendor/knative.dev/test-infra/scripts/e2e-tests.sh
rename to vendor/knative.dev/hack/e2e-tests.sh
diff --git a/vendor/knative.dev/hack/go.mod b/vendor/knative.dev/hack/go.mod
new file mode 100644
index 000000000..5bef87726
--- /dev/null
+++ b/vendor/knative.dev/hack/go.mod
@@ -0,0 +1,3 @@
+module knative.dev/hack
+
+go 1.14
diff --git a/vendor/modules.txt b/vendor/modules.txt
index be57e3817..2a9393ffd 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -75,9 +75,9 @@ github.com/aws/aws-sdk-go/service/sts
 github.com/aws/aws-sdk-go/service/sts/stsiface
 # github.com/beorn7/perks v1.0.1
 github.com/beorn7/perks/quantile
-# github.com/blang/semver v3.5.1+incompatible
+# github.com/blang/semver/v4 v4.0.0
 ## explicit
-github.com/blang/semver
+github.com/blang/semver/v4
 # github.com/census-instrumentation/opencensus-proto v0.3.0
 ## explicit
 github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1
@@ -95,7 +95,6 @@ github.com/davecgh/go-spew/spew
 github.com/emicklei/go-restful
 github.com/emicklei/go-restful/log
 # github.com/evanphx/json-patch v4.5.0+incompatible
-## explicit
 github.com/evanphx/json-patch
 # github.com/ghodss/yaml v1.0.0
 ## explicit
@@ -310,6 +309,7 @@ go.uber.org/zap/internal/ztest
 go.uber.org/zap/zapcore
 go.uber.org/zap/zaptest
 # golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
+## explicit
 golang.org/x/crypto/cast5
 golang.org/x/crypto/openpgp
 golang.org/x/crypto/openpgp/armor
@@ -360,6 +360,7 @@ golang.org/x/text/unicode/bidi
 golang.org/x/text/unicode/norm
 golang.org/x/text/width
 # golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
+## explicit
 golang.org/x/time/rate
 # golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3
 ## explicit
@@ -532,6 +533,9 @@ google.golang.org/protobuf/types/known/wrapperspb
 google.golang.org/protobuf/types/pluginpb
 # gopkg.in/alecthomas/kingpin.v2 v2.2.6
 gopkg.in/alecthomas/kingpin.v2
+# gopkg.in/evanphx/json-patch.v4 v4.9.0
+## explicit
+gopkg.in/evanphx/json-patch.v4
 # gopkg.in/inf.v0 v0.9.1
 gopkg.in/inf.v0
 # gopkg.in/yaml.v2 v2.3.0
@@ -928,6 +932,7 @@ k8s.io/kube-openapi/pkg/generators/rules
 k8s.io/kube-openapi/pkg/util/proto
 k8s.io/kube-openapi/pkg/util/sets
 # k8s.io/test-infra v0.0.0-20200803112140-d8aa4e063646
+## explicit
 k8s.io/test-infra/prow/config/secret
 k8s.io/test-infra/prow/logrusutil
 k8s.io/test-infra/prow/version
@@ -936,9 +941,9 @@ k8s.io/utils/buffer
 k8s.io/utils/integer
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/test-infra v0.0.0-20201026182042-46291de4ab66
+# knative.dev/hack v0.0.0-20201027201633-1763a666eb41
 ## explicit
-knative.dev/test-infra/scripts
+knative.dev/hack
 # sigs.k8s.io/boskos v0.0.0-20200729174948-794df80db9c9
 ## explicit
 sigs.k8s.io/boskos/client
diff --git a/version/version.go b/version/version.go
index cadf90cda..f78014630 100644
--- a/version/version.go
+++ b/version/version.go
@@ -21,7 +21,7 @@ import (
 	"os"
 	"strings"
 
-	"github.com/blang/semver"
+	"github.com/blang/semver/v4"
 	"k8s.io/client-go/discovery"
 )
 


Test patch:
diff --git a/apis/depcheck_test.go b/apis/depcheck_test.go
new file mode 100644
index 000000000..d2430f89c
--- /dev/null
+++ b/apis/depcheck_test.go
@@ -0,0 +1,34 @@
+/*
+Copyright 2020 The Knative Authors
+
+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 apis_test
+
+import (
+	"testing"
+
+	"knative.dev/pkg/depcheck"
+)
+
+func TestNoDeps(t *testing.T) {
+	depcheck.AssertNoDependency(t, map[string][]string{
+		"knative.dev/pkg/apis":                depcheck.KnownHeavyDependencies,
+		"knative.dev/pkg/apis/duck":           depcheck.KnownHeavyDependencies,
+		"knative.dev/pkg/apis/duck/ducktypes": depcheck.KnownHeavyDependencies,
+		"knative.dev/pkg/apis/duck/v1alpha1":  depcheck.KnownHeavyDependencies,
+		"knative.dev/pkg/apis/duck/v1beta1":   depcheck.KnownHeavyDependencies,
+		"knative.dev/pkg/apis/duck/v1":        depcheck.KnownHeavyDependencies,
+	})
+}
diff --git a/depcheck/depcheck_test.go b/depcheck/depcheck_test.go
index 7f11bf67c..e54ca2c4d 100644
--- a/depcheck/depcheck_test.go
+++ b/depcheck/depcheck_test.go
@@ -20,6 +20,7 @@ limitations under the License.
 package depcheck_test
 
 import (
+	"strings"
 	"testing"
 
 	"knative.dev/pkg/depcheck"
@@ -28,6 +29,9 @@ import (
 // TestExample doesn't follow the Go Example style because it isn't well
 // suited for libraries needing *testing.T
 func TestExample(t *testing.T) {
+
+	// For larger packages, it can make the most sense to simply avoid
+	// known "heavy" packages, which pull in large amount of code or data.
 	depcheck.AssertNoDependency(t, map[string][]string{
 		// Our duck types shouldn't depend on fuzzers.
 		"knative.dev/pkg/apis/duck/v1": {
@@ -41,10 +45,41 @@ func TestExample(t *testing.T) {
 		"knative.dev/pkg/depcheck": {
 			"k8s.io/apimachinery/pkg/util/sets",
 		},
+	})
+
+	// Sample failure case, duck clearly relies on corev1 for all assortment of things.
+	if err := depcheck.CheckNoDependency("knative.dev/pkg/apis/duck", []string{"k8s.io/api/core/v1"}); err == nil {
+		t.Error("CheckNoDependency() = nil, wanted error")
+	} else if !strings.Contains(err.Error(), "knative.dev/pkg/tracker") {
+		t.Errorf("CheckNoDependency() = %v, expected to contain: %v", err, "knative.dev/pkg/tracker")
+	} else {
+		t.Log("CheckNoDependency() =", err)
+	}
 
-		// BAD Example used to illustrate path error message.
-		// "knative.dev/pkg/apis/duck": {
-		// 	"k8s.io/api/core/v1",
-		// },
+	// For small packages, it can make the most sense to curate
+	// the external dependencies very carefully.
+	depcheck.AssertOnlyDependencies(t, map[string][]string{
+		// Example libraries with very limited dependencies.
+		"knative.dev/pkg/pool": {
+			"context",
+			"sync",
+			"golang.org/x/sync/errgroup",
+		},
+		"knative.dev/pkg/ptr": {
+			"time",
+		},
 	})
+
+	// Sample failure case, doesn't include transitive dependencies!
+	if err := depcheck.CheckOnlyDependencies("knative.dev/pkg/depcheck", map[string]struct{}{
+		"fmt":                            {},
+		"sort":                           {},
+		"strings":                        {},
+		"testing":                        {},
+		"golang.org/x/tools/go/packages": {},
+	}); err == nil {
+		t.Error("CheckOnlyDependencies() = nil, wanted error")
+	} else if !strings.Contains(err.Error(), "golang.org/x/tools/go/gcexportdata") {
+		t.Errorf("CheckOnlyDependencies() = %v, expected to contain: %v", err, "golang.org/x/tools/go/gcexportdata")
+	}
 }
diff --git a/leaderelection/context_test.go b/leaderelection/context_test.go
index bf6dbb487..271bab215 100644
--- a/leaderelection/context_test.go
+++ b/leaderelection/context_test.go
@@ -1,6 +1,3 @@
-// +build !race
-// TODO(https://github.com/kubernetes/kubernetes/issues/90952): Remove the above.
-
 /*
 Copyright 2020 The Knative Authors
 
diff --git a/logging/depcheck_test.go b/logging/depcheck_test.go
new file mode 100644
index 000000000..e0d3a8dd4
--- /dev/null
+++ b/logging/depcheck_test.go
@@ -0,0 +1,29 @@
+/*
+Copyright 2020 The Knative Authors
+
+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 logging_test
+
+import (
+	"testing"
+
+	"knative.dev/pkg/depcheck"
+)
+
+func TestNoDeps(t *testing.T) {
+	depcheck.AssertNoDependency(t, map[string][]string{
+		"knative.dev/pkg/logging": depcheck.KnownHeavyDependencies,
+	})
+}
diff --git a/network/depcheck_test.go b/network/depcheck_test.go
new file mode 100644
index 000000000..285de24b3
--- /dev/null
+++ b/network/depcheck_test.go
@@ -0,0 +1,31 @@
+/*
+Copyright 2020 The Knative Authors
+
+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 network_test
+
+import (
+	"testing"
+
+	"knative.dev/pkg/depcheck"
+)
+
+func TestNoDeps(t *testing.T) {
+	depcheck.AssertNoDependency(t, map[string][]string{
+		"knative.dev/pkg/network":          depcheck.KnownHeavyDependencies,
+		"knative.dev/pkg/network/handlers": depcheck.KnownHeavyDependencies,
+		"knative.dev/pkg/network/prober":   depcheck.KnownHeavyDependencies,
+	})
+}
diff --git a/test/presubmit-tests.sh b/test/presubmit-tests.sh
index af8199dd0..dcae993bc 100755
--- a/test/presubmit-tests.sh
+++ b/test/presubmit-tests.sh
@@ -24,7 +24,7 @@ export DISABLE_MD_LINTING=1
 
 export GO111MODULE=on
 
-source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/presubmit-tests.sh
+source $(dirname $0)/../vendor/knative.dev/hack/presubmit-tests.sh
 
 # TODO(#17): Write integration tests.
 
diff --git a/test/test-reconciler-codegen.sh b/test/test-reconciler-codegen.sh
index cf7f5dfdb..c6bb3e20c 100755
--- a/test/test-reconciler-codegen.sh
+++ b/test/test-reconciler-codegen.sh
@@ -18,7 +18,7 @@ set -o errexit
 set -o nounset
 set -o pipefail
 
-source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/library.sh
+source $(dirname $0)/../vendor/knative.dev/hack/library.sh
 
 CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
 KNATIVE_CODEGEN_PKG=${KNATIVE_CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/knative.dev/pkg 2>/dev/null || echo ../pkg)}
diff --git a/vendor/knative.dev/test-infra/LICENSE b/vendor/knative.dev/hack/LICENSE
similarity index 99%
rename from vendor/knative.dev/test-infra/LICENSE
rename to vendor/knative.dev/hack/LICENSE
index d64569567..261eeb9e9 100644
--- a/vendor/knative.dev/test-infra/LICENSE
+++ b/vendor/knative.dev/hack/LICENSE
@@ -1,4 +1,3 @@
-
                                  Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
diff --git a/vendor/knative.dev/test-infra/scripts/README.md b/vendor/knative.dev/hack/README.md
similarity index 91%
rename from vendor/knative.dev/test-infra/scripts/README.md
rename to vendor/knative.dev/hack/README.md
index 1f3aa6f70..af2cbc657 100644
--- a/vendor/knative.dev/test-infra/scripts/README.md
+++ b/vendor/knative.dev/hack/README.md
@@ -1,7 +1,7 @@
-# Helper scripts
+# knative.dev/hack
 
-This directory contains helper scripts used by Prow test jobs, as well as local
-development scripts.
+`hack` is a collection of scripts used to bootstrap CI processes and other vital
+entrypoint functionallity.
 
 ## Using the `presubmit-tests.sh` helper script
 
@@ -19,13 +19,13 @@ This is a helper script to run the presubmit tests. To use it:
 
    The markdown link checker tool doesn't check `localhost` links by default.
    Its configuration file, `markdown-link-check-config.json`, lives in the
-   `test-infra/scripts` directory. To override it, create a file with the same
-   name, containing the custom config in the `/test` directory.
+   `hack` directory. To override it, create a file with the same name,
+   containing the custom config in the `/test` directory.
 
    The markdown lint tool ignores long lines by default. Its configuration file,
-   `markdown-lint-config.rc`, lives in the `test-infra/scripts` directory. To
-   override it, create a file with the same name, containing the custom config
-   in the `/test` directory.
+   `markdown-lint-config.rc`, lives in the `hack` repo. To override it, create a
+   file with the same name, containing the custom config in the `/test`
+   directory.
 
 1. [optional] Customize the default build test runner, if you're using it. Set
    the following environment variables if the default values don't fit your
@@ -85,7 +85,7 @@ skipped.
 ### Sample presubmit test script
 
 ```bash
-source vendor/knative.dev/test-infra/scripts/presubmit-tests.sh
+source vendor/knative.dev/hack/presubmit-tests.sh
 
 function post_build_tests() {
   echo "Cleaning up after build tests"
@@ -176,7 +176,7 @@ test cluster is created in a specific region, `us-west2`.
 
 ```bash
 
-source vendor/knative.dev/test-infra/scripts/e2e-tests.sh
+source vendor/knative.dev/hack/e2e-tests.sh
 
 function knative_setup() {
   start_latest_knative_serving
@@ -247,7 +247,7 @@ benchmarking jobs for each repo. To use it:
 This script will update `Knative serving` and the given benchmark.
 
 ```bash
-source vendor/knative.dev/test-infra/scripts/performance-tests.sh
+source vendor/knative.dev/hack/performance-tests.sh
 
 function update_knative() {
   echo ">> Updating serving"
@@ -322,7 +322,7 @@ This is a helper script for Knative release scripts. To use it:
 ### Sample release script
 
 ```bash
-source vendor/knative.dev/test-infra/scripts/release.sh
+source vendor/knative.dev/hack/release.sh
 
 function build_release() {
   # config/ contains the manifests
@@ -332,3 +332,14 @@ function build_release() {
 
 main "$@"
 ```
+
+# Origins of `hack`
+
+When Kubernetes was first getting started, someone was trying to introduce some
+quick shell scripts and land them into the `./scripts` folder. But there was one
+that opposed this: Ville Aikas. The compromise was to put those quick scripts in
+a folder called `hack` to remind users and developers that there is likely a
+better way to perform the task you are attempting that is not using a shell
+script, like a tested python script.
+
+> "I was like fine, put them in hack not scripts, cause they are hacks." - Ville Aikas
diff --git a/vendor/knative.dev/test-infra/scripts/dummy.go b/vendor/knative.dev/hack/hack.go
similarity index 74%
rename from vendor/knative.dev/test-infra/scripts/dummy.go
rename to vendor/knative.dev/hack/hack.go
index 82c9edfa9..689d1471a 100644
--- a/vendor/knative.dev/test-infra/scripts/dummy.go
+++ b/vendor/knative.dev/hack/hack.go
@@ -1,5 +1,7 @@
+// +build hack
+
 /*
-Copyright 2018 The Knative Authors
+Copyright 2020 The Knative Authors
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,6 +16,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// Package scripts is a placeholder that allows us to pull the shell scripts
-// via go mod vendor.
-package scripts
+// package hack is a collection of scripts used to bootstrap CI processes and
+// other vital entrypoint functionallity.
+
+package hack
diff --git a/vendor/knative.dev/test-infra/scripts/infra-library.sh b/vendor/knative.dev/hack/infra-library.sh
similarity index 100%
rename from vendor/knative.dev/test-infra/scripts/infra-library.sh
rename to vendor/knative.dev/hack/infra-library.sh
diff --git a/vendor/knative.dev/test-infra/scripts/library.sh b/vendor/knative.dev/hack/library.sh
similarity index 97%
rename from vendor/knative.dev/test-infra/scripts/library.sh
rename to vendor/knative.dev/hack/library.sh
index 0dbe50021..10220e298 100644
--- a/vendor/knative.dev/test-infra/scripts/library.sh
+++ b/vendor/knative.dev/hack/library.sh
@@ -557,11 +557,7 @@ function go_update_deps() {
   echo "--- Removing unwanted vendor files"
 
   # Remove unwanted vendor files
-  find vendor/ \( -name "OWNERS" \
-    -o -name "OWNERS_ALIASES" \
-    -o -name "BUILD" \
-    -o -name "BUILD.bazel" \
-    -o -name "*_test.go" \) -exec rm -f {} +
+  find vendor/ \( -name "OWNERS" -o -name "OWNERS_ALIASES" -o -name "BUILD" -o -name "BUILD.bazel" -o -name "*_test.go" \) -print0 | xargs -0 rm -f
 
   export GOFLAGS=-mod=vendor
 
@@ -575,16 +571,10 @@ function go_update_deps() {
 # Run kntest tool, error out and ask users to install it if it's not currently installed.
 # Parameters: $1..$n - parameters passed to the tool.
 function run_kntest() {
-  # If the current repo is test-infra, run kntest from source.
-  if [[ "${REPO_NAME}" == "test-infra" ]]; then
-    go run "${REPO_ROOT_DIR}"/kntest/cmd/kntest "$@"
-  # Otherwise kntest must be installed.
-  else
-    if [[ ! -x "$(command -v kntest)" ]]; then
-      echo "--- FAIL: kntest not installed, please clone test-infra repo and run \`go install ./kntest/cmd/kntest\` to install it"; return 1;
-    fi
-    kntest "$@"
+  if [[ ! -x "$(command -v kntest)" ]]; then
+    echo "--- FAIL: kntest not installed, please clone knative test-infra repo and run \`go install ./kntest/cmd/kntest\` to install it"; return 1;
   fi
+  kntest "$@"
 }
 
 # Run go-licenses to update licenses.
diff --git a/vendor/knative.dev/test-infra/scripts/performance-tests.sh b/vendor/knative.dev/hack/performance-tests.sh
similarity index 100%
rename from vendor/knative.dev/test-infra/scripts/performance-tests.sh
rename to vendor/knative.dev/hack/performance-tests.sh
diff --git a/vendor/knative.dev/test-infra/scripts/presubmit-tests.sh b/vendor/knative.dev/hack/presubmit-tests.sh
similarity index 100%
rename from vendor/knative.dev/test-infra/scripts/presubmit-tests.sh
rename to vendor/knative.dev/hack/presubmit-tests.sh
diff --git a/vendor/knative.dev/test-infra/scripts/release.sh b/vendor/knative.dev/hack/release.sh
similarity index 100%
rename from vendor/knative.dev/test-infra/scripts/release.sh
rename to vendor/knative.dev/hack/release.sh
diff --git a/vendor/knative.dev/test-infra/scripts/shellcheck-presubmit.sh b/vendor/knative.dev/hack/shellcheck-presubmit.sh
similarity index 100%
rename from vendor/knative.dev/test-infra/scripts/shellcheck-presubmit.sh
rename to vendor/knative.dev/hack/shellcheck-presubmit.sh
diff --git a/vendor/knative.dev/test-infra/scripts/update-test-infra.sh b/vendor/knative.dev/test-infra/scripts/update-test-infra.sh
deleted file mode 100644
index d443f3c20..000000000
--- a/vendor/knative.dev/test-infra/scripts/update-test-infra.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2020 The Knative Authors
-#
-# 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.
-
-set -e
-
-# This script updates test-infra scripts in-repo.
-# Run it to update (usually from hack/update-deps.sh) the current scripts.
-# Scripts are installed to REPO_ROOT/scripts/test-infra
-
-# The following arguments are accepted:
-# --update
-#  Do the update
-# --ref X
-#  Defines which ref (branch, tag, commit) of test-infra to get scripts from; defaults to master
-# --first-time
-#  Run this script from your repo root directory to install scripts for the first time
-#  Will also sed -i non-vendor scripts in the current repo to point to new path
-# TODO: --verify
-#  Verify the contents of scripts/test-infra match the contents from commit sha in scripts/test-infra/COMMIT
-#  One can verify manually by running the script with '--ref $(cat scripts/test-infra/COMMIT)' and ensuring no files are staged
-
-declare -i FIRST_TIME_SETUP=0
-declare -i DO_UPDATE=0
-declare SCRIPTS_REF=master
-
-while [[ $# -ne 0 ]]; do
-  parameter="$1"
-  case ${parameter} in
-    --ref)
-      shift
-      SCRIPTS_REF="$1"
-      ;;
-    --first-time)
-      FIRST_TIME_SETUP=1
-      ;;
-    --update)
-      DO_UPDATE=1
-      ;;
-    *)
-      echo "unknown option ${parameter}"
-      exit 1
-      ;;
-  esac
-  shift
-done
-
-function do_read_tree() {
-    mkdir -p scripts/test-infra
-    git read-tree --prefix=scripts/test-infra -u "test-infra/${SCRIPTS_REF}:scripts"
-    git show-ref -s -- "refs/remotes/test-infra/${SCRIPTS_REF}" > scripts/test-infra/COMMIT
-    git add scripts/test-infra/COMMIT
-    echo "test-infra scripts installed to scripts/test-infra from branch ${SCRIPTS_REF}"
-}
-
-function run() {
-  if (( FIRST_TIME_SETUP )); then
-    if [[ ! -d .git ]]; then
-      echo "I don't believe you are in a repo root; exiting"
-      exit 5
-    fi
-    git remote add test-infra https://github.com/knative/test-infra.git || echo "test-infra remote already set; not changing"
-    git fetch test-infra "${SCRIPTS_REF}"
-    do_read_tree
-    echo "Attempting to point all scripts to use this new path"
-    grep -RiIl vendor/knative.dev/test-infra | grep -v ^vendor | grep -v ^scripts/test-infra | xargs sed -i 's+vendor/knative.dev/test-infra/scripts+scripts/test-infra+'
-  elif (( DO_UPDATE )); then
-    pushd "$(dirname "${BASH_SOURCE[0]}")/../.."
-    trap popd EXIT
-
-    git remote add test-infra https://github.com/knative/test-infra.git || true
-    git fetch test-infra "${SCRIPTS_REF}"
-    git rm -fr scripts/test-infra
-    rm -fR scripts/test-infra
-    do_read_tree
-  fi
-}
-
-run