Repository: knative/pkg
Pull request #2050 (2021-03-08 19:15:38)

Drop master references to knative repos
<!-- Please include the 'why' behind your changes if no issue exists -->
## Proposed Changes

As a followup to the recent renaming spree, all of these can now change :partying_face: 

**Release Note**

<!-- Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". -->

```release-note
NONE
```

/assign @mattmoor 


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

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **markusthoemmes** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @markusthoemmes` 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/main/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":["markusthoemmes"]} -->
knative-prow-robot: @markusthoemmes: The following test **failed**, say `/retest` to rerun all failed tests:

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

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

<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/.github/workflows/knative-releasability.yaml b/.github/workflows/knative-releasability.yaml
index f9b1799f2..cf885877c 100644
--- a/.github/workflows/knative-releasability.yaml
+++ b/.github/workflows/knative-releasability.yaml
@@ -60,7 +60,7 @@ jobs:
           go-version: 1.15.x
 
       - name: Install Dependencies
-        run: GO111MODULE=on go get knative.dev/test-infra/buoy@master
+        run: GO111MODULE=on go get knative.dev/test-infra/buoy@main
 
       - name: Check out code
         uses: actions/checkout@v2
diff --git a/.github/workflows/knative-release-notes.yaml b/.github/workflows/knative-release-notes.yaml
index b9c30dd99..517f429bc 100644
--- a/.github/workflows/knative-release-notes.yaml
+++ b/.github/workflows/knative-release-notes.yaml
@@ -21,9 +21,9 @@ on:
   workflow_dispatch:
     inputs:
       branch:
-        description: 'Branch? (master)'
+        description: 'Branch? (main)'
         required: true
-        default: 'master'
+        default: 'main'
       start-sha:
         description: 'Starting SHA? (last tag on branch)'
       end-sha:
diff --git a/.github/workflows/knative-style.yaml b/.github/workflows/knative-style.yaml
index be7ce9a87..877f48501 100644
--- a/.github/workflows/knative-style.yaml
+++ b/.github/workflows/knative-style.yaml
@@ -127,7 +127,7 @@ jobs:
         if: steps.golangci_configuration.outputs.files_exists == 'true'
         uses: golangci/golangci-lint-action@v2
         with:
-          version: v1.35
+          version: v1.38
 
       - name: misspell
         shell: bash
diff --git a/README.md b/README.md
index 6f6211cbb..4c8b8696a 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Alan Cleaver is licensed under CC BY 2.0
 
 [![GoDoc](https://godoc.org/github.com/knative/pkg?status.svg)](https://godoc.org/github.com/knative/pkg)
 [![Go Report Card](https://goreportcard.com/badge/knative/pkg)](https://goreportcard.com/report/knative/pkg)
-[![codecov](https://codecov.io/gh/knative/pkg/branch/master/graph/badge.svg)](https://codecov.io/gh/knative/pkg)
+[![codecov](https://codecov.io/gh/knative/pkg/branch/main/graph/badge.svg)](https://codecov.io/gh/knative/pkg)
 
 Knative `pkg` provides a place for sharing common Knative packages across the
 Knative repos.
diff --git a/apis/duck/ABOUT.md b/apis/duck/ABOUT.md
index 98ffc9424..b223412a0 100644
--- a/apis/duck/ABOUT.md
+++ b/apis/duck/ABOUT.md
@@ -73,7 +73,7 @@ the resulting JSON Patch can only contain fields relevant to the resource.
 
 In Knative, we follow the Kubernetes API principles of using `conditions` as a
 key part of our resources’ status, but we go a step further in
-[defining particular conventions](https://github.com/knative/serving/blob/master/docs/spec/errors.md#error-conditions-and-reporting)
+[defining particular conventions](https://github.com/knative/serving/blob/main/docs/spec/errors.md#error-conditions-and-reporting)
 on how these are used.
 
 To support this, we define:
diff --git a/client/injection/apiextensions/client/client.go b/client/injection/apiextensions/client/client.go
index 3edca7e9e..e8695e03f 100644
--- a/client/injection/apiextensions/client/client.go
+++ b/client/injection/apiextensions/client/client.go
@@ -29,6 +29,9 @@ import (
 
 func init() {
 	injection.Default.RegisterClient(withClient)
+	injection.Default.RegisterClientFetcher(func(ctx context.Context) interface{} {
+		return Get(ctx)
+	})
 }
 
 // Key is used as the key for associating information with a context.Context.
diff --git a/client/injection/apiextensions/client/fake/fake.go b/client/injection/apiextensions/client/fake/fake.go
index 1ed129871..6b47e9de3 100644
--- a/client/injection/apiextensions/client/fake/fake.go
+++ b/client/injection/apiextensions/client/fake/fake.go
@@ -31,6 +31,9 @@ import (
 
 func init() {
 	injection.Fake.RegisterClient(withClient)
+	injection.Fake.RegisterClientFetcher(func(ctx context.Context) interface{} {
+		return Get(ctx)
+	})
 }
 
 func withClient(ctx context.Context, cfg *rest.Config) context.Context {
diff --git a/client/injection/kube/client/client.go b/client/injection/kube/client/client.go
index 00591ff57..b7994cb72 100644
--- a/client/injection/kube/client/client.go
+++ b/client/injection/kube/client/client.go
@@ -29,6 +29,9 @@ import (
 
 func init() {
 	injection.Default.RegisterClient(withClient)
+	injection.Default.RegisterClientFetcher(func(ctx context.Context) interface{} {
+		return Get(ctx)
+	})
 }
 
 // Key is used as the key for associating information with a context.Context.
diff --git a/client/injection/kube/client/fake/fake.go b/client/injection/kube/client/fake/fake.go
index 022ae42f0..e16622294 100644
--- a/client/injection/kube/client/fake/fake.go
+++ b/client/injection/kube/client/fake/fake.go
@@ -31,6 +31,9 @@ import (
 
 func init() {
 	injection.Fake.RegisterClient(withClient)
+	injection.Fake.RegisterClientFetcher(func(ctx context.Context) interface{} {
+		return Get(ctx)
+	})
 }
 
 func withClient(ctx context.Context, cfg *rest.Config) context.Context {
diff --git a/codegen/cmd/injection-gen/generators/client.go b/codegen/cmd/injection-gen/generators/client.go
index 317e12a44..d7cb717ed 100644
--- a/codegen/cmd/injection-gen/generators/client.go
+++ b/codegen/cmd/injection-gen/generators/client.go
@@ -66,7 +66,11 @@ func (g *clientGenerator) GenerateType(c *generator.Context, t *types.Type, w io
 		"clientSetNewForConfigOrDie": c.Universe.Function(types.Name{Package: g.clientSetPackage, Name: "NewForConfigOrDie"}),
 		"clientSetInterface":         c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"}),
 		"injectionRegisterClient":    c.Universe.Function(types.Name{Package: "knative.dev/pkg/injection", Name: "Default.RegisterClient"}),
-		"restConfig":                 c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}),
+		"injectionRegisterClientFetcher": c.Universe.Function(types.Name{
+			Package: "knative.dev/pkg/injection",
+			Name:    "Default.RegisterClientFetcher",
+		}),
+		"restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}),
 		"loggingFromContext": c.Universe.Function(types.Name{
 			Package: "knative.dev/pkg/logging",
 			Name:    "FromContext",
@@ -85,6 +89,9 @@ func (g *clientGenerator) GenerateType(c *generator.Context, t *types.Type, w io
 var injectionClient = `
 func init() {
 	{{.injectionRegisterClient|raw}}(withClient)
+	{{.injectionRegisterClientFetcher|raw}}(func(ctx context.Context) interface{} {
+		return Get(ctx)
+	})
 }
 
 // Key is used as the key for associating information with a context.Context.
diff --git a/codegen/cmd/injection-gen/generators/fake_client.go b/codegen/cmd/injection-gen/generators/fake_client.go
index 3e98ce381..76725f2bd 100644
--- a/codegen/cmd/injection-gen/generators/fake_client.go
+++ b/codegen/cmd/injection-gen/generators/fake_client.go
@@ -71,6 +71,10 @@ func (g *fakeClientGenerator) GenerateType(c *generator.Context, t *types.Type,
 			Package: "knative.dev/pkg/injection",
 			Name:    "Fake.RegisterClient",
 		}),
+		"injectionRegisterClientFetcher": c.Universe.Function(types.Name{
+			Package: "knative.dev/pkg/injection",
+			Name:    "Fake.RegisterClientFetcher",
+		}),
 		"loggingFromContext": c.Universe.Function(types.Name{
 			Package: "knative.dev/pkg/logging",
 			Name:    "FromContext",
@@ -91,6 +95,9 @@ func (g *fakeClientGenerator) GenerateType(c *generator.Context, t *types.Type,
 var injectionFakeClient = `
 func init() {
 	{{.injectionRegisterClient|raw}}(withClient)
+	{{.injectionRegisterClientFetcher|raw}}(func(ctx context.Context) interface{} {
+		return Get(ctx)
+	})
 }
 
 func withClient(ctx {{.contextContext|raw}}, cfg *{{.restConfig|raw}}) {{.contextContext|raw}} {
diff --git a/go.mod b/go.mod
index 1409ed333..0113839c3 100644
--- a/go.mod
+++ b/go.mod
@@ -67,6 +67,6 @@ require (
 	k8s.io/code-generator v0.19.7
 	k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14
 	k8s.io/klog v1.0.0
-	knative.dev/hack v0.0.0-20210305150220-f99a25560134
+	knative.dev/hack v0.0.0-20210309141825-9b73a256fd9a
 	sigs.k8s.io/yaml v1.2.0
 )
diff --git a/go.sum b/go.sum
index 027a30ce6..4dab077d4 100644
--- a/go.sum
+++ b/go.sum
@@ -1168,8 +1168,8 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL
 k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
 k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg=
 k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-knative.dev/hack v0.0.0-20210305150220-f99a25560134 h1:lUllAp28TkevQIgWrsjow8ZLnXJy3AraRzGFm/ffD2c=
-knative.dev/hack v0.0.0-20210305150220-f99a25560134/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
+knative.dev/hack v0.0.0-20210309141825-9b73a256fd9a h1:0UGKyvFzY1Czu0lP9+0IrJhwtKe2oNLI2GYa7MIQ5c0=
+knative.dev/hack v0.0.0-20210309141825-9b73a256fd9a/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
 pgregory.net/rapid v0.3.3 h1:jCjBsY4ln4Atz78QoBWxUEvAHaFyNDQg9+WU62aCn1U=
 pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/injection/clients.go b/injection/clients.go
index 5c464924c..b71ef1d94 100644
--- a/injection/clients.go
+++ b/injection/clients.go
@@ -26,6 +26,10 @@ import (
 // client type to a context.
 type ClientInjector func(context.Context, *rest.Config) context.Context
 
+// ClientFetcher holds the type of a callback that returns a particular client type
+// from a context.
+type ClientFetcher func(context.Context) interface{}
+
 func (i *impl) RegisterClient(ci ClientInjector) {
 	i.m.Lock()
 	defer i.m.Unlock()
@@ -40,3 +44,21 @@ func (i *impl) GetClients() []ClientInjector {
 	// Copy the slice before returning.
 	return append(i.clients[:0:0], i.clients...)
 }
+
+func (i *impl) RegisterClientFetcher(f ClientFetcher) {
+	i.m.Lock()
+	defer i.m.Unlock()
+
+	i.clientFetchers = append(i.clientFetchers, f)
+}
+
+func (i *impl) FetchAllClients(ctx context.Context) []interface{} {
+	i.m.RLock()
+	defer i.m.RUnlock()
+
+	clients := make([]interface{}, 0, len(i.clientFetchers))
+	for _, f := range i.clientFetchers {
+		clients = append(clients, f(ctx))
+	}
+	return clients
+}
diff --git a/injection/interface.go b/injection/interface.go
index 7d2764cdc..112a6415f 100644
--- a/injection/interface.go
+++ b/injection/interface.go
@@ -36,6 +36,13 @@ type Interface interface {
 	// GetClients fetches all of the registered client injectors.
 	GetClients() []ClientInjector
 
+	// RegisterClientFetcher registers a new callback that fetches a client from
+	// a given context.
+	RegisterClientFetcher(ClientFetcher)
+
+	// FetchAllClients returns all known clients from the given context.
+	FetchAllClients(context.Context) []interface{}
+
 	// RegisterInformerFactory registers a new injector callback for associating
 	// a new informer factory with a context.
 	RegisterInformerFactory(InformerFactoryInjector)
@@ -92,6 +99,7 @@ type impl struct {
 	m sync.RWMutex
 
 	clients           []ClientInjector
+	clientFetchers    []ClientFetcher
 	factories         []InformerFactoryInjector
 	informers         []InformerInjector
 	filteredInformers []FilteredInformersInjector
diff --git a/metrics/config.go b/metrics/config.go
index c4c9c7f84..6407a1b0d 100644
--- a/metrics/config.go
+++ b/metrics/config.go
@@ -41,7 +41,7 @@ const (
 	DomainEnv = "METRICS_DOMAIN"
 
 	// The following keys are used to configure metrics reporting.
-	// See https://github.com/knative/serving/blob/master/config/config-observability.yaml
+	// See https://github.com/knative/serving/blob/main/config/config-observability.yaml
 	// for details.
 	allowStackdriverCustomMetricsKey = "metrics.allow-stackdriver-custom-metrics"
 	collectorAddressKey              = "metrics.opencensus-address"
diff --git a/metrics/exporter.go b/metrics/exporter.go
index 3fc4966fd..46e5916de 100644
--- a/metrics/exporter.go
+++ b/metrics/exporter.go
@@ -81,7 +81,7 @@ type ExporterOptions struct {
 	PrometheusHost string
 
 	// ConfigMap is the data from config map config-observability. Must be present.
-	// See https://github.com/knative/serving/blob/master/config/config-observability.yaml
+	// See https://github.com/knative/serving/blob/main/config/config-observability.yaml
 	// for details.
 	ConfigMap map[string]string
 
diff --git a/vendor/knative.dev/hack/README.md b/vendor/knative.dev/hack/README.md
index 50859e7af..a6a98c784 100644
--- a/vendor/knative.dev/hack/README.md
+++ b/vendor/knative.dev/hack/README.md
@@ -281,7 +281,7 @@ This is a helper script for Knative release scripts. To use it:
    - `RELEASE_VERSION`: contains the release version if `--version` was passed.
      This also overrides the value of the `TAG` variable as `v<version>`.
    - `RELEASE_BRANCH`: contains the release branch if `--branch` was passed.
-     Otherwise it's empty and `master` HEAD will be considered the release
+     Otherwise it's empty and `main` HEAD will be considered the release
      branch.
    - `RELEASE_NOTES`: contains the filename with the release notes if
      `--release-notes` was passed. The release notes is a simple markdown file.
diff --git a/vendor/knative.dev/hack/library.sh b/vendor/knative.dev/hack/library.sh
index 25b3407e8..f8f8b629c 100644
--- a/vendor/knative.dev/hack/library.sh
+++ b/vendor/knative.dev/hack/library.sh
@@ -787,18 +787,18 @@ function shellcheck_new_files() {
 function latest_version() {
   # This function works "best effort" and works on Prow but not necessarily locally.
   # The problem is finding the latest release. If a release occurs on the same commit which
-  # was branched from master, then the tag will be an ancestor to any commit derived from master.
+  # was branched from main, then the tag will be an ancestor to any commit derived from main.
   # That was the original logic. Additionally in a release branch, the tag is always an ancestor.
-  # However, if the release commit ends up not the first commit from master, then the tag is not
-  # an ancestor of master, so we can't use `git describe` to find the most recent versioned tag. So
+  # However, if the release commit ends up not the first commit from main, then the tag is not
+  # an ancestor of main, so we can't use `git describe` to find the most recent versioned tag. So
   # we just sort all the tags and find the newest versioned one.
-  # But when running locally, we cannot(?) know if the current branch is a fork of master or a fork
+  # But when running locally, we cannot(?) know if the current branch is a fork of main or a fork
   # of a release branch. That's where this function will malfunction when the last release did not
   # occur on the first commit -- it will try to run the upgrade tests from an older version instead
   # of the most recent release.
   # Workarounds include:
   # Tag the first commit of the release branch. Say release-0.75 released v0.75.0 from the second commit
-  # Then tag the first commit in common between master and release-0.75 with `v0.75`.
+  # Then tag the first commit in common between main and release-0.75 with `v0.75`.
   # Always name your local fork master or main.
   if [ $(current_branch) = "master" ] || [ $(current_branch) = "main" ]; then
     # For main branch, simply use git tag without major version, this will work even
diff --git a/vendor/knative.dev/hack/microbenchmarks.sh b/vendor/knative.dev/hack/microbenchmarks.sh
index ee375842c..549573fe5 100644
--- a/vendor/knative.dev/hack/microbenchmarks.sh
+++ b/vendor/knative.dev/hack/microbenchmarks.sh
@@ -32,11 +32,11 @@ function microbenchmarks_run() {
   go test -bench=. -benchtime=$BENCH_RUN_TIME -count=$BENCH_RUN_COUNT -benchmem -run="^$" -v ./...   >> "$OUTPUT_FILE" || exit
 }
 
-# To run microbenchmarks on your machine and compare your revision with upstream/master:
+# To run microbenchmarks on your machine and compare your revision with upstream/main:
 #
 # git fetch upstream
 # source microbenchmarks.sh
-# microbenchmarks_run_and_compare upstream/master
+# microbenchmarks_run_and_compare upstream/main
 #
 # NOTE: Hypothetically we should run these microbenchmarks on a machine running only a kernel and a shell,
 # but this might be sometimes hard to achieve unless you have a spare computer to play with.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 50e9cb633..2b856a924 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -947,7 +947,7 @@ k8s.io/utils/buffer
 k8s.io/utils/integer
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/hack v0.0.0-20210305150220-f99a25560134
+# knative.dev/hack v0.0.0-20210309141825-9b73a256fd9a
 ## explicit
 knative.dev/hack
 # sigs.k8s.io/structured-merge-diff/v4 v4.0.1
diff --git a/version/version.go b/version/version.go
index 34504debf..b2a4e2b47 100644
--- a/version/version.go
+++ b/version/version.go
@@ -32,7 +32,7 @@ const (
 
 	// NOTE: If you are changing this line, please also update the minimum kubernetes
 	// version listed here:
-	// https://github.com/knative/docs/blob/master/docs/install/any-kubernetes-cluster.md#before-you-begin
+	// https://github.com/knative/docs/blob/main/docs/install/any-kubernetes-cluster.md#before-you-begin
 	defaultMinimumVersion = "v1.17.0"
 )
 
diff --git a/webhook/psbinding/README.md b/webhook/psbinding/README.md
index e73ccf858..4715a3e67 100644
--- a/webhook/psbinding/README.md
+++ b/webhook/psbinding/README.md
@@ -3,7 +3,7 @@
 The `psbinding` package provides facilities to make authoring
 [Bindings](https://docs.google.com/document/d/1t5WVrj2KQZ2u5s0LvIUtfHnSonBv5Vcv8Gl2k5NXrCQ/edit)
 whose subjects adhere to
-[`duckv1.PodSpecable`](https://github.com/knative/pkg/blob/master/apis/duck/v1/podspec_types.go#L32)
+[`duckv1.PodSpecable`](https://github.com/knative/pkg/blob/main/apis/duck/v1/podspec_types.go#L32)
 easier. The Bindings doc mentions two key elements of the controller
 architecture:
 


Test patch:
diff --git a/injection/clients_test.go b/injection/clients_test.go
index 4e47006a1..d84dbb353 100644
--- a/injection/clients_test.go
+++ b/injection/clients_test.go
@@ -20,6 +20,7 @@ import (
 	"context"
 	"testing"
 
+	"github.com/google/go-cmp/cmp"
 	"k8s.io/client-go/rest"
 )
 
@@ -50,3 +51,35 @@ func TestRegisterClient(t *testing.T) {
 		t.Errorf("GetClients() = %d, wanted %d", want, got)
 	}
 }
+
+type fakeClient struct {
+	Name string
+}
+
+func TestRegisterClientFetcher(t *testing.T) {
+	i := &impl{}
+
+	fakeA := fakeClient{Name: "a"}
+	fetchA := func(ctx context.Context) interface{} {
+		return fakeA
+	}
+
+	fakeB := fakeClient{Name: "b"}
+	fetchB := func(ctx context.Context) interface{} {
+		return fakeB
+	}
+
+	ctx := context.Background()
+	if want, got := 0, len(i.FetchAllClients(ctx)); got != want {
+		t.Errorf("FetchAllClients() = %d, wanted %d", got, want)
+	}
+
+	i.RegisterClientFetcher(fetchA)
+	i.RegisterClientFetcher(fetchB)
+
+	got := i.FetchAllClients(ctx)
+	want := []interface{}{fakeA, fakeB}
+	if !cmp.Equal(got, want) {
+		t.Errorf("FetchAllClients() = %v, wanted %v", got, want)
+	}
+}
diff --git a/metrics/record_test.go b/metrics/record_test.go
index e597926ef..35fb28a07 100644
--- a/metrics/record_test.go
+++ b/metrics/record_test.go
@@ -29,6 +29,7 @@ import (
 	"go.opencensus.io/resource"
 	"go.opencensus.io/stats"
 	"go.opencensus.io/stats/view"
+	"go.opencensus.io/tag"
 )
 
 type cases struct {
@@ -226,3 +227,83 @@ func TestMeter(t *testing.T) {
 		})
 	}
 }
+
+func BenchmarkMetricsRecording(b *testing.B) {
+	requestKey := tag.MustNewKey("request")
+	requestStatus := tag.MustNewKey("requestStatus")
+	requestURL := tag.MustNewKey("requestUrl")
+	tagKeys := []tag.Key{requestKey, requestStatus, requestURL}
+	measure1 := stats.Int64("count1", "First counter", stats.UnitDimensionless)
+	measure2 := stats.Int64("count2", "Second counter", stats.UnitDimensionless)
+	v := []*view.View{{
+		Measure:     measure1,
+		Aggregation: view.LastValue(),
+		TagKeys:     tagKeys,
+	}, {
+		Measure:     measure2,
+		Aggregation: view.LastValue(),
+		TagKeys:     tagKeys,
+	}}
+	err := RegisterResourceView(v...)
+	if err != nil {
+		b.Error("Failed to register resource view")
+	}
+	defer UnregisterResourceView(v...)
+	metricsConfig := &metricsConfig{}
+	measurement1 := measure1.M(1000)
+	measurement2 := measure2.M(1)
+	setCurMetricsConfig(metricsConfig)
+	getTagCtx := func() (context.Context, error) {
+		ctx := context.Background()
+		ctx, err := tag.New(
+			ctx,
+			tag.Insert(requestKey, "login"),
+			tag.Insert(requestStatus, "status_ok"),
+			tag.Insert(requestURL, "localhost"),
+		)
+		return ctx, err
+	}
+	if err != nil {
+		b.Error("Failed to create tags")
+	}
+	b.Run("sequential", func(b *testing.B) {
+		for j := 0; j < b.N; j++ {
+			ctx, err := getTagCtx()
+			if err != nil {
+				b.Error("Failed to get context")
+			}
+			Record(ctx, measurement1)
+		}
+	})
+	b.Run("parallel", func(b *testing.B) {
+		b.RunParallel(func(pb *testing.PB) {
+			for pb.Next() {
+				ctx, err := getTagCtx()
+				if err != nil {
+					b.Error("Failed to get context")
+				}
+				Record(ctx, measurement1)
+			}
+		})
+	})
+	b.Run("sequential-batch", func(b *testing.B) {
+		for j := 0; j < b.N; j++ {
+			ctx, err := getTagCtx()
+			if err != nil {
+				b.Error("Failed to get context")
+			}
+			RecordBatch(ctx, measurement1, measurement2)
+		}
+	})
+	b.Run("parallel-batch", func(b *testing.B) {
+		b.RunParallel(func(pb *testing.PB) {
+			for pb.Next() {
+				ctx, err := getTagCtx()
+				if err != nil {
+					b.Error("Failed to get context")
+				}
+				RecordBatch(ctx, measurement1, measurement2)
+			}
+		})
+	})
+}
diff --git a/reconciler/testing/context.go b/reconciler/testing/context.go
index 7c36d8ed7..aa7f385be 100644
--- a/reconciler/testing/context.go
+++ b/reconciler/testing/context.go
@@ -18,10 +18,19 @@ package testing
 
 import (
 	"context"
+	"time"
 
+	"go.uber.org/atomic"
 	"go.uber.org/zap/zaptest"
 
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/runtime/serializer"
+	"k8s.io/apimachinery/pkg/util/wait"
+	"k8s.io/apimachinery/pkg/watch"
 	"k8s.io/client-go/rest"
+	clientgotesting "k8s.io/client-go/testing"
 	"k8s.io/client-go/tools/record"
 
 	"knative.dev/pkg/controller"
@@ -43,3 +52,73 @@ func SetupFakeContextWithCancel(t zaptest.TestingT) (context.Context, context.Ca
 	ctx, is := injection.Fake.SetupInformers(ctx, &rest.Config{})
 	return ctx, c, is
 }
+
+// fakeClient is an interface capturing the two functions we need from fake clients.
+type fakeClient interface {
+	PrependWatchReactor(resource string, reaction clientgotesting.WatchReactionFunc)
+	PrependReactor(verb, resource string, reaction clientgotesting.ReactionFunc)
+}
+
+// withTracker is an interface capturing only the Tracker function. The dynamic client
+// currently does not have that, so we need to special-case it.
+type withTracker interface {
+	Tracker() clientgotesting.ObjectTracker
+}
+
+// RunAndSyncInformers runs the given informers, then makes sure their caches are all
+// synced and in addition makes sure that all the Watch calls have been properly setup.
+// See https://github.com/kubernetes/kubernetes/issues/95372 for background on the Watch
+// calls tragedy.
+func RunAndSyncInformers(ctx context.Context, informers ...controller.Informer) (func(), error) {
+	var watchesPending atomic.Int32
+
+	for _, client := range injection.Fake.FetchAllClients(ctx) {
+		c := client.(fakeClient)
+
+		var tracker clientgotesting.ObjectTracker
+		if withTracker, ok := c.(withTracker); ok {
+			tracker = withTracker.Tracker()
+		} else {
+			// Required setup for the dynamic client as it doesn't define a Tracker() function.
+			// TODO(markusthoemmes): Drop this if https://github.com/kubernetes/kubernetes/pull/100085 lands.
+			scheme := runtime.NewScheme()
+			scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "List"}, &unstructured.UnstructuredList{})
+			codecs := serializer.NewCodecFactory(scheme)
+			tracker = clientgotesting.NewObjectTracker(scheme, codecs.UniversalDecoder())
+		}
+
+		c.PrependReactor("list", "*", func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
+			// Every list (before actual informer usage) is going to be followed by a Watch call.
+			watchesPending.Inc()
+			return false, nil, nil
+		})
+
+		c.PrependWatchReactor("*", func(action clientgotesting.Action) (handled bool, ret watch.Interface, err error) {
+			// The actual Watch call. This is a reimplementation of the default Watch
+			// calls in fakes to guarantee we have actually **done** the work.
+			gvr := action.GetResource()
+			ns := action.GetNamespace()
+			watch, err := tracker.Watch(gvr, ns)
+			if err != nil {
+				return false, nil, err
+			}
+
+			watchesPending.Dec()
+
+			return true, watch, nil
+		})
+	}
+
+	wf, err := controller.RunInformers(ctx.Done(), informers...)
+	if err != nil {
+		return wf, err
+	}
+
+	err = wait.PollImmediate(time.Microsecond, wait.ForeverTestTimeout, func() (bool, error) {
+		if watchesPending.Load() == 0 {
+			return true, nil
+		}
+		return false, nil
+	})
+	return wf, err
+}
diff --git a/test/README.md b/test/README.md
index d106ffec9..c56070878 100644
--- a/test/README.md
+++ b/test/README.md
@@ -28,7 +28,7 @@ You can use the test library in this dir to:
 
 These flags are useful for running against an existing cluster, making use of
 your existing
-[environment setup](https://github.com/knative/serving/blob/master/DEVELOPMENT.md#environment-setup).
+[environment setup](https://github.com/knative/serving/blob/main/DEVELOPMENT.md#environment-setup).
 
 By importing `knative.dev/pkg/test` you get access to a global variable called
 `test.Flags` which holds the values of
@@ -46,7 +46,7 @@ _See [e2e_flags.go](./e2e_flags.go)._
 debug logs will be emitted to stdout.
 
 We are using a generic
-[FormatLogger](https://github.com/knative/pkg/blob/master/test/logging/logging.go#L49)
+[FormatLogger](https://github.com/knative/pkg/blob/main/test/logging/logging.go#L49)
 that can be passed in any existing logger that satisfies it. Test can use the
 generic [logging methods](https://golang.org/pkg/testing/#T) to log info and
 error logs. All the common methods accept generic FormatLogger as a parameter
@@ -64,7 +64,7 @@ _See [logging.go](./logging/logging.go)._
 ### Check Knative Serving resources
 
 _WARNING: this code also exists in
-[`knative/serving`](https://github.com/knative/serving/blob/master/test/adding_tests.md#make-requests-against-deployed-services)._
+[`knative/serving`](https://github.com/knative/serving/blob/main/test/adding_tests.md#make-requests-against-deployed-services)._
 
 After creating Knative Serving resources or making changes to them, you will
 need to wait for the system to realize those changes. You can use the Knative
diff --git a/test/logstream/README.md b/test/logstream/README.md
index 18577b855..7c7886bd5 100644
--- a/test/logstream/README.md
+++ b/test/logstream/README.md
@@ -8,7 +8,7 @@ This is a guide to start using `logstream` in your e2e testing.
    knative test scripts already define this, and in some places (e.g. serving)
    randomize it. However, to facilitate usage outside of CI, you should consider
    including a package like
-   [this](https://github.com/knative/serving/blob/master/test/defaultsystem/system.go)
+   [this](https://github.com/knative/serving/blob/main/test/defaultsystem/system.go)
    and linking it like
    [this](https://github.com/knative/serving/blob/e797247322b5aa35001152d2a2715dbc20a86cc4/test/conformance.go#L20-L23)
 
@@ -49,4 +49,4 @@ Now, any log statements that the library prints through this logger will appear
 in the logstream!
 
 For an example of this pattern, see
-[the knative/networking prober library](https://github.com/knative/networking/blob/master/pkg/status/status.go).
+[the knative/networking prober library](https://github.com/knative/networking/blob/main/pkg/status/status.go).
diff --git a/test/mako/sidecar.go b/test/mako/sidecar.go
index ff890f624..2b6057c1e 100644
--- a/test/mako/sidecar.go
+++ b/test/mako/sidecar.go
@@ -53,7 +53,7 @@ const (
 	// These token settings are for alerter.
 	// If we want to enable the alerter for a benchmark, we need to mount the
 	// token to the pod, with the same name and path.
-	// See https://github.com/knative/serving/blob/master/test/performance/benchmarks/dataplane-probe/continuous/dataplane-probe.yaml
+	// See https://github.com/knative/serving/blob/main/test/performance/benchmarks/dataplane-probe/continuous/dataplane-probe.yaml
 	tokenFolder     = "/var/secret"
 	githubToken     = "github-token"
 	slackReadToken  = "slack-read-token"
diff --git a/test/zipkin/util.go b/test/zipkin/util.go
index 95659c3b4..5e9cb5feb 100644
--- a/test/zipkin/util.go
+++ b/test/zipkin/util.go
@@ -46,7 +46,7 @@ const (
 	ZipkinTraceIDHeader = "ZIPKIN_TRACE_ID"
 
 	// ZipkinPort is port exposed by the Zipkin Pod
-	// https://github.com/knative/serving/blob/master/config/monitoring/200-common/100-zipkin.yaml#L25 configures the Zipkin Port on the cluster.
+	// https://github.com/knative/serving/blob/main/config/monitoring/200-common/100-zipkin.yaml#L25 configures the Zipkin Port on the cluster.
 	ZipkinPort = 9411
 
 	// ZipkinTraceEndpoint port-forwarded zipkin endpoint
diff --git a/webhook/webhook_test.go b/webhook/webhook_test.go
index 340eb7154..d5ea25f94 100644
--- a/webhook/webhook_test.go
+++ b/webhook/webhook_test.go
@@ -24,7 +24,6 @@ import (
 	"time"
 
 	"golang.org/x/sync/errgroup"
-	"knative.dev/pkg/controller"
 
 	// Make system.Namespace() work in tests.
 	_ "knative.dev/pkg/system/testing"
@@ -53,7 +52,7 @@ func newNonRunningTestWebhook(t *testing.T, options Options, acs ...interface{})
 	ctx, ctxCancel, informers := SetupFakeContextWithCancel(t)
 	ctx = WithOptions(ctx, options)
 
-	stopCb, err := controller.RunInformers(ctx.Done(), informers...)
+	stopCb, err := RunAndSyncInformers(ctx, informers...)
 	if err != nil {
 		t.Fatal("StartInformers() =", err)
 	}