Repository: shipwright-io/build
Pull request #737 (2021-04-22 14:44:11)

Provide well-documented parameters for source and image for the build strategy author
# Changes

First part for the [Tekton parameter replacement](https://github.com/shipwright-io/build/blob/master/docs/proposals/removal-tekton-resources.md#risks-and-mitigations) / [Remove usage of Tekton resources #696](https://github.com/shipwright-io/build/issues/696): introducing our own parameters for the output image and source directory. From the longer list in the referenced EP, this is 3 and a part of 1.

Notes:

* for runtime images, there was actually a bug as the rendered runtime image always used the build's output image. This would have failed if the BuildRun specified a different one.
* also related to runtime images, in the `runtimeBuildAndPushStep` function, I intentionally removed the `--context` argument because the generated Dockerfile.runtime does not contain any `COPY` or `ADD` commands that take from the context, but rather always from the first stage
* in the TaskRun generation, I retained the old string transformation, like `$(build.output.image)` although no sample build strategy uses it anymore. As this is kind of a break of a (non-documented) API, we can do the removal in a later release

# Submitter Checklist

- [x] Includes tests if functionality changed/was added
- [x] Includes docs if changes are user-facing
- [x] [Set a kind label on this PR](https://prow.k8s.io/command-help#kind)  
- [x] Release notes block has been filled in, or marked NONE

# Release Notes

```release-note
action required: Introduce system-provided parameters: shp-output-image, shp-source-root, and shp-source-context. Sample build strategies are adopted. If you have your own build strategies, ensure they are updated to use these parameters.
```

openshift-ci-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 ask for approval from **saschaschwarze0** after the PR has been reviewed.

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

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

- **[OWNERS](https://github.com/shipwright-io/build/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":["saschaschwarze0"]} -->

Patch:
diff --git a/Makefile b/Makefile
index c36c61d7..9d512760 100644
--- a/Makefile
+++ b/Makefile
@@ -7,15 +7,9 @@ CONTROLLER = $(OUTPUT_DIR)/bin/shipwright-build-controller
 
 # golang cache directory path
 GOCACHE ?= $(shell echo ${PWD})/$(OUTPUT_DIR)/gocache
-
 # golang target architecture
-# Check if GO_OS is defined, if not set it to `linux` which is the only supported OS
-# this provides flexibility to users to set GO_OS in the future if require
-ifeq ($(origin GO_OS), undefined)
-GO_OS = "linux"
-endif
+GO_OS ?= $(shell uname | tr '[:upper:]' '[:lower:]')
 GO_ARCH ?= $(shell uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/')
-
 # golang global flags
 GO_FLAGS ?= -v -mod=vendor -ldflags=-w
 
@@ -33,7 +27,7 @@ ZAP_FLAGS ?= --zap-log-level=debug --zap-encoder=console
 TEST_NAMESPACE ?= default
 
 # CI: tekton pipelines controller version
-TEKTON_VERSION ?= v0.23.0
+TEKTON_VERSION ?= v0.21.0
 
 # E2E test flags
 TEST_E2E_FLAGS ?= -failFast -p -randomizeAllSpecs -slowSpecThreshold=300 -timeout=30m -progress -stream -trace -v
@@ -232,7 +226,6 @@ test-e2e-kind-with-prereq-install: ginkgo install-controller-kind install-strate
 .PHONY: install install-apis install-controller install-strategies
 
 install:
-	@echo "Building Shipwright Build controller for platform ${GO_OS}/${GO_ARCH}"
 	GOOS=$(GO_OS) GOARCH=$(GO_ARCH) KO_DOCKER_REPO="$(IMAGE_HOST)/$(IMAGE)" GOFLAGS="$(GO_FLAGS)" ko apply --bare -R -f deploy/
 
 install-with-pprof:
@@ -244,7 +237,6 @@ install-apis:
 	kubectl wait --timeout=10s --for condition=established crd/clusterbuildstrategies.shipwright.io
 
 install-controller: install-apis
-	@echo "Building Shipwright Build controller for platform ${GO_OS}/${GO_ARCH}"
 	GOOS=$(GO_OS) GOARCH=$(GO_ARCH) KO_DOCKER_REPO="$(IMAGE_HOST)/$(IMAGE)" GOFLAGS="$(GO_FLAGS)" ko apply --bare -f deploy/
 
 install-controller-kind: install-apis
diff --git a/README.md b/README.md
index 19c58069..80a07019 100644
--- a/README.md
+++ b/README.md
@@ -134,7 +134,6 @@ To find out more on what's the best strategy or what else can Shipwright do for
 | Version | Docs                           | Examples                    |
 | ------- | ------------------------------ | --------------------------- |
 | HEAD    | [Docs @ HEAD](/docs/README.md) | [Examples @ HEAD](/samples) |
-| [v0.4.0](https://github.com/shipwright-io/build/releases/tag/v0.4.0)    | [Docs @ v0.4.0](https://github.com/shipwright-io/build/tree/v0.4.0/docs) | [Examples @ v0.4.0](https://github.com/shipwright-io/build/tree/v0.4.0/samples) |
 | [v0.3.0](https://github.com/shipwright-io/build/releases/tag/v0.3.0)    | [Docs @ v0.3.0](https://github.com/shipwright-io/build/tree/v0.3.0/docs) | [Examples @ v0.3.0](https://github.com/shipwright-io/build/tree/v0.3.0/samples) |
 | [v0.2.0](https://github.com/shipwright-io/build/releases/tag/v0.2.0)    | [Docs @ v0.2.0](https://github.com/shipwright-io/build/tree/v0.2.0/docs) | [Examples @ v0.2.0](https://github.com/shipwright-io/build/tree/v0.2.0/samples) |
 | [v0.1.1](https://github.com/shipwright-io/build/releases/tag/v0.1.1)    | [Docs @ v0.1.1](https://github.com/shipwright-io/build/tree/v0.1.1/docs) | [Examples @ v0.1.1](https://github.com/shipwright-io/build/tree/v0.1.1/samples) |
@@ -145,7 +144,7 @@ To find out more on what's the best strategy or what else can Shipwright do for
 | Dependency                           | Supported versions           |
 | -------------------------------------| ---------------------------- |
 | [Kubernetes](https://kubernetes.io/) | v1.17.\*, v1.18.\*, v1.19.\*, v1.20.\* |
-| [Tekton](https://tekton.dev)         | v0.19.0, v0.20.\*, v0.21.0, v0.22.0, v0.23.0 |
+| [Tekton](https://tekton.dev)         | v0.19.0, v0.20.\*, v0.21.0   |
 
 ### Platform support
 
diff --git a/cmd/manager/main.go b/cmd/manager/main.go
index 4a35a82b..d2df24ee 100644
--- a/cmd/manager/main.go
+++ b/cmd/manager/main.go
@@ -22,6 +22,7 @@ import (
 
 	buildconfig "github.com/shipwright-io/build/pkg/config"
 	"github.com/shipwright-io/build/pkg/controller"
+	"github.com/shipwright-io/build/pkg/controller/ready"
 	"github.com/shipwright-io/build/pkg/ctxlog"
 	buildMetrics "github.com/shipwright-io/build/pkg/metrics"
 	"github.com/shipwright-io/build/version"
@@ -74,6 +75,14 @@ func main() {
 		os.Exit(1)
 	}
 
+	r := ready.NewFileReady("/tmp/shipwright-build-ready")
+	err = r.Set()
+	if err != nil {
+		ctxlog.Error(ctx, err, "Checking for /tmp/shipwright-build-ready failed")
+		os.Exit(1)
+	}
+	defer r.Unset()
+
 	buildCfg := buildconfig.NewDefaultConfig()
 	if err := buildCfg.SetConfigFromEnv(); err != nil {
 		ctxlog.Error(ctx, err, "")
diff --git a/deploy/500-controller.yaml b/deploy/500-controller.yaml
index c0339122..1e34a019 100644
--- a/deploy/500-controller.yaml
+++ b/deploy/500-controller.yaml
@@ -32,18 +32,17 @@ spec:
                   fieldPath: metadata.name
             - name: CONTROLLER_NAME
               value: "shipwright-build"
-          ports:
-            - containerPort: 8383
-              name: metrics-port
           livenessProbe:
-            httpGet:
-              path: /metrics
-              port: metrics-port
+            exec:
+              command:
+                - stat
+                - /tmp/shipwright-build-ready
             initialDelaySeconds: 5
             periodSeconds: 10
           readinessProbe:
-            httpGet:
-              path: /metrics
-              port: metrics-port
+            exec:
+              command:
+                - stat
+                - /tmp/shipwright-build-ready
             initialDelaySeconds: 5
             periodSeconds: 10
diff --git a/docs/buildstrategies.md b/docs/buildstrategies.md
index 574d9922..173e6890 100644
--- a/docs/buildstrategies.md
+++ b/docs/buildstrategies.md
@@ -187,6 +187,16 @@ kubectl apply -f samples/buildstrategy/source-to-image/buildstrategy_source-to-i
 [s2i]: https://github.com/openshift/source-to-image
 [buildah]: https://github.com/containers/buildah
 
+## System parameters
+
+You can use parameters when defining the steps of a build strategy to access system information as well as information provided by the user in his Build or BuildRun. The following parameters are available:
+
+| Parameter                      | Description |
+| ------------------------------ | ----------- |
+| `$(params.shp-source-root)`    | The absolute path to the directory that contains the user's sources. |
+| `$(params.shp-source-context)` | The absolute path to the context directory of the user's sources. If the user specified no value for `spec.source.contextDir` in his Build, then this value will equal the value for `$(params.shp-source-root)`. Note that this directory is not guaranteed to exist at the time the container for your step is started, you can therefore not use this parameter as a step's working directory. |
+| `$(params.shp-output-image)`      | The URL of the image that the user wants to push as specified in the Build's `spec.output.image`, or the override from the BuildRun's `spec.output.image`. |
+
 ## Steps Resource Definition
 
 All strategies steps can include a definition of resources(_limits and requests_) for CPU, memory and disk. For strategies with more than one step, each step(_container_) could require more resources than others. Strategy admins are free to define the values that they consider the best fit for each step. Also, identical strategies with the same steps that are only different in their name and step resources can be installed on the cluster to allow users to create a build with smaller and larger resource requirements.
@@ -205,7 +215,7 @@ spec:
   buildSteps:
     - name: build-and-push
       image: gcr.io/kaniko-project/executor:v1.5.2
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         runAsUser: 0
         capabilities:
@@ -229,8 +239,8 @@ spec:
       args:
         - --skip-tls-verify=true
         - --dockerfile=$(build.dockerfile)
-        - --context=/workspace/source/$(build.source.contextDir)
-        - --destination=$(build.output.image)
+        - --context=$(params.shp-source-context)
+        - --destination=$(params.shp-output-image)
         - --oci-layout-path=/workspace/output/image
         - --snapshotMode=redo
         - --push-retry=3
@@ -250,7 +260,7 @@ spec:
   buildSteps:
     - name: build-and-push
       image: gcr.io/kaniko-project/executor:v1.5.2
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         runAsUser: 0
         capabilities:
@@ -274,8 +284,8 @@ spec:
       args:
         - --skip-tls-verify=true
         - --dockerfile=$(build.dockerfile)
-        - --context=/workspace/source/$(build.source.contextDir)
-        - --destination=$(build.output.image)
+        - --context=$(params.shp-source-context)
+        - --destination=$(params.shp-output-image)
         - --oci-layout-path=/workspace/output/image
         - --snapshotMode=redo
         - --push-retry=3
@@ -403,14 +413,14 @@ If we will apply the following resources:
   ```yaml
     - name: buildah-bud
       image: quay.io/buildah/stable:latest
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         privileged: true
       command:
         - /usr/bin/buildah
       args:
         - bud
-        - --tag=$(build.output.image)
+        - --tag=$(params.shp-output-image)
         - --file=$(build.dockerfile)
         - $(build.source.contextDir)
       resources:
@@ -432,7 +442,7 @@ If we will apply the following resources:
       args:
         - push
         - --tls-verify=false
-        - docker://$(build.output.image)
+        - docker://$(params.shp-output-image)
       resources:
         limits:
           cpu: 500m
diff --git a/docs/proposals/removal-tekton-resources.md b/docs/proposals/removal-tekton-resources.md
index 2fe66c52..89a404b4 100644
--- a/docs/proposals/removal-tekton-resources.md
+++ b/docs/proposals/removal-tekton-resources.md
@@ -99,13 +99,13 @@ Here is the list of parameters that we will make available:
 
 | Name | Purpose |
 | ---- | ------- |
-| `shp-image-url` | The URL of the image to be built. |
+| `shp-output-image` | The reference of the image to be built. |
 | `shp-source-root` | The path to the directory where we download the sources to. The value is hard-coded and will be `/workspace/source` |
 | `shp-source-context` | The path to the context directory inside the sources. The value depends on the presence of the `contextDir` in the user's Build. If it is not present, then the value will be `/workspace/source`, otherwise it will be `path.Join("/workspace/source", build.spec.contextDir)`. The purpose is that a build strategy author is not required to manually concatenate these values. |
 
 The build strategy author uses those parameters using the `$(params.<PARAMETER_NAME>)` syntax.
 
-We stop supporting the `$(build.output.image)` replacement token that is today used to access the image URL from the build strategy.
+We stop supporting the `$(build.output.image)` replacement token that is today used to access the image reference from the build strategy.
 
 The build strategy documentation will list above parameters which makes them part of our API.
 
@@ -193,8 +193,6 @@ The image URL is a new configuration option of the build controller deployment (
 
 The resources of the step are also configurable at the build controller deployment level with reasonable defaults.
 
-
-
 The way we run the download logic is something we can implement in a staged approach and start with the simple approach: Just a container with the necessary command-line tools (like `git`), and a simple executable implemented by us that parses the arguments and calls the `git` binary similar to [today's logic in Tekton](https://github.com/tektoncd/pipeline/blob/v0.21.0/pkg/git/git.go).
 
 Eventually, I propose we evolve our code to use libraries like [go-git](https://github.com/go-git/go-git) to perform the logic. This enables us to improve our error handling (and retry certain network errors) and reporting as this usually can be done better when using libraries compared to when calling other executables. On the other hand, we need to check if go-git has maybe limitations (for example missing lfs support) that forces us to stay on the approach to call the `git` binary.
@@ -209,7 +207,7 @@ The complexity and the relationship with other enhancement proposals like [Add E
 
 To address the complexity, I suggest that the implementation is done in a staged approach with smaller but consistent changes (the numbering sometimes implies dependencies, but some things are also independent and can be worked on in parallel or in a different order):
 
-1. Introduce system parameter for the output image (`shp-image-url`), remove the image resource, use the new system parameter in the sample build strategies to access the designated location of the output image. Comment out those arguments in the Kaniko and ko strategies that write the image digest file.
+1. Introduce system parameter for the output image (`shp-output-image`), remove the image resource, use the new system parameter in the sample build strategies to access the designated location of the output image. Comment out those arguments in the Kaniko and ko strategies that write the image digest file.
 2. Implement a container image that accepts the arguments for the Git operation and runs the `git clone`, either already using [go-git](https://github.com/go-git/go-git) if that is easy to achieve, or using Tekton's approach to call the `git` binary. Tests for the binary must be implemented as well for public and private repositories.
 3. Introduce system parameters that point to the source directory (`shp-source-root` and `shp-source-context`) and use them in our sample build strategies as a replacement of the hardcoded `/workspace/source` paths.
 4. Introduce the `shipwright` workspace. Replace the Git resource with our own custom step that consumes the container image from (2). Stop adding the Git secret to the service account and mount it to this step directly.
@@ -276,7 +274,7 @@ To run our own logic to download the sources, instead of having one step per sou
 
 ---
 
-Instead of a single parameter for the image URL (`shp-image-url`), one could have split this into different parameters to separate the tag into an own parameter (`shp-image-tag`). This would have helped strategies that need this value separately. [We decided](https://github.com/shipwright-io/build/pull/727#discussion_r615930419) against this for simplicity and because ko is the only tool today that needs this (and parses the image URL to split it). It is possible to revisit this in the future and to provide additional parameters if needed.
+Instead of a single parameter for the output image (`shp-output-image`), one could have split this into different parameters to separate the tag into an own parameter (`shp-output-image-tag`). This would have helped strategies that need this value separately. [We decided](https://github.com/shipwright-io/build/pull/727#discussion_r615930419) against this for simplicity and because ko is the only tool today that needs this (and parses the image URL to split it). It is possible to revisit this in the future and to provide additional parameters if needed.
 
 ## Infrastructure Needed [optional]
 
diff --git a/go.mod b/go.mod
index ce061597..8dfe1995 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
 	github.com/prometheus/client_golang v1.8.0
 	github.com/prometheus/client_model v0.2.0
 	github.com/spf13/pflag v1.0.5
-	github.com/tektoncd/pipeline v0.23.0
+	github.com/tektoncd/pipeline v0.21.0
 	go.uber.org/zap v1.16.0
 	k8s.io/api v0.20.2
 	k8s.io/apimachinery v0.20.2
diff --git a/go.sum b/go.sum
index 943c227a..6bfdd70f 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,7 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
 cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
 cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
 cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
@@ -13,6 +14,7 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP
 cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
 cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
 cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.64.0/go.mod h1:xfORb36jGvE+6EexW71nMEtL025s3x6xvuYUKM4JLv4=
 cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
 cloud.google.com/go v0.72.0 h1:eWRCuwubtDrCJG0oSUMgnsbD4CmPFQF2ei4OFbXvwww=
 cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
@@ -34,6 +36,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
 cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
 cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+cloud.google.com/go/storage v1.11.0/go.mod h1:/PAbprKS+5msVYogBmczjWalDXnQ9mr64yEq9YnyPeo=
 contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d h1:LblfooH1lKOpp1hIhukktmSAxFkqMPFk9KR6iZ0MJNI=
 contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d/go.mod h1:IshRmMJBhDfFj5Y67nVhMYTTIze91RUeT73ipWKs/GY=
 contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0 h1:2O3c1g5CzMc1+Uah4Waot9Obm0yw70VXJzWaP6Fz3nw=
@@ -42,19 +45,23 @@ contrib.go.opencensus.io/exporter/stackdriver v0.13.4 h1:ksUxwH3OD5sxkjzEqGxNTl+
 contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
 contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
 github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-sdk-for-go v50.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
 github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
 github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
-github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ=
 github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
+github.com/Azure/go-autorest/autorest v0.11.17 h1:2zCdHwNgRH+St1J+ZMf66xI8aLr/5KMy+wWLH97zwYM=
+github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
 github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
 github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
 github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
-github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0=
 github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
+github.com/Azure/go-autorest/autorest/adal v0.9.10 h1:r6fZHMaHD8B6LDCn0o5vyBFHIHrM6Ywwx7mb49lPItI=
+github.com/Azure/go-autorest/autorest/adal v0.9.10/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
 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 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
@@ -67,7 +74,9 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPu
 github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
 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=
+github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
 github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
+github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
 github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
 github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
 github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
@@ -77,6 +86,9 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
 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=
+github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/GoogleCloudPlatform/cloud-builders/gcs-fetcher v0.0.0-20191203181535-308b93ad1f39/go.mod h1:yfGmCjKuUzk9WzubMlW2zwjhCraIc/J+M40cufdemRM=
 github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317/go.mod h1:DF8FZRxMHMGv/vP2lQP6h+dYzzjpuRn24VeRiYn3qjQ=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
@@ -91,6 +103,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
 github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
@@ -124,8 +137,9 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ
 github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.27.0/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.31.12 h1:SxRRGyhlCagI0DYkhOg+FgdXGXzRTE3vEX/gsgFaiKQ=
 github.com/aws/aws-sdk-go v1.31.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.37.1 h1:BTHmuN+gzhxkvU9sac2tZvaY0gV9ihbHw+KxZOecYvY=
+github.com/aws/aws-sdk-go v1.37.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
 github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -206,6 +220,7 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
@@ -334,6 +349,7 @@ github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -369,6 +385,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
 github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
 github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
 github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
@@ -410,6 +427,7 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG
 github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
 github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -421,6 +439,8 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
+github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
@@ -491,11 +511,16 @@ github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9Gkys
 github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
+github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
 github.com/jenkins-x/go-scm v1.5.117/go.mod h1:PCT338UhP/pQ0IeEeMEf/hoLTYKcH7qjGEKd7jPkeYg=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
 github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
+github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@@ -522,6 +547,7 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -627,6 +653,7 @@ github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
 github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
+github.com/openzipkin/zipkin-go v0.2.0/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
@@ -642,8 +669,10 @@ github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtb
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pierrec/lz4 v2.2.6+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -657,6 +686,7 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
 github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
 github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
 github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
@@ -673,6 +703,7 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
 github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
 github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
@@ -682,6 +713,7 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
 github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
 github.com/prometheus/procfs v0.0.6/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
@@ -693,6 +725,7 @@ github.com/prometheus/statsd_exporter v0.15.0 h1:UiwC1L5HkxEPeapXdm2Ye0u1vUJfTj7
 github.com/prometheus/statsd_exporter v0.15.0/go.mod h1:Dv8HnkoLQkeEjkIE4/2ndAA7WL1zHKK7WMqFQqu72rw=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -755,8 +788,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
 github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/tektoncd/pipeline v0.23.0 h1:nOyk1KqXTZBlqRx20YrITUh7F/uDI2bXMfHedIxIzEY=
-github.com/tektoncd/pipeline v0.23.0/go.mod h1:QcD1kMaXVIHA/V7RCi4NQUCR6z3plBVjmglRbpS71FQ=
+github.com/tektoncd/pipeline v0.21.0 h1:Dq4pPy0z7IIw8RiLjc+rEHPmA3cuCN2Ra/VZ7nDwCLo=
+github.com/tektoncd/pipeline v0.21.0/go.mod h1:GwdfGGt/5VhZL8JvJu8kFz8friKufcJ/TJkJmK6uc0U=
 github.com/tektoncd/plumbing v0.0.0-20201021153918-6b7e894737b5/go.mod h1:WTWwsg91xgm+jPOKoyKVK/yRYxnVDlUYeDlypB1lDdQ=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -774,6 +807,8 @@ github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv
 github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
 github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
+github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -822,6 +857,7 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -841,6 +877,7 @@ golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
 golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
 golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
@@ -863,6 +900,7 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7
 golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mobile v0.0.0-20190806162312-597adff16ade/go.mod h1:AlhUtkH4DA4asiFC5RgK7ZKmauvtkAVcy9L0epCzlWo=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
 golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@@ -914,6 +952,7 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
@@ -958,6 +997,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -967,6 +1007,8 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1051,6 +1093,7 @@ golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgw
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
 golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
+golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -1089,7 +1132,9 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 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-20200817023811-d00afeaade8f/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
 golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
 golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -1148,6 +1193,7 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn
 google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
+google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
@@ -1173,7 +1219,9 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc
 google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
 google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/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-20200815001618-f69a88009b70/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-20200827165113-ac2560b5e952/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -1231,6 +1279,11 @@ gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
 gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
@@ -1264,6 +1317,7 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
diff --git a/hack/install-tekton.sh b/hack/install-tekton.sh
index fe8298f0..e6ef9093 100755
--- a/hack/install-tekton.sh
+++ b/hack/install-tekton.sh
@@ -9,7 +9,7 @@
 
 set -eu
 
-TEKTON_VERSION="${TEKTON_VERSION:-v0.23.0}"
+TEKTON_VERSION="${TEKTON_VERSION:-v0.21.0}"
 
 TEKTON_HOST="github.com"
 TEKTON_HOST_PATH="tektoncd/pipeline/releases/download"
diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go
index 5901d694..de361056 100644
--- a/pkg/controller/controller.go
+++ b/pkg/controller/controller.go
@@ -21,6 +21,19 @@ import (
 	"github.com/shipwright-io/build/pkg/reconciler/clusterbuildstrategy"
 )
 
+// AddToManagerFuncs is a list of functions to add all Controllers to the Manager
+var AddToManagerFuncs []func(context.Context, *config.Config, manager.Manager) error
+
+// AddToManager adds all Controllers to the Manager
+func AddToManager(ctx context.Context, c *config.Config, m manager.Manager) error {
+	for _, f := range AddToManagerFuncs {
+		if err := f(ctx, c, m); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
 // NewManager add all the controllers to the manager and register the required schemes
 func NewManager(ctx context.Context, config *config.Config, cfg *rest.Config, options manager.Options) (manager.Manager, error) {
 	mgr, err := manager.New(cfg, options)
@@ -46,7 +59,6 @@ func NewManager(ctx context.Context, config *config.Config, cfg *rest.Config, op
 		return nil, err
 	}
 
-	// Add Reconcilers.
 	if err := build.Add(ctx, config, mgr); err != nil {
 		return nil, err
 	}
@@ -63,5 +75,10 @@ func NewManager(ctx context.Context, config *config.Config, cfg *rest.Config, op
 		return nil, err
 	}
 
+	// Setup all Controllers
+	if err := AddToManager(ctx, config, mgr); err != nil {
+		return nil, err
+	}
+
 	return mgr, nil
 }
diff --git a/pkg/controller/ready/ready.go b/pkg/controller/ready/ready.go
new file mode 100644
index 00000000..3c9664d0
--- /dev/null
+++ b/pkg/controller/ready/ready.go
@@ -0,0 +1,52 @@
+// Copyright The Shipwright Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package ready
+
+import "os"
+
+// Ready holds state about whether the controller is ready and communicates
+// that to a Kubernetes readiness/liveness probe.
+type Ready interface {
+	// Set ensures that future readiness/liveness probes will indicate that
+	// the controller is ready.
+	Set() error
+
+	// Unset ensures that future readiness/liveness probes will indicate
+	// that the controller is not ready.
+	Unset() error
+}
+
+type fileReady struct {
+	filename string
+}
+
+// NewFileReady returns a Ready that uses the presence of a file on disk to
+// communicate whether the controller is ready.
+func NewFileReady(filename string) Ready {
+	return fileReady{filename}
+}
+
+// Set creates a file on disk whose presence can be used by a
+// readiness/liveness probe.
+func (r fileReady) Set() error {
+	f, err := os.Create(r.filename)
+	if err != nil {
+		if os.IsExist(err) {
+			return nil
+		}
+		return err
+	}
+
+	return f.Close()
+}
+
+// Unset removes the file on disk that was created by Set().
+func (r fileReady) Unset() error {
+	if _, err := os.Stat(r.filename); os.IsNotExist(err) {
+		return nil
+	}
+
+	return os.Remove(r.filename)
+}
diff --git a/pkg/reconciler/buildrun/resources/remote_artifacts.go b/pkg/reconciler/buildrun/resources/remote_artifacts.go
index ae9c0a71..7294f50e 100644
--- a/pkg/reconciler/buildrun/resources/remote_artifacts.go
+++ b/pkg/reconciler/buildrun/resources/remote_artifacts.go
@@ -31,7 +31,7 @@ func remoteArtifactStep(b *buildv1alpha1.Build, image string) v1beta1.Step {
 	container := v1.Container{
 		Name:       "remote-artifacts",
 		Image:      image,
-		WorkingDir: workspaceDir,
+		WorkingDir: fmt.Sprintf("$(params.%s%s)", prefixParamsResults, paramSourceRoot),
 		Command:    []string{"/bin/sh"},
 		Args:       append([]string{"-e", "-x", "-c"}, strings.Join(script, " ; ")),
 	}
diff --git a/pkg/reconciler/buildrun/resources/runtime_image.go b/pkg/reconciler/buildrun/resources/runtime_image.go
index 3bfdf71c..9600c98d 100644
--- a/pkg/reconciler/buildrun/resources/runtime_image.go
+++ b/pkg/reconciler/buildrun/resources/runtime_image.go
@@ -7,7 +7,6 @@ package resources
 import (
 	"bytes"
 	"fmt"
-	"path"
 	"strconv"
 	"strings"
 	"text/template"
@@ -23,7 +22,7 @@ import (
 const (
 	// runtimeDockerfileTmpl Dockerfile template to be used with runtime-image, it uses Build
 	// attributes directly as template input.
-	runtimeDockerfileTmpl = `FROM {{ .Spec.Output.Image }} as builder
+	runtimeDockerfileTmpl = `FROM $(params.shp-output-image) as builder
 
 FROM {{ .Spec.Runtime.Base.Image }}
 
@@ -63,9 +62,6 @@ ENTRYPOINT [ {{ renderEntrypoint .Spec.Runtime.Entrypoint }} ]
 {{- end -}}
 `
 
-	// workspaceDir common workspace directory, where the source code is located.
-	workspaceDir = "/workspace/source"
-
 	// runtimeDockerfile runtime Dockerfile file name.
 	runtimeDockerfile = "Dockerfile.runtime"
 
@@ -76,9 +72,6 @@ ENTRYPOINT [ {{ renderEntrypoint .Spec.Runtime.Entrypoint }} ]
 // rootUserID root's UID
 var rootUserID = int64(0)
 
-// runtimeDockerfilePath path to runtime Dockerfile on workspace directory.
-var runtimeDockerfilePath = path.Join(workspaceDir, runtimeDockerfile)
-
 // renderUserAndGroup based on informed user, returns it joined by colon (":"), or empty string when
 // nil or user not informed. Follows the rules for Dockerfile's USER and "COPY --chown" directives.
 func renderUserAndGroup(user *buildv1alpha1.User) string {
@@ -132,9 +125,8 @@ func renderRuntimeDockerfile(b *buildv1alpha1.Build) (*bytes.Buffer, error) {
 
 // runtimeDockerfileTransformations search and replace special variables `$()` in informed string.
 func runtimeDockerfileTransformations(b *buildv1alpha1.Build, str string) string {
-	contextDir := getContextDir(b)
 	transformations := map[string]string{
-		"$(workspace)": path.Join(workspaceDir, contextDir),
+		"$(workspace)": fmt.Sprintf("$(params.%s%s)", prefixParamsResults, paramSourceContext),
 	}
 	for k, v := range transformations {
 		str = strings.ReplaceAll(str, k, v)
@@ -142,15 +134,6 @@ func runtimeDockerfileTransformations(b *buildv1alpha1.Build, str string) string
 	return str
 }
 
-// getContextDir retrieve contextDir from Source, or empty string.
-func getContextDir(b *buildv1alpha1.Build) string {
-	contextDir := ""
-	if b != nil && b.Spec.Source.ContextDir != nil {
-		contextDir = path.Join(workspaceDir, *b.Spec.Source.ContextDir)
-	}
-	return contextDir
-}
-
 // runtimeDockerfileStep trigger the rendering of Dockerfile.runtime, and use this input as a
 // build-step to create a new file.
 func runtimeDockerfileStep(b *buildv1alpha1.Build) (*v1beta1.Step, error) {
@@ -174,12 +157,12 @@ func runtimeDockerfileStep(b *buildv1alpha1.Build) (*v1beta1.Step, error) {
 		SecurityContext: &v1.SecurityContext{
 			RunAsUser: &rootUserID,
 		},
-		WorkingDir: workspaceDir,
+		WorkingDir: fmt.Sprintf("$(params.%s%s)", prefixParamsResults, paramSourceRoot),
 		Command:    []string{"/bin/sh"},
 		Args: []string{
 			"-x",
 			"-c",
-			fmt.Sprintf("echo '%s' >%s", dockerfileTransformed, runtimeDockerfilePath),
+			fmt.Sprintf("echo '%s' >%s", dockerfileTransformed, runtimeDockerfile),
 		},
 	}
 	return &v1beta1.Step{Container: container}, nil
@@ -187,11 +170,10 @@ func runtimeDockerfileStep(b *buildv1alpha1.Build) (*v1beta1.Step, error) {
 
 // runtimeBuildAndPushStep returns a Task step to build the Dockerfile.runtime with kaniko.
 func runtimeBuildAndPushStep(b *buildv1alpha1.Build, kanikoImage string) *v1beta1.Step {
-	contextDir := getContextDir(b)
 	container := v1.Container{
 		Name:       "kaniko-build-and-push",
 		Image:      kanikoImage,
-		WorkingDir: workspaceDir,
+		WorkingDir: fmt.Sprintf("$(params.%s%s)", prefixParamsResults, paramSourceRoot),
 		SecurityContext: &v1.SecurityContext{
 			RunAsUser: &rootUserID,
 			Capabilities: &v1.Capabilities{
@@ -215,8 +197,7 @@ func runtimeBuildAndPushStep(b *buildv1alpha1.Build, kanikoImage string) *v1beta
 		Args: []string{
 			"--skip-tls-verify=true",
 			fmt.Sprintf("--dockerfile=%s", runtimeDockerfile),
-			fmt.Sprintf("--context=%x", path.Join(workspaceDir, contextDir)),
-			fmt.Sprintf("--destination=%s", b.Spec.Output.Image),
+			fmt.Sprintf("--destination=$(params.%s%s)", prefixParamsResults, paramOutputImage),
 			"--snapshotMode=redo",
 			"--oci-layout-path=/workspace/output/image",
 		},
diff --git a/pkg/reconciler/buildrun/resources/taskrun.go b/pkg/reconciler/buildrun/resources/taskrun.go
index 43f998c3..e09cccb6 100644
--- a/pkg/reconciler/buildrun/resources/taskrun.go
+++ b/pkg/reconciler/buildrun/resources/taskrun.go
@@ -6,6 +6,7 @@ package resources
 
 import (
 	"fmt"
+	"path"
 	"strconv"
 	"strings"
 
@@ -20,10 +21,16 @@ import (
 )
 
 const (
+	prefixParamsResults = "shp-"
+
+	paramOutputImage   = "output-image"
+	paramSourceRoot    = "source-root"
+	paramSourceContext = "source-context"
+
 	inputSourceResourceName = "source"
 	inputGitSourceURL       = "url"
 	inputGitSourceRevision  = "revision"
-	inputParamBuilder  = "BUILDER_IMAGE"
+	inputParamBuilder       = "BUILDER_IMAGE"
 	inputParamDockerfile    = "DOCKERFILE"
 	inputParamContextDir    = "CONTEXT_DIR"
 	outputImageResourceName = "image"
@@ -35,9 +42,14 @@ const (
 func getStringTransformations(fullText string) string {
 
 	stringTransformations := map[string]string{
-		"$(build.output.image)":      "$(outputs.resources.image.url)",
-		"$(build.builder.image)":     fmt.Sprintf("$(inputs.params.%s)", inputParamBuilder),
-		"$(build.dockerfile)":        fmt.Sprintf("$(inputs.params.%s)", inputParamDockerfile),
+		// this will be removed, build strategy author should use $(params.shp-output-image) directly
+		"$(build.output.image)": fmt.Sprintf("$(params.%s%s)", prefixParamsResults, paramOutputImage),
+
+		"$(build.builder.image)": fmt.Sprintf("$(inputs.params.%s)", inputParamBuilder),
+		"$(build.dockerfile)":    fmt.Sprintf("$(inputs.params.%s)", inputParamDockerfile),
+
+		// this will be removed, build strategy author should use $(params.shp-source-context); it is still needed by the ko build
+		// strategy that mis-uses this setting to store the path to the main package; requires strategy parameter support to get rid
 		"$(build.source.contextDir)": fmt.Sprintf("$(inputs.params.%s)", inputParamContextDir),
 	}
 
@@ -94,6 +106,21 @@ func GenerateTaskSpec(
 					StringVal: ".",
 				},
 			},
+			{
+				Name:        prefixParamsResults + paramOutputImage,
+				Description: "The URL of the image that the build produces",
+				Type:        taskv1.ParamTypeString,
+			},
+			{
+				Name:        prefixParamsResults + paramSourceContext,
+				Description: "The context directory inside the source directory",
+				Type:        taskv1.ParamTypeString,
+			},
+			{
+				Name:        prefixParamsResults + paramSourceRoot,
+				Description: "The source directory",
+				Type:        taskv1.ParamTypeString,
+			},
 		},
 		Steps: []v1beta1.Step{},
 	}
@@ -195,11 +222,11 @@ func GenerateTaskRun(
 	}
 
 	// retrieve expected imageURL form build or buildRun
-	var Image string
+	var image string
 	if buildRun.Spec.Output != nil {
-		Image = buildRun.Spec.Output.Image
+		image = buildRun.Spec.Output.Image
 	} else {
-		Image = build.Spec.Output.Image
+		image = build.Spec.Output.Image
 	}
 
 	taskSpec, err := GenerateTaskSpec(cfg, build, buildRun, strategy.GetBuildSteps())
@@ -251,7 +278,7 @@ func GenerateTaskRun(
 								Params: []taskv1.ResourceParam{
 									{
 										Name:  outputImageResourceURL,
-										Value: Image,
+										Value: image,
 									},
 								},
 							},
@@ -279,9 +306,25 @@ func GenerateTaskRun(
 
 	expectedTaskRun.Spec.Timeout = effectiveTimeout(build, buildRun)
 
-	var inputParams []v1beta1.Param
+	params := []v1beta1.Param{
+		{
+			// shp-output-image
+			Name: prefixParamsResults + paramOutputImage,
+			Value: v1beta1.ArrayOrString{
+				Type:      v1beta1.ParamTypeString,
+				StringVal: image,
+			},
+		},
+		{
+			Name: prefixParamsResults + paramSourceRoot,
+			Value: v1beta1.ArrayOrString{
+				Type:      v1beta1.ParamTypeString,
+				StringVal: "/workspace/source",
+			},
+		},
+	}
 	if build.Spec.Builder != nil {
-		inputParams = append(inputParams, v1beta1.Param{
+		params = append(params, v1beta1.Param{
 			Name: inputParamBuilder,
 			Value: v1beta1.ArrayOrString{
 				Type:      v1beta1.ParamTypeString,
@@ -290,7 +333,7 @@ func GenerateTaskRun(
 		})
 	}
 	if build.Spec.Dockerfile != nil {
-		inputParams = append(inputParams, v1beta1.Param{
+		params = append(params, v1beta1.Param{
 			Name: inputParamDockerfile,
 			Value: v1beta1.ArrayOrString{
 				Type:      v1beta1.ParamTypeString,
@@ -299,16 +342,31 @@ func GenerateTaskRun(
 		})
 	}
 	if build.Spec.Source.ContextDir != nil {
-		inputParams = append(inputParams, v1beta1.Param{
+		params = append(params, v1beta1.Param{
 			Name: inputParamContextDir,
 			Value: v1beta1.ArrayOrString{
 				Type:      v1beta1.ParamTypeString,
 				StringVal: *build.Spec.Source.ContextDir,
 			},
 		})
+		params = append(params, v1beta1.Param{
+			Name: prefixParamsResults + paramSourceContext,
+			Value: v1beta1.ArrayOrString{
+				Type:      v1beta1.ParamTypeString,
+				StringVal: path.Join("/workspace/source", *build.Spec.Source.ContextDir),
+			},
+		})
+	} else {
+		params = append(params, v1beta1.Param{
+			Name: prefixParamsResults + paramSourceContext,
+			Value: v1beta1.ArrayOrString{
+				Type:      v1beta1.ParamTypeString,
+				StringVal: "/workspace/source",
+			},
+		})
 	}
 
-	expectedTaskRun.Spec.Params = inputParams
+	expectedTaskRun.Spec.Params = params
 	return expectedTaskRun, nil
 }
 
diff --git a/samples/buildstrategy/buildah/buildstrategy_buildah_cr.yaml b/samples/buildstrategy/buildah/buildstrategy_buildah_cr.yaml
index d09ca4d7..b8a8d41a 100644
--- a/samples/buildstrategy/buildah/buildstrategy_buildah_cr.yaml
+++ b/samples/buildstrategy/buildah/buildstrategy_buildah_cr.yaml
@@ -7,16 +7,16 @@ spec:
   buildSteps:
     - name: buildah-bud
       image: quay.io/buildah/stable:latest
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         privileged: true
       command:
         - /usr/bin/buildah
       args:
         - bud
-        - --tag=$(build.output.image)
+        - --tag=$(params.shp-output-image)
         - --file=$(build.dockerfile)
-        - $(build.source.contextDir)
+        - $(params.shp-source-context)
       resources:
         limits:
           cpu: 500m
@@ -36,8 +36,8 @@ spec:
       args:
         - push
         - --tls-verify=false
-        - $(build.output.image)
-        - docker://$(build.output.image)
+        - $(params.shp-output-image)
+        - docker://$(params.shp-output-image)
       resources:
         limits:
           cpu: 500m
diff --git a/samples/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml b/samples/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml
index f1311792..f54fbb72 100644
--- a/samples/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml
+++ b/samples/buildstrategy/buildkit/buildstrategy_buildkit_cr.yaml
@@ -28,7 +28,7 @@ spec:
           chown -R 1000:1000 /tekton/home
     - name: build-and-push
       image: moby/buildkit:master-rootless
-      workingDir: /workspace/source/
+      workingDir: $(params.shp-source-root)
       env:
       - name: DOCKER_CONFIG
         value: /tekton/home/.docker
@@ -42,12 +42,12 @@ spec:
         - --progress=plain
         - --frontend=dockerfile.v0
         - --local
-        - context=/workspace/source/$(build.source.contextDir)
+        - context=$(params.shp-source-context)
         - --local
-        - dockerfile=/workspace/source/$(build.dockerfile)
+        - dockerfile=$(params.shp-source-root)/$(build.dockerfile)
         - --output
-        - type=image,name=$(build.output.image),push=true,registry.insecure=false
+        - type=image,name=$(params.shp-output-image),push=true,registry.insecure=false
         - --export-cache
         - type=inline
         - --import-cache
-        - type=registry,ref=$(build.output.image)
+        - type=registry,ref=$(params.shp-output-image)
diff --git a/samples/buildstrategy/buildkit/buildstrategy_buildkit_insecure_cr.yaml b/samples/buildstrategy/buildkit/buildstrategy_buildkit_insecure_cr.yaml
index 8759ea20..0bb8c151 100644
--- a/samples/buildstrategy/buildkit/buildstrategy_buildkit_insecure_cr.yaml
+++ b/samples/buildstrategy/buildkit/buildstrategy_buildkit_insecure_cr.yaml
@@ -28,7 +28,7 @@ spec:
           chown -R 1000:1000 /tekton/home
     - name: build-and-push
       image: moby/buildkit:master-rootless
-      workingDir: /workspace/source/
+      workingDir: $(params.shp-source-root)
       env:
       - name: DOCKER_CONFIG
         value: /tekton/home/.docker
@@ -42,12 +42,12 @@ spec:
         - --progress=plain
         - --frontend=dockerfile.v0
         - --local
-        - context=/workspace/source/$(build.source.contextDir)
+        - context=$(params.shp-source-context)
         - --local
-        - dockerfile=/workspace/source/$(build.dockerfile)
+        - dockerfile=$(params.shp-source-root)/$(build.dockerfile)
         - --output
-        - type=image,name=$(build.output.image),push=true,registry.insecure=true
+        - type=image,name=$(params.shp-output-image),push=true,registry.insecure=true
         - --export-cache
         - type=inline
         - --import-cache
-        - type=registry,ref=$(build.output.image)
+        - type=registry,ref=$(params.shp-output-image)
diff --git a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_cr.yaml b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_cr.yaml
index 542838c4..c927c3fb 100644
--- a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_cr.yaml
+++ b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_cr.yaml
@@ -17,7 +17,7 @@ spec:
       args:
         - -c
         - >
-          chown -R "1000:1000" /workspace/source &&
+          chown -R "1000:1000" "$(params.shp-source-root)" &&
           chown -R "1000:1000" /tekton/home &&
           chown -R "1000:1000" /cache &&
           chown -R "1000:1000" /layers
@@ -41,10 +41,10 @@ spec:
       command:
         - /cnb/lifecycle/creator
       args:
-        - -app=/workspace/source/$(build.source.contextDir)
+        - -app=$(params.shp-source-context)
         - -cache-dir=/cache
         - -layers=/layers
-        - $(build.output.image)
+        - $(params.shp-output-image)
       resources:
         limits:
           cpu: 500m
diff --git a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_namespaced_cr.yaml b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_namespaced_cr.yaml
index 922edbec..87a394da 100644
--- a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_namespaced_cr.yaml
+++ b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3-heroku_namespaced_cr.yaml
@@ -17,7 +17,7 @@ spec:
       args:
         - -c
         - >
-          chown -R "1000:1000" /workspace/source &&
+          chown -R "1000:1000" "$(params.shp-source-root)" &&
           chown -R "1000:1000" /tekton/home &&
           chown -R "1000:1000" /cache &&
           chown -R "1000:1000" /layers
@@ -41,10 +41,10 @@ spec:
       command:
         - /cnb/lifecycle/creator
       args:
-        - -app=/workspace/source/$(build.source.contextDir)
+        - -app=$(params.shp-source-context)
         - -cache-dir=/cache
         - -layers=/layers
-        - $(build.output.image)
+        - $(params.shp-output-image)
       resources:
         limits:
           cpu: 500m
diff --git a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_cr.yaml b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_cr.yaml
index fd1a9f79..848669f2 100644
--- a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_cr.yaml
+++ b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_cr.yaml
@@ -17,7 +17,7 @@ spec:
       args:
         - -c
         - >
-          chown -R "1000:1000" /workspace/source &&
+          chown -R "1000:1000" "$(params.shp-source-root)" &&
           chown -R "1000:1000" /tekton/home &&
           chown -R "1000:1000" /cache &&
           chown -R "1000:1000" /layers
@@ -41,10 +41,10 @@ spec:
       command:
         - /cnb/lifecycle/creator
       args:
-        - -app=/workspace/source/$(build.source.contextDir)
+        - -app=$(params.shp-source-context)
         - -cache-dir=/cache
         - -layers=/layers
-        - $(build.output.image)
+        - $(params.shp-output-image)
       resources:
         limits:
           cpu: 500m
diff --git a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_namespaced_cr.yaml b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_namespaced_cr.yaml
index 8235890d..e9383090 100644
--- a/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_namespaced_cr.yaml
+++ b/samples/buildstrategy/buildpacks-v3/buildstrategy_buildpacks-v3_namespaced_cr.yaml
@@ -17,7 +17,7 @@ spec:
       args:
         - -c
         - >
-          chown -R "1000:1000" /workspace/source &&
+          chown -R "1000:1000" "$(params.shp-source-root)" &&
           chown -R "1000:1000" /tekton/home &&
           chown -R "1000:1000" /cache &&
           chown -R "1000:1000" /layers
@@ -41,10 +41,10 @@ spec:
       command:
         - /cnb/lifecycle/creator
       args:
-        - -app=/workspace/source/$(build.source.contextDir)
+        - -app=$(params.shp-source-context)
         - -cache-dir=/cache
         - -layers=/layers
-        - $(build.output.image)
+        - $(params.shp-output-image)
       resources:
         limits:
           cpu: 500m
diff --git a/samples/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml b/samples/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml
index cfcbfa3f..850bbc90 100644
--- a/samples/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml
+++ b/samples/buildstrategy/kaniko/buildstrategy_kaniko_cr.yaml
@@ -7,7 +7,7 @@ spec:
   buildSteps:
     - name: build-and-push
       image: gcr.io/kaniko-project/executor:v1.5.2
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         runAsUser: 0
         capabilities:
@@ -31,8 +31,8 @@ spec:
       args:
         - --skip-tls-verify=true
         - --dockerfile=$(build.dockerfile)
-        - --context=/workspace/source/$(build.source.contextDir)
-        - --destination=$(build.output.image)
+        - --context=$(params.shp-source-context)
+        - --destination=$(params.shp-output-image)
         - --oci-layout-path=/workspace/output/image
         - --snapshotMode=redo
         - --push-retry=3
diff --git a/samples/buildstrategy/ko/buildstrategy_ko_cr.yaml b/samples/buildstrategy/ko/buildstrategy_ko_cr.yaml
index cfcdae4f..5179350a 100644
--- a/samples/buildstrategy/ko/buildstrategy_ko_cr.yaml
+++ b/samples/buildstrategy/ko/buildstrategy_ko_cr.yaml
@@ -20,7 +20,7 @@ spec:
           set -euo pipefail
 
           chown -R 1000:1000 /workspace/output
-          chown -R 1000:1000 /workspace/source
+          chown -R 1000:1000 "$(params.shp-source-root)"
           chown -R 1000:1000 /tekton/home
       resources:
         limits:
@@ -31,7 +31,7 @@ spec:
           memory: 128Mi
     - name: build-and-push
       image: golang:1.15
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         runAsUser: 1000
         runAsGroup: 1000
@@ -51,7 +51,7 @@ spec:
           # - a URL with a tag but without a port: registry/image:tag
           # - a URL with both a tag and a port: registry:port/image:tag
 
-          IMAGE=$(build.output.image)
+          IMAGE=$(params.shp-output-image)
 
           REPO=
           TAG=
diff --git a/samples/buildstrategy/source-to-image/buildstrategy_source-to-image-redhat_cr.yaml b/samples/buildstrategy/source-to-image/buildstrategy_source-to-image-redhat_cr.yaml
index 9fb99a3a..5e76eb16 100644
--- a/samples/buildstrategy/source-to-image/buildstrategy_source-to-image-redhat_cr.yaml
+++ b/samples/buildstrategy/source-to-image/buildstrategy_source-to-image-redhat_cr.yaml
@@ -7,12 +7,12 @@ spec:
   buildSteps:
     - name: s2i-generate
       image: registry.redhat.io/ocp-tools-43-tech-preview/source-to-image-rhel8:latest
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       args:
         - build
         - .
         - $(build.builder.image)
-        - $(build.output.image)
+        - $(params.shp-output-image)
         - --as-dockerfile=/s2i/Dockerfile
       volumeMounts:
         - name: s2i
@@ -26,7 +26,7 @@ spec:
         - /usr/bin/buildah
       args:
         - bud
-        - --tag=$(build.output.image)
+        - --tag=$(params.shp-output-image)
       volumeMounts:
         - name: s2i
           mountPath: /s2i
@@ -41,7 +41,7 @@ spec:
       args:
         - push
         - --tls-verify=false
-        - docker://$(build.output.image)
+        - docker://$(params.shp-output-image)
       volumeMounts:
         - name: buildah-images
           mountPath: /var/lib/containers/storage
diff --git a/samples/buildstrategy/source-to-image/buildstrategy_source-to-image_cr.yaml b/samples/buildstrategy/source-to-image/buildstrategy_source-to-image_cr.yaml
index 8df39335..30c5ce59 100644
--- a/samples/buildstrategy/source-to-image/buildstrategy_source-to-image_cr.yaml
+++ b/samples/buildstrategy/source-to-image/buildstrategy_source-to-image_cr.yaml
@@ -16,12 +16,12 @@ spec:
       volumeMounts:
         - mountPath: /gen-source
           name: gen-source
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
     - args:
         - '--skip-tls-verify=true'
         - '--dockerfile=/gen-source/Dockerfile.gen'
         - '--context=/gen-source'
-        - '--destination=$(build.output.image)'
+        - '--destination=$(params.shp-output-image)'
         - '--oci-layout-path=/workspace/output/image'
         - '--snapshotMode=redo'
         - '--push-retry=3'
diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token.go
index b83f16a4..addc9109 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/adal/token.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/adal/token.go
@@ -30,6 +30,7 @@ import (
 	"net/http"
 	"net/url"
 	"os"
+	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -76,6 +77,15 @@ const (
 
 	// the API version to use for the App Service MSI endpoint
 	appServiceAPIVersion = "2017-09-01"
+
+	// secret header used when authenticating against app service MSI endpoint
+	secretHeader = "Secret"
+
+	// the format for expires_on in UTC with AM/PM
+	expiresOnDateFormatPM = "1/2/2006 15:04:05 PM +00:00"
+
+	// the format for expires_on in UTC without AM/PM
+	expiresOnDateFormat = "1/2/2006 15:04:05 +00:00"
 )
 
 // OAuthTokenProvider is an interface which should be implemented by an access token retriever
@@ -727,14 +737,16 @@ func newServicePrincipalTokenFromMSI(msiEndpoint, resource string, userAssignedI
 
 	v := url.Values{}
 	v.Set("resource", resource)
-	// App Service MSI currently only supports token API version 2017-09-01
-	if isAppService() {
+	// we only support token API version 2017-09-01 for app services
+	clientIDParam := "client_id"
+	if isASEEndpoint(*msiEndpointURL) {
 		v.Set("api-version", appServiceAPIVersion)
+		clientIDParam = "clientid"
 	} else {
 		v.Set("api-version", msiAPIVersion)
 	}
 	if userAssignedID != nil {
-		v.Set("client_id", *userAssignedID)
+		v.Set(clientIDParam, *userAssignedID)
 	}
 	if identityResourceID != nil {
 		v.Set("mi_res_id", *identityResourceID)
@@ -892,7 +904,6 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
 		spt.inner.Token = *token
 		return spt.InvokeRefreshCallbacks(spt.inner.Token)
 	}
-
 	req, err := http.NewRequest(http.MethodPost, spt.inner.OauthConfig.TokenEndpoint.String(), nil)
 	if err != nil {
 		return fmt.Errorf("adal: Failed to build the refresh request. Error = '%v'", err)
@@ -901,7 +912,7 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
 	// Add header when runtime is on App Service or Functions
 	if isASEEndpoint(spt.inner.OauthConfig.TokenEndpoint) {
 		asMSISecret, _ := os.LookupEnv(asMSISecretEnv)
-		req.Header.Add("Secret", asMSISecret)
+		req.Header.Add(secretHeader, asMSISecret)
 	}
 	req = req.WithContext(ctx)
 	if !isIMDS(spt.inner.OauthConfig.TokenEndpoint) {
@@ -937,7 +948,10 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
 
 	if _, ok := spt.inner.Secret.(*ServicePrincipalMSISecret); ok {
 		req.Method = http.MethodGet
-		req.Header.Set(metadataHeader, "true")
+		// the metadata header isn't applicable for ASE
+		if !isASEEndpoint(spt.inner.OauthConfig.TokenEndpoint) {
+			req.Header.Set(metadataHeader, "true")
+		}
 	}
 
 	var resp *http.Response
@@ -964,9 +978,9 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
 
 	if resp.StatusCode != http.StatusOK {
 		if err != nil {
-			return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Failed reading response body: %v", resp.StatusCode, err), resp)
+			return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Failed reading response body: %v Endpoint %s", resp.StatusCode, err, req.URL.String()), resp)
 		}
-		return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Response body: %s", resp.StatusCode, string(rb)), resp)
+		return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Response body: %s Endpoint %s", resp.StatusCode, string(rb), req.URL.String()), resp)
 	}
 
 	// for the following error cases don't return a TokenRefreshError.  the operation succeeded
@@ -979,15 +993,60 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
 	if len(strings.Trim(string(rb), " ")) == 0 {
 		return fmt.Errorf("adal: Empty service principal token received during refresh")
 	}
-	var token Token
+	token := struct {
+		AccessToken  string `json:"access_token"`
+		RefreshToken string `json:"refresh_token"`
+
+		// AAD returns expires_in as a string, ADFS returns it as an int
+		ExpiresIn json.Number `json:"expires_in"`
+		// expires_on can be in two formats, a UTC time stamp or the number of seconds.
+		ExpiresOn string      `json:"expires_on"`
+		NotBefore json.Number `json:"not_before"`
+
+		Resource string `json:"resource"`
+		Type     string `json:"token_type"`
+	}{}
+	// return a TokenRefreshError in the follow error cases as the token is in an unexpected format
 	err = json.Unmarshal(rb, &token)
 	if err != nil {
-		return fmt.Errorf("adal: Failed to unmarshal the service principal token during refresh. Error = '%v' JSON = '%s'", err, string(rb))
+		return newTokenRefreshError(fmt.Sprintf("adal: Failed to unmarshal the service principal token during refresh. Error = '%v' JSON = '%s'", err, string(rb)), resp)
+	}
+	expiresOn := json.Number("")
+	// ADFS doesn't include the expires_on field
+	if token.ExpiresOn != "" {
+		if expiresOn, err = parseExpiresOn(token.ExpiresOn); err != nil {
+			return newTokenRefreshError(fmt.Sprintf("adal: failed to parse expires_on: %v value '%s'", err, token.ExpiresOn), resp)
+		}
+	}
+	spt.inner.Token.AccessToken = token.AccessToken
+	spt.inner.Token.RefreshToken = token.RefreshToken
+	spt.inner.Token.ExpiresIn = token.ExpiresIn
+	spt.inner.Token.ExpiresOn = expiresOn
+	spt.inner.Token.NotBefore = token.NotBefore
+	spt.inner.Token.Resource = token.Resource
+	spt.inner.Token.Type = token.Type
+
+	return spt.InvokeRefreshCallbacks(spt.inner.Token)
+}
+
+// converts expires_on to the number of seconds
+func parseExpiresOn(s string) (json.Number, error) {
+	// convert the expiration date to the number of seconds from now
+	timeToDuration := func(t time.Time) json.Number {
+		dur := t.Sub(time.Now().UTC())
+		return json.Number(strconv.FormatInt(int64(dur.Round(time.Second).Seconds()), 10))
+	}
+	if _, err := strconv.ParseInt(s, 10, 64); err == nil {
+		// this is the number of seconds case, no conversion required
+		return json.Number(s), nil
+	} else if eo, err := time.Parse(expiresOnDateFormatPM, s); err == nil {
+		return timeToDuration(eo), nil
+	} else if eo, err := time.Parse(expiresOnDateFormat, s); err == nil {
+		return timeToDuration(eo), nil
+	} else {
+		// unknown format
+		return json.Number(""), err
 	}
-
-	spt.inner.Token = token
-
-	return spt.InvokeRefreshCallbacks(token)
 }
 
 // retry logic specific to retrieving a token from the IMDS endpoint
@@ -1118,68 +1177,77 @@ func (mt *MultiTenantServicePrincipalToken) AuxiliaryOAuthTokens() []string {
 	return tokens
 }
 
-// EnsureFreshWithContext will refresh the token if it will expire within the refresh window (as set by
-// RefreshWithin) and autoRefresh flag is on.  This method is safe for concurrent use.
-func (mt *MultiTenantServicePrincipalToken) EnsureFreshWithContext(ctx context.Context) error {
-	if err := mt.PrimaryToken.EnsureFreshWithContext(ctx); err != nil {
-		return fmt.Errorf("failed to refresh primary token: %v", err)
+// NewMultiTenantServicePrincipalToken creates a new MultiTenantServicePrincipalToken with the specified credentials and resource.
+func NewMultiTenantServicePrincipalToken(multiTenantCfg MultiTenantOAuthConfig, clientID string, secret string, resource string) (*MultiTenantServicePrincipalToken, error) {
+	if err := validateStringParam(clientID, "clientID"); err != nil {
+		return nil, err
 	}
-	for _, aux := range mt.AuxiliaryTokens {
-		if err := aux.EnsureFreshWithContext(ctx); err != nil {
-			return fmt.Errorf("failed to refresh auxiliary token: %v", err)
-		}
+	if err := validateStringParam(secret, "secret"); err != nil {
+		return nil, err
 	}
-	return nil
-}
-
-// RefreshWithContext obtains a fresh token for the Service Principal.
-func (mt *MultiTenantServicePrincipalToken) RefreshWithContext(ctx context.Context) error {
-	if err := mt.PrimaryToken.RefreshWithContext(ctx); err != nil {
-		return fmt.Errorf("failed to refresh primary token: %v", err)
+	if err := validateStringParam(resource, "resource"); err != nil {
+		return nil, err
 	}
-	for _, aux := range mt.AuxiliaryTokens {
-		if err := aux.RefreshWithContext(ctx); err != nil {
-			return fmt.Errorf("failed to refresh auxiliary token: %v", err)
-		}
+	auxTenants := multiTenantCfg.AuxiliaryTenants()
+	m := MultiTenantServicePrincipalToken{
+		AuxiliaryTokens: make([]*ServicePrincipalToken, len(auxTenants)),
 	}
-	return nil
-}
-
-// RefreshExchangeWithContext refreshes the token, but for a different resource.
-func (mt *MultiTenantServicePrincipalToken) RefreshExchangeWithContext(ctx context.Context, resource string) error {
-	if err := mt.PrimaryToken.RefreshExchangeWithContext(ctx, resource); err != nil {
-		return fmt.Errorf("failed to refresh primary token: %v", err)
+	primary, err := NewServicePrincipalToken(*multiTenantCfg.PrimaryTenant(), clientID, secret, resource)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create SPT for primary tenant: %v", err)
 	}
-	for _, aux := range mt.AuxiliaryTokens {
-		if err := aux.RefreshExchangeWithContext(ctx, resource); err != nil {
-			return fmt.Errorf("failed to refresh auxiliary token: %v", err)
+	m.PrimaryToken = primary
+	for i := range auxTenants {
+		aux, err := NewServicePrincipalToken(*auxTenants[i], clientID, secret, resource)
+		if err != nil {
+			return nil, fmt.Errorf("failed to create SPT for auxiliary tenant: %v", err)
 		}
+		m.AuxiliaryTokens[i] = aux
 	}
-	return nil
+	return &m, nil
 }
 
-// NewMultiTenantServicePrincipalToken creates a new MultiTenantServicePrincipalToken with the specified credentials and resource.
-func NewMultiTenantServicePrincipalToken(multiTenantCfg MultiTenantOAuthConfig, clientID string, secret string, resource string) (*MultiTenantServicePrincipalToken, error) {
+// NewMultiTenantServicePrincipalTokenFromCertificate creates a new MultiTenantServicePrincipalToken with the specified certificate credentials and resource.
+func NewMultiTenantServicePrincipalTokenFromCertificate(multiTenantCfg MultiTenantOAuthConfig, clientID string, certificate *x509.Certificate, privateKey *rsa.PrivateKey, resource string) (*MultiTenantServicePrincipalToken, error) {
 	if err := validateStringParam(clientID, "clientID"); err != nil {
 		return nil, err
 	}
-	if err := validateStringParam(secret, "secret"); err != nil {
-		return nil, err
-	}
 	if err := validateStringParam(resource, "resource"); err != nil {
 		return nil, err
 	}
+	if certificate == nil {
+		return nil, fmt.Errorf("parameter 'certificate' cannot be nil")
+	}
+	if privateKey == nil {
+		return nil, fmt.Errorf("parameter 'privateKey' cannot be nil")
+	}
 	auxTenants := multiTenantCfg.AuxiliaryTenants()
 	m := MultiTenantServicePrincipalToken{
 		AuxiliaryTokens: make([]*ServicePrincipalToken, len(auxTenants)),
 	}
-	primary, err := NewServicePrincipalToken(*multiTenantCfg.PrimaryTenant(), clientID, secret, resource)
+	primary, err := NewServicePrincipalTokenWithSecret(
+		*multiTenantCfg.PrimaryTenant(),
+		clientID,
+		resource,
+		&ServicePrincipalCertificateSecret{
+			PrivateKey:  privateKey,
+			Certificate: certificate,
+		},
+	)
 	if err != nil {
 		return nil, fmt.Errorf("failed to create SPT for primary tenant: %v", err)
 	}
 	m.PrimaryToken = primary
 	for i := range auxTenants {
-		aux, err := NewServicePrincipalToken(*auxTenants[i], clientID, secret, resource)
+		aux, err := NewServicePrincipalTokenWithSecret(
+			*auxTenants[i],
+			clientID,
+			resource,
+			&ServicePrincipalCertificateSecret{
+				PrivateKey:  privateKey,
+				Certificate: certificate,
+			},
+		)
 		if err != nil {
 			return nil, fmt.Errorf("failed to create SPT for auxiliary tenant: %v", err)
 		}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token_1.13.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token_1.13.go
index 45e01a7e..54b4defe 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/adal/token_1.13.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/adal/token_1.13.go
@@ -18,6 +18,7 @@ package adal
 
 import (
 	"context"
+	"fmt"
 	"net/http"
 	"time"
 )
@@ -34,3 +35,43 @@ func getMSIEndpoint(ctx context.Context, sender Sender) (*http.Response, error)
 	req.URL.RawQuery = q.Encode()
 	return sender.Do(req)
 }
+
+// EnsureFreshWithContext will refresh the token if it will expire within the refresh window (as set by
+// RefreshWithin) and autoRefresh flag is on.  This method is safe for concurrent use.
+func (mt *MultiTenantServicePrincipalToken) EnsureFreshWithContext(ctx context.Context) error {
+	if err := mt.PrimaryToken.EnsureFreshWithContext(ctx); err != nil {
+		return fmt.Errorf("failed to refresh primary token: %w", err)
+	}
+	for _, aux := range mt.AuxiliaryTokens {
+		if err := aux.EnsureFreshWithContext(ctx); err != nil {
+			return fmt.Errorf("failed to refresh auxiliary token: %w", err)
+		}
+	}
+	return nil
+}
+
+// RefreshWithContext obtains a fresh token for the Service Principal.
+func (mt *MultiTenantServicePrincipalToken) RefreshWithContext(ctx context.Context) error {
+	if err := mt.PrimaryToken.RefreshWithContext(ctx); err != nil {
+		return fmt.Errorf("failed to refresh primary token: %w", err)
+	}
+	for _, aux := range mt.AuxiliaryTokens {
+		if err := aux.RefreshWithContext(ctx); err != nil {
+			return fmt.Errorf("failed to refresh auxiliary token: %w", err)
+		}
+	}
+	return nil
+}
+
+// RefreshExchangeWithContext refreshes the token, but for a different resource.
+func (mt *MultiTenantServicePrincipalToken) RefreshExchangeWithContext(ctx context.Context, resource string) error {
+	if err := mt.PrimaryToken.RefreshExchangeWithContext(ctx, resource); err != nil {
+		return fmt.Errorf("failed to refresh primary token: %w", err)
+	}
+	for _, aux := range mt.AuxiliaryTokens {
+		if err := aux.RefreshExchangeWithContext(ctx, resource); err != nil {
+			return fmt.Errorf("failed to refresh auxiliary token: %w", err)
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token_legacy.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token_legacy.go
index 6f7ad807..6d73bae1 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/adal/token_legacy.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/adal/token_legacy.go
@@ -34,3 +34,43 @@ func getMSIEndpoint(ctx context.Context, sender Sender) (*http.Response, error)
 	req.URL.RawQuery = q.Encode()
 	return sender.Do(req)
 }
+
+// EnsureFreshWithContext will refresh the token if it will expire within the refresh window (as set by
+// RefreshWithin) and autoRefresh flag is on.  This method is safe for concurrent use.
+func (mt *MultiTenantServicePrincipalToken) EnsureFreshWithContext(ctx context.Context) error {
+	if err := mt.PrimaryToken.EnsureFreshWithContext(ctx); err != nil {
+		return err
+	}
+	for _, aux := range mt.AuxiliaryTokens {
+		if err := aux.EnsureFreshWithContext(ctx); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// RefreshWithContext obtains a fresh token for the Service Principal.
+func (mt *MultiTenantServicePrincipalToken) RefreshWithContext(ctx context.Context) error {
+	if err := mt.PrimaryToken.RefreshWithContext(ctx); err != nil {
+		return err
+	}
+	for _, aux := range mt.AuxiliaryTokens {
+		if err := aux.RefreshWithContext(ctx); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// RefreshExchangeWithContext refreshes the token, but for a different resource.
+func (mt *MultiTenantServicePrincipalToken) RefreshExchangeWithContext(ctx context.Context, resource string) error {
+	if err := mt.PrimaryToken.RefreshExchangeWithContext(ctx, resource); err != nil {
+		return err
+	}
+	for _, aux := range mt.AuxiliaryTokens {
+		if err := aux.RefreshExchangeWithContext(ctx, resource); err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization.go b/vendor/github.com/Azure/go-autorest/autorest/authorization.go
index 15138b64..1226c411 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/authorization.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/authorization.go
@@ -299,18 +299,24 @@ type MultiTenantServicePrincipalTokenAuthorizer interface {
 
 // NewMultiTenantServicePrincipalTokenAuthorizer crates a BearerAuthorizer using the given token provider
 func NewMultiTenantServicePrincipalTokenAuthorizer(tp adal.MultitenantOAuthTokenProvider) MultiTenantServicePrincipalTokenAuthorizer {
-	return &multiTenantSPTAuthorizer{tp: tp}
+	return NewMultiTenantBearerAuthorizer(tp)
 }
 
-type multiTenantSPTAuthorizer struct {
+// MultiTenantBearerAuthorizer implements bearer authorization across multiple tenants.
+type MultiTenantBearerAuthorizer struct {
 	tp adal.MultitenantOAuthTokenProvider
 }
 
+// NewMultiTenantBearerAuthorizer creates a MultiTenantBearerAuthorizer using the given token provider.
+func NewMultiTenantBearerAuthorizer(tp adal.MultitenantOAuthTokenProvider) *MultiTenantBearerAuthorizer {
+	return &MultiTenantBearerAuthorizer{tp: tp}
+}
+
 // WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header using the
 // primary token along with the auxiliary authorization header using the auxiliary tokens.
 //
 // By default, the token will be automatically refreshed through the Refresher interface.
-func (mt multiTenantSPTAuthorizer) WithAuthorization() PrepareDecorator {
+func (mt *MultiTenantBearerAuthorizer) WithAuthorization() PrepareDecorator {
 	return func(p Preparer) Preparer {
 		return PreparerFunc(func(r *http.Request) (*http.Request, error) {
 			r, err := p.Prepare(r)
@@ -340,3 +346,8 @@ func (mt multiTenantSPTAuthorizer) WithAuthorization() PrepareDecorator {
 		})
 	}
 }
+
+// TokenProvider returns the underlying MultitenantOAuthTokenProvider for this authorizer.
+func (mt *MultiTenantBearerAuthorizer) TokenProvider() adal.MultitenantOAuthTokenProvider {
+	return mt.tp
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization_sas.go b/vendor/github.com/Azure/go-autorest/autorest/authorization_sas.go
index 89a659cb..66501493 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/authorization_sas.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/authorization_sas.go
@@ -54,13 +54,12 @@ func (sas *SASTokenAuthorizer) WithAuthorization() PrepareDecorator {
 				return r, err
 			}
 
-			if r.URL.RawQuery != "" {
-				r.URL.RawQuery = fmt.Sprintf("%s&%s", r.URL.RawQuery, sas.sasToken)
-			} else {
+			if r.URL.RawQuery == "" {
 				r.URL.RawQuery = sas.sasToken
+			} else if !strings.Contains(r.URL.RawQuery, sas.sasToken) {
+				r.URL.RawQuery = fmt.Sprintf("%s&%s", r.URL.RawQuery, sas.sasToken)
 			}
 
-			r.RequestURI = r.URL.String()
 			return Prepare(r)
 		})
 	}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization_storage.go b/vendor/github.com/Azure/go-autorest/autorest/authorization_storage.go
index b844a3df..2af5030a 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/authorization_storage.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/authorization_storage.go
@@ -152,6 +152,9 @@ func buildCanonicalizedResource(accountName, uri string, keyType SharedKeyType)
 		// the resource's URI should be encoded exactly as it is in the URI.
 		// -- https://msdn.microsoft.com/en-gb/library/azure/dd179428.aspx
 		cr.WriteString(u.EscapedPath())
+	} else {
+		// a slash is required to indicate the root path
+		cr.WriteString("/")
 	}
 
 	params, err := url.ParseQuery(u.RawQuery)
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go
index 5326f1fd..42e28cf2 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go
@@ -42,6 +42,52 @@ const (
 
 var pollingCodes = [...]int{http.StatusNoContent, http.StatusAccepted, http.StatusCreated, http.StatusOK}
 
+// FutureAPI contains the set of methods on the Future type.
+type FutureAPI interface {
+	// Response returns the last HTTP response.
+	Response() *http.Response
+
+	// Status returns the last status message of the operation.
+	Status() string
+
+	// PollingMethod returns the method used to monitor the status of the asynchronous operation.
+	PollingMethod() PollingMethodType
+
+	// DoneWithContext queries the service to see if the operation has completed.
+	DoneWithContext(context.Context, autorest.Sender) (bool, error)
+
+	// GetPollingDelay returns a duration the application should wait before checking
+	// the status of the asynchronous request and true; this value is returned from
+	// the service via the Retry-After response header.  If the header wasn't returned
+	// then the function returns the zero-value time.Duration and false.
+	GetPollingDelay() (time.Duration, bool)
+
+	// WaitForCompletionRef will return when one of the following conditions is met: the long
+	// running operation has completed, the provided context is cancelled, or the client's
+	// polling duration has been exceeded.  It will retry failed polling attempts based on
+	// the retry value defined in the client up to the maximum retry attempts.
+	// If no deadline is specified in the context then the client.PollingDuration will be
+	// used to determine if a default deadline should be used.
+	// If PollingDuration is greater than zero the value will be used as the context's timeout.
+	// If PollingDuration is zero then no default deadline will be used.
+	WaitForCompletionRef(context.Context, autorest.Client) error
+
+	// MarshalJSON implements the json.Marshaler interface.
+	MarshalJSON() ([]byte, error)
+
+	// MarshalJSON implements the json.Unmarshaler interface.
+	UnmarshalJSON([]byte) error
+
+	// PollingURL returns the URL used for retrieving the status of the long-running operation.
+	PollingURL() string
+
+	// GetResult should be called once polling has completed successfully.
+	// It makes the final GET call to retrieve the resultant payload.
+	GetResult(autorest.Sender) (*http.Response, error)
+}
+
+var _ FutureAPI = (*Future)(nil)
+
 // Future provides a mechanism to access the status and results of an asynchronous request.
 // Since futures are stateful they should be passed by value to avoid race conditions.
 type Future struct {
@@ -413,12 +459,12 @@ func (pt *pollingTrackerBase) updateRawBody() error {
 		if err != nil {
 			return autorest.NewErrorWithError(err, "pollingTrackerBase", "updateRawBody", nil, "failed to read response body")
 		}
+		// put the body back so it's available to other callers
+		pt.resp.Body = ioutil.NopCloser(bytes.NewReader(b))
 		// observed in 204 responses over HTTP/2.0; the content length is -1 but body is empty
 		if len(b) == 0 {
 			return nil
 		}
-		// put the body back so it's available to other callers
-		pt.resp.Body = ioutil.NopCloser(bytes.NewReader(b))
 		if err = json.Unmarshal(b, &pt.rawBody); err != nil {
 			return autorest.NewErrorWithError(err, "pollingTrackerBase", "updateRawBody", nil, "failed to unmarshal response body")
 		}
@@ -466,7 +512,12 @@ func (pt *pollingTrackerBase) updateErrorFromResponse() {
 		re := respErr{}
 		defer pt.resp.Body.Close()
 		var b []byte
-		if b, err = ioutil.ReadAll(pt.resp.Body); err != nil || len(b) == 0 {
+		if b, err = ioutil.ReadAll(pt.resp.Body); err != nil {
+			goto Default
+		}
+		// put the body back so it's available to other callers
+		pt.resp.Body = ioutil.NopCloser(bytes.NewReader(b))
+		if len(b) == 0 {
 			goto Default
 		}
 		if err = json.Unmarshal(b, &re); err != nil {
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go b/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
index 26be936b..0ded76bc 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
@@ -37,6 +37,9 @@ const (
 	// should be included in the response.
 	HeaderReturnClientID = "x-ms-return-client-request-id"
 
+	// HeaderContentType is the type of the content in the HTTP response.
+	HeaderContentType = "Content-Type"
+
 	// HeaderRequestID is the Azure extension header of the service generated request ID returned
 	// in the response.
 	HeaderRequestID = "x-ms-request-id"
@@ -89,54 +92,85 @@ func (se ServiceError) Error() string {
 
 // UnmarshalJSON implements the json.Unmarshaler interface for the ServiceError type.
 func (se *ServiceError) UnmarshalJSON(b []byte) error {
-	// per the OData v4 spec the details field must be an array of JSON objects.
-	// unfortunately not all services adhear to the spec and just return a single
-	// object instead of an array with one object.  so we have to perform some
-	// shenanigans to accommodate both cases.
 	// http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Toc372793091
 
-	type serviceError1 struct {
+	type serviceErrorInternal struct {
 		Code           string                   `json:"code"`
 		Message        string                   `json:"message"`
-		Target         *string                  `json:"target"`
-		Details        []map[string]interface{} `json:"details"`
-		InnerError     map[string]interface{}   `json:"innererror"`
-		AdditionalInfo []map[string]interface{} `json:"additionalInfo"`
+		Target         *string                  `json:"target,omitempty"`
+		AdditionalInfo []map[string]interface{} `json:"additionalInfo,omitempty"`
+		// not all services conform to the OData v4 spec.
+		// the following fields are where we've seen discrepancies
+
+		// spec calls for []map[string]interface{} but have seen map[string]interface{}
+		Details interface{} `json:"details,omitempty"`
+
+		// spec calls for map[string]interface{} but have seen []map[string]interface{} and string
+		InnerError interface{} `json:"innererror,omitempty"`
 	}
 
-	type serviceError2 struct {
-		Code           string                   `json:"code"`
-		Message        string                   `json:"message"`
-		Target         *string                  `json:"target"`
-		Details        map[string]interface{}   `json:"details"`
-		InnerError     map[string]interface{}   `json:"innererror"`
-		AdditionalInfo []map[string]interface{} `json:"additionalInfo"`
+	sei := serviceErrorInternal{}
+	if err := json.Unmarshal(b, &sei); err != nil {
+		return err
 	}
 
-	se1 := serviceError1{}
-	err := json.Unmarshal(b, &se1)
-	if err == nil {
-		se.populate(se1.Code, se1.Message, se1.Target, se1.Details, se1.InnerError, se1.AdditionalInfo)
-		return nil
+	// copy the fields we know to be correct
+	se.AdditionalInfo = sei.AdditionalInfo
+	se.Code = sei.Code
+	se.Message = sei.Message
+	se.Target = sei.Target
+
+	// converts an []interface{} to []map[string]interface{}
+	arrayOfObjs := func(v interface{}) ([]map[string]interface{}, bool) {
+		arrayOf, ok := v.([]interface{})
+		if !ok {
+			return nil, false
+		}
+		final := []map[string]interface{}{}
+		for _, item := range arrayOf {
+			as, ok := item.(map[string]interface{})
+			if !ok {
+				return nil, false
+			}
+			final = append(final, as)
+		}
+		return final, true
 	}
 
-	se2 := serviceError2{}
-	err = json.Unmarshal(b, &se2)
-	if err == nil {
-		se.populate(se2.Code, se2.Message, se2.Target, nil, se2.InnerError, se2.AdditionalInfo)
-		se.Details = append(se.Details, se2.Details)
-		return nil
+	// convert the remaining fields, falling back to raw JSON if necessary
+
+	if c, ok := arrayOfObjs(sei.Details); ok {
+		se.Details = c
+	} else if c, ok := sei.Details.(map[string]interface{}); ok {
+		se.Details = []map[string]interface{}{c}
+	} else if sei.Details != nil {
+		// stuff into Details
+		se.Details = []map[string]interface{}{
+			{"raw": sei.Details},
+		}
 	}
-	return err
-}
 
-func (se *ServiceError) populate(code, message string, target *string, details []map[string]interface{}, inner map[string]interface{}, additional []map[string]interface{}) {
-	se.Code = code
-	se.Message = message
-	se.Target = target
-	se.Details = details
-	se.InnerError = inner
-	se.AdditionalInfo = additional
+	if c, ok := sei.InnerError.(map[string]interface{}); ok {
+		se.InnerError = c
+	} else if c, ok := arrayOfObjs(sei.InnerError); ok {
+		// if there's only one error extract it
+		if len(c) == 1 {
+			se.InnerError = c[0]
+		} else {
+			// multiple errors, stuff them into the value
+			se.InnerError = map[string]interface{}{
+				"multi": c,
+			}
+		}
+	} else if c, ok := sei.InnerError.(string); ok {
+		se.InnerError = map[string]interface{}{"error": c}
+	} else if sei.InnerError != nil {
+		// stuff into InnerError
+		se.InnerError = map[string]interface{}{
+			"raw": sei.InnerError,
+		}
+	}
+	return nil
 }
 
 // RequestError describes an error response returned by Azure service.
@@ -171,6 +205,11 @@ type Resource struct {
 	ResourceName   string
 }
 
+// String function returns a string in form of azureResourceID
+func (r Resource) String() string {
+	return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s/%s/%s", r.SubscriptionID, r.ResourceGroup, r.Provider, r.ResourceType, r.ResourceName)
+}
+
 // ParseResourceID parses a resource ID into a ResourceDetails struct.
 // See https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource#return-value-4.
 func ParseResourceID(resourceID string) (Resource, error) {
@@ -302,16 +341,30 @@ func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator {
 					// Check if error is unwrapped ServiceError
 					decoder := autorest.NewDecoder(encodedAs, bytes.NewReader(b.Bytes()))
 					if err := decoder.Decode(&e.ServiceError); err != nil {
-						return err
+						return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), err)
+					}
+
+					// for example, should the API return the literal value `null` as the response
+					if e.ServiceError == nil {
+						e.ServiceError = &ServiceError{
+							Code:    "Unknown",
+							Message: "Unknown service error",
+							Details: []map[string]interface{}{
+								{
+									"HttpResponse.Body": b.String(),
+								},
+							},
+						}
 					}
 				}
-				if e.ServiceError.Message == "" {
+
+				if e.ServiceError != nil && e.ServiceError.Message == "" {
 					// if we're here it means the returned error wasn't OData v4 compliant.
 					// try to unmarshal the body in hopes of getting something.
 					rawBody := map[string]interface{}{}
 					decoder := autorest.NewDecoder(encodedAs, bytes.NewReader(b.Bytes()))
 					if err := decoder.Decode(&rawBody); err != nil {
-						return err
+						return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), err)
 					}
 
 					e.ServiceError = &ServiceError{
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
index faff9327..9bbc0899 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
@@ -46,6 +46,8 @@ type ResourceIdentifier struct {
 	Batch               string `json:"batch"`
 	OperationalInsights string `json:"operationalInsights"`
 	Storage             string `json:"storage"`
+	Synapse             string `json:"synapse"`
+	ServiceBus          string `json:"serviceBus"`
 }
 
 // Environment represents a set of endpoints for each of Azure's Clouds.
@@ -71,6 +73,8 @@ type Environment struct {
 	ContainerRegistryDNSSuffix   string             `json:"containerRegistryDNSSuffix"`
 	CosmosDBDNSSuffix            string             `json:"cosmosDBDNSSuffix"`
 	TokenAudience                string             `json:"tokenAudience"`
+	APIManagementHostNameSuffix  string             `json:"apiManagementHostNameSuffix"`
+	SynapseEndpointSuffix        string             `json:"synapseEndpointSuffix"`
 	ResourceIdentifiers          ResourceIdentifier `json:"resourceIdentifiers"`
 }
 
@@ -98,6 +102,8 @@ var (
 		ContainerRegistryDNSSuffix:   "azurecr.io",
 		CosmosDBDNSSuffix:            "documents.azure.com",
 		TokenAudience:                "https://management.azure.com/",
+		APIManagementHostNameSuffix:  "azure-api.net",
+		SynapseEndpointSuffix:        "dev.azuresynapse.net",
 		ResourceIdentifiers: ResourceIdentifier{
 			Graph:               "https://graph.windows.net/",
 			KeyVault:            "https://vault.azure.net",
@@ -105,6 +111,8 @@ var (
 			Batch:               "https://batch.core.windows.net/",
 			OperationalInsights: "https://api.loganalytics.io",
 			Storage:             "https://storage.azure.com/",
+			Synapse:             "https://dev.azuresynapse.net",
+			ServiceBus:          "https://servicebus.azure.net/",
 		},
 	}
 
@@ -131,6 +139,8 @@ var (
 		ContainerRegistryDNSSuffix:   "azurecr.us",
 		CosmosDBDNSSuffix:            "documents.azure.us",
 		TokenAudience:                "https://management.usgovcloudapi.net/",
+		APIManagementHostNameSuffix:  "azure-api.us",
+		SynapseEndpointSuffix:        NotAvailable,
 		ResourceIdentifiers: ResourceIdentifier{
 			Graph:               "https://graph.windows.net/",
 			KeyVault:            "https://vault.usgovcloudapi.net",
@@ -138,6 +148,8 @@ var (
 			Batch:               "https://batch.core.usgovcloudapi.net/",
 			OperationalInsights: "https://api.loganalytics.us",
 			Storage:             "https://storage.azure.com/",
+			Synapse:             NotAvailable,
+			ServiceBus:          "https://servicebus.azure.net/",
 		},
 	}
 
@@ -164,6 +176,8 @@ var (
 		ContainerRegistryDNSSuffix:   "azurecr.cn",
 		CosmosDBDNSSuffix:            "documents.azure.cn",
 		TokenAudience:                "https://management.chinacloudapi.cn/",
+		APIManagementHostNameSuffix:  "azure-api.cn",
+		SynapseEndpointSuffix:        "dev.azuresynapse.azure.cn",
 		ResourceIdentifiers: ResourceIdentifier{
 			Graph:               "https://graph.chinacloudapi.cn/",
 			KeyVault:            "https://vault.azure.cn",
@@ -171,6 +185,8 @@ var (
 			Batch:               "https://batch.chinacloudapi.cn/",
 			OperationalInsights: NotAvailable,
 			Storage:             "https://storage.azure.com/",
+			Synapse:             "https://dev.azuresynapse.net",
+			ServiceBus:          "https://servicebus.azure.net/",
 		},
 	}
 
@@ -197,6 +213,8 @@ var (
 		ContainerRegistryDNSSuffix:   NotAvailable,
 		CosmosDBDNSSuffix:            "documents.microsoftazure.de",
 		TokenAudience:                "https://management.microsoftazure.de/",
+		APIManagementHostNameSuffix:  NotAvailable,
+		SynapseEndpointSuffix:        NotAvailable,
 		ResourceIdentifiers: ResourceIdentifier{
 			Graph:               "https://graph.cloudapi.de/",
 			KeyVault:            "https://vault.microsoftazure.de",
@@ -204,6 +222,8 @@ var (
 			Batch:               "https://batch.cloudapi.de/",
 			OperationalInsights: NotAvailable,
 			Storage:             "https://storage.azure.com/",
+			Synapse:             NotAvailable,
+			ServiceBus:          "https://servicebus.azure.net/",
 		},
 	}
 )
diff --git a/vendor/github.com/Azure/go-autorest/autorest/client.go b/vendor/github.com/Azure/go-autorest/autorest/client.go
index e04f9fd4..898db8b9 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/client.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/client.go
@@ -165,7 +165,8 @@ type Client struct {
 	// Setting this to zero will use the provided context to control the duration.
 	PollingDuration time.Duration
 
-	// RetryAttempts sets the default number of retry attempts for client.
+	// RetryAttempts sets the total number of times the client will attempt to make an HTTP request.
+	// Set the value to 1 to disable retries.  DO NOT set the value to less than 1.
 	RetryAttempts int
 
 	// RetryDuration sets the delay duration for retries.
diff --git a/vendor/github.com/Azure/go-autorest/autorest/error.go b/vendor/github.com/Azure/go-autorest/autorest/error.go
index f724f333..35098eda 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/error.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/error.go
@@ -96,3 +96,8 @@ func (e DetailedError) Error() string {
 	}
 	return fmt.Sprintf("%s#%s: %s: StatusCode=%d -- Original Error: %v", e.PackageType, e.Method, e.Message, e.StatusCode, e.Original)
 }
+
+// Unwrap returns the original error.
+func (e DetailedError) Unwrap() error {
+	return e.Original
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/go.mod b/vendor/github.com/Azure/go-autorest/autorest/go.mod
index b66c78da..75a534f1 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/go.mod
+++ b/vendor/github.com/Azure/go-autorest/autorest/go.mod
@@ -4,9 +4,9 @@ go 1.12
 
 require (
 	github.com/Azure/go-autorest v14.2.0+incompatible
-	github.com/Azure/go-autorest/autorest/adal v0.9.0
-	github.com/Azure/go-autorest/autorest/mocks v0.4.0
+	github.com/Azure/go-autorest/autorest/adal v0.9.5
+	github.com/Azure/go-autorest/autorest/mocks v0.4.1
 	github.com/Azure/go-autorest/logger v0.2.0
 	github.com/Azure/go-autorest/tracing v0.6.0
-	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
+	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
 )
diff --git a/vendor/github.com/Azure/go-autorest/autorest/go.sum b/vendor/github.com/Azure/go-autorest/autorest/go.sum
index 96d2ad0f..fa27c68d 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/go.sum
+++ b/vendor/github.com/Azure/go-autorest/autorest/go.sum
@@ -1,21 +1,21 @@
 github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
-github.com/Azure/go-autorest/autorest/adal v0.9.0 h1:SigMbuFNuKgc1xcGhaeapbh+8fgsu+GxgDRFyg7f5lM=
-github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
+github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0=
+github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
 github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
 github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
-github.com/Azure/go-autorest/autorest/mocks v0.4.0 h1:z20OWOSG5aCye0HEkDp6TPmP17ZcfeMxPi6HnSALa8c=
-github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
 github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
 github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
 github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer.go b/vendor/github.com/Azure/go-autorest/autorest/preparer.go
index 6e8ed64e..98574a41 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/preparer.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/preparer.go
@@ -127,10 +127,7 @@ func WithHeader(header string, value string) PrepareDecorator {
 		return PreparerFunc(func(r *http.Request) (*http.Request, error) {
 			r, err := p.Prepare(r)
 			if err == nil {
-				if r.Header == nil {
-					r.Header = make(http.Header)
-				}
-				r.Header.Set(http.CanonicalHeaderKey(header), value)
+				setHeader(r, http.CanonicalHeaderKey(header), value)
 			}
 			return r, err
 		})
@@ -230,7 +227,7 @@ func AsPost() PrepareDecorator { return WithMethod("POST") }
 func AsPut() PrepareDecorator { return WithMethod("PUT") }
 
 // WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed
-// from the supplied baseUrl.
+// from the supplied baseUrl.  Query parameters will be encoded as required.
 func WithBaseURL(baseURL string) PrepareDecorator {
 	return func(p Preparer) Preparer {
 		return PreparerFunc(func(r *http.Request) (*http.Request, error) {
@@ -241,11 +238,16 @@ func WithBaseURL(baseURL string) PrepareDecorator {
 					return r, err
 				}
 				if u.Scheme == "" {
-					err = fmt.Errorf("autorest: No scheme detected in URL %s", baseURL)
+					return r, fmt.Errorf("autorest: No scheme detected in URL %s", baseURL)
 				}
-				if err == nil {
-					r.URL = u
+				if u.RawQuery != "" {
+					q, err := url.ParseQuery(u.RawQuery)
+					if err != nil {
+						return r, err
+					}
+					u.RawQuery = q.Encode()
 				}
+				r.URL = u
 			}
 			return r, err
 		})
@@ -290,10 +292,7 @@ func WithFormData(v url.Values) PrepareDecorator {
 			if err == nil {
 				s := v.Encode()
 
-				if r.Header == nil {
-					r.Header = make(http.Header)
-				}
-				r.Header.Set(http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost)
+				setHeader(r, http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost)
 				r.ContentLength = int64(len(s))
 				r.Body = ioutil.NopCloser(strings.NewReader(s))
 			}
@@ -329,10 +328,7 @@ func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDec
 				if err = writer.Close(); err != nil {
 					return r, err
 				}
-				if r.Header == nil {
-					r.Header = make(http.Header)
-				}
-				r.Header.Set(http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType())
+				setHeader(r, http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType())
 				r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
 				r.ContentLength = int64(body.Len())
 				return r, err
@@ -437,6 +433,7 @@ func WithXML(v interface{}) PrepareDecorator {
 					bytesWithHeader := []byte(withHeader)
 
 					r.ContentLength = int64(len(bytesWithHeader))
+					setHeader(r, headerContentLength, fmt.Sprintf("%d", len(bytesWithHeader)))
 					r.Body = ioutil.NopCloser(bytes.NewReader(bytesWithHeader))
 				}
 			}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/sender.go b/vendor/github.com/Azure/go-autorest/autorest/sender.go
index 704f3e55..78610ef2 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/sender.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/sender.go
@@ -23,11 +23,29 @@ import (
 	"net/http"
 	"net/http/cookiejar"
 	"strconv"
+	"sync"
 	"time"
 
 	"github.com/Azure/go-autorest/tracing"
 )
 
+// there is one sender per TLS renegotiation type, i.e. count of tls.RenegotiationSupport enums
+const defaultSendersCount = 3
+
+type defaultSender struct {
+	sender Sender
+	init   *sync.Once
+}
+
+// each type of sender will be created on demand in sender()
+var defaultSenders [defaultSendersCount]defaultSender
+
+func init() {
+	for i := 0; i < defaultSendersCount; i++ {
+		defaultSenders[i].init = &sync.Once{}
+	}
+}
+
 // used as a key type in context.WithValue()
 type ctxSendDecorators struct{}
 
@@ -107,26 +125,31 @@ func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*ht
 }
 
 func sender(renengotiation tls.RenegotiationSupport) Sender {
-	// Use behaviour compatible with DefaultTransport, but require TLS minimum version.
-	defaultTransport := http.DefaultTransport.(*http.Transport)
-	transport := &http.Transport{
-		Proxy:                 defaultTransport.Proxy,
-		DialContext:           defaultTransport.DialContext,
-		MaxIdleConns:          defaultTransport.MaxIdleConns,
-		IdleConnTimeout:       defaultTransport.IdleConnTimeout,
-		TLSHandshakeTimeout:   defaultTransport.TLSHandshakeTimeout,
-		ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
-		TLSClientConfig: &tls.Config{
-			MinVersion:    tls.VersionTLS12,
-			Renegotiation: renengotiation,
-		},
-	}
-	var roundTripper http.RoundTripper = transport
-	if tracing.IsEnabled() {
-		roundTripper = tracing.NewTransport(transport)
-	}
-	j, _ := cookiejar.New(nil)
-	return &http.Client{Jar: j, Transport: roundTripper}
+	// note that we can't init defaultSenders in init() since it will
+	// execute before calling code has had a chance to enable tracing
+	defaultSenders[renengotiation].init.Do(func() {
+		// Use behaviour compatible with DefaultTransport, but require TLS minimum version.
+		defaultTransport := http.DefaultTransport.(*http.Transport)
+		transport := &http.Transport{
+			Proxy:                 defaultTransport.Proxy,
+			DialContext:           defaultTransport.DialContext,
+			MaxIdleConns:          defaultTransport.MaxIdleConns,
+			IdleConnTimeout:       defaultTransport.IdleConnTimeout,
+			TLSHandshakeTimeout:   defaultTransport.TLSHandshakeTimeout,
+			ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
+			TLSClientConfig: &tls.Config{
+				MinVersion:    tls.VersionTLS12,
+				Renegotiation: renengotiation,
+			},
+		}
+		var roundTripper http.RoundTripper = transport
+		if tracing.IsEnabled() {
+			roundTripper = tracing.NewTransport(transport)
+		}
+		j, _ := cookiejar.New(nil)
+		defaultSenders[renengotiation].sender = &http.Client{Jar: j, Transport: roundTripper}
+	})
+	return defaultSenders[renengotiation].sender
 }
 
 // AfterDelay returns a SendDecorator that delays for the passed time.Duration before
diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility.go b/vendor/github.com/Azure/go-autorest/autorest/utility.go
index 67baab2c..3467b8fa 100644
--- a/vendor/github.com/Azure/go-autorest/autorest/utility.go
+++ b/vendor/github.com/Azure/go-autorest/autorest/utility.go
@@ -26,8 +26,6 @@ import (
 	"net/url"
 	"reflect"
 	"strings"
-
-	"github.com/Azure/go-autorest/autorest/adal"
 )
 
 // EncodedAs is a series of constants specifying various data encodings
@@ -207,18 +205,6 @@ func ChangeToGet(req *http.Request) *http.Request {
 	return req
 }
 
-// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError
-// interface.  If err is a DetailedError it will walk the chain of Original errors.
-func IsTokenRefreshError(err error) bool {
-	if _, ok := err.(adal.TokenRefreshError); ok {
-		return true
-	}
-	if de, ok := err.(DetailedError); ok {
-		return IsTokenRefreshError(de.Original)
-	}
-	return false
-}
-
 // IsTemporaryNetworkError returns true if the specified error is a temporary network error or false
 // if it's not.  If the error doesn't implement the net.Error interface the return value is true.
 func IsTemporaryNetworkError(err error) bool {
@@ -237,3 +223,10 @@ func DrainResponseBody(resp *http.Response) error {
 	}
 	return nil
 }
+
+func setHeader(r *http.Request, key, value string) {
+	if r.Header == nil {
+		r.Header = make(http.Header)
+	}
+	r.Header.Set(key, value)
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility_1.13.go b/vendor/github.com/Azure/go-autorest/autorest/utility_1.13.go
new file mode 100644
index 00000000..4cb5e684
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/utility_1.13.go
@@ -0,0 +1,29 @@
+// +build go1.13
+
+// Copyright 2017 Microsoft Corporation
+//
+//  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 autorest
+
+import (
+	"errors"
+
+	"github.com/Azure/go-autorest/autorest/adal"
+)
+
+// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError interface.
+func IsTokenRefreshError(err error) bool {
+	var tre adal.TokenRefreshError
+	return errors.As(err, &tre)
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility_legacy.go b/vendor/github.com/Azure/go-autorest/autorest/utility_legacy.go
new file mode 100644
index 00000000..ebb51b4f
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/utility_legacy.go
@@ -0,0 +1,31 @@
+// +build !go1.13
+
+// Copyright 2017 Microsoft Corporation
+//
+//  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 autorest
+
+import "github.com/Azure/go-autorest/autorest/adal"
+
+// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError
+// interface.  If err is a DetailedError it will walk the chain of Original errors.
+func IsTokenRefreshError(err error) bool {
+	if _, ok := err.(adal.TokenRefreshError); ok {
+		return true
+	}
+	if de, ok := err.(DetailedError); ok {
+		return IsTokenRefreshError(de.Original)
+	}
+	return false
+}
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/images.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/images.go
index 19de1291..3df1434a 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/images.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/images.go
@@ -36,6 +36,8 @@ type Images struct {
 	ShellImage string
 	// GsutilImage is the container image containing gsutil.
 	GsutilImage string
+	// BuildGCSFetcherImage is the container image containing our GCS fetcher binary.
+	BuildGCSFetcherImage string
 	// PRImage is the container image that we use to implement the PR source step.
 	PRImage string
 	// ImageDigestExporterImage is the container image containing our image digest exporter binary.
@@ -56,6 +58,7 @@ func (i Images) Validate() error {
 		{i.KubeconfigWriterImage, "kubeconfig-writer"},
 		{i.ShellImage, "shell"},
 		{i.GsutilImage, "gsutil"},
+		{i.BuildGCSFetcherImage, "build-gcs-fetcher"},
 		{i.PRImage, "pr"},
 		{i.ImageDigestExporterImage, "imagedigest-exporter"},
 	} {
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/conversion_error.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/conversion_error.go
index fae79e65..5c8a01e5 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/conversion_error.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/conversion_error.go
@@ -34,3 +34,6 @@ const (
 type CannotConvertError = v1beta1.CannotConvertError
 
 var _ error = (*CannotConvertError)(nil)
+
+// ConvertErrorf creates a CannotConvertError from the field name and format string.
+var ConvertErrorf = v1beta1.ConvertErrorf
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipeline_conversion.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipeline_conversion.go
index 63abd3e7..7d2b4824 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipeline_conversion.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipeline_conversion.go
@@ -19,16 +19,13 @@ package v1alpha1
 
 import (
 	"context"
-	"encoding/json"
 	"fmt"
 
 	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"knative.dev/pkg/apis"
 )
 
 const FinallyFieldName = "finally"
-const finallyAnnotationKey = "tekton.dev/v1beta1Finally"
 
 var _ apis.Convertible = (*Pipeline)(nil)
 
@@ -37,19 +34,10 @@ func (source *Pipeline) ConvertTo(ctx context.Context, obj apis.Convertible) err
 	switch sink := obj.(type) {
 	case *v1beta1.Pipeline:
 		sink.ObjectMeta = source.ObjectMeta
-		if err := source.Spec.ConvertTo(ctx, &sink.Spec); err != nil {
-			return err
-		}
-		if err := deserializeFinally(&sink.ObjectMeta, &sink.Spec); err != nil {
-			return err
-		}
-		if err := v1beta1.ValidatePipelineTasks(ctx, sink.Spec.Tasks, sink.Spec.Finally); err != nil {
-			return fmt.Errorf("error converting finally annotation into beta field: %w", err)
-		}
+		return source.Spec.ConvertTo(ctx, &sink.Spec)
 	default:
 		return fmt.Errorf("unknown version, got: %T", sink)
 	}
-	return nil
 }
 
 func (source *PipelineSpec) ConvertTo(ctx context.Context, sink *v1beta1.PipelineSpec) error {
@@ -93,9 +81,6 @@ func (sink *Pipeline) ConvertFrom(ctx context.Context, obj apis.Convertible) err
 	switch source := obj.(type) {
 	case *v1beta1.Pipeline:
 		sink.ObjectMeta = source.ObjectMeta
-		if err := serializeFinally(&sink.ObjectMeta, source.Spec.Finally); err != nil {
-			return err
-		}
 		return sink.Spec.ConvertFrom(ctx, source.Spec)
 	default:
 		return fmt.Errorf("unknown version, got: %T", sink)
@@ -115,6 +100,10 @@ func (sink *PipelineSpec) ConvertFrom(ctx context.Context, source v1beta1.Pipeli
 			}
 		}
 	}
+	// finally clause was introduced in v1beta1 and not available in v1alpha1
+	if len(source.Finally) > 0 {
+		return ConvertErrorf(FinallyFieldName, ConversionErrorFieldNotAvailableMsg)
+	}
 	return nil
 }
 
@@ -136,40 +125,3 @@ func (sink *PipelineTask) ConvertFrom(ctx context.Context, source v1beta1.Pipeli
 	sink.Timeout = source.Timeout
 	return nil
 }
-
-// serializeFinally serializes a list of Finally Tasks to the annotations
-// of an object's metadata section. This can then be used to re-instantiate
-// the Finally Tasks when converting back up to v1beta1 and beyond.
-func serializeFinally(meta *metav1.ObjectMeta, finally []v1beta1.PipelineTask) error {
-	if len(finally) != 0 {
-		b, err := json.Marshal(finally)
-		if err != nil {
-			return err
-		}
-		if meta.Annotations == nil {
-			meta.Annotations = make(map[string]string)
-		}
-		meta.Annotations[finallyAnnotationKey] = string(b)
-	}
-	return nil
-}
-
-// deserializeFinally populates a PipelineSpec's Finally list
-// from an annotation found on resources that have been previously
-// converted down from v1beta1 to v1alpha1.
-func deserializeFinally(meta *metav1.ObjectMeta, spec *v1beta1.PipelineSpec) error {
-	if meta.Annotations != nil {
-		if str, ok := meta.Annotations[finallyAnnotationKey]; ok {
-			finally := []v1beta1.PipelineTask{}
-			if err := json.Unmarshal([]byte(str), &finally); err != nil {
-				return fmt.Errorf("error converting finally annotation into beta field: %w", err)
-			}
-			delete(meta.Annotations, finallyAnnotationKey)
-			if len(meta.Annotations) == 0 {
-				meta.Annotations = nil
-			}
-			spec.Finally = finally
-		}
-	}
-	return nil
-}
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipelinerun_conversion.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipelinerun_conversion.go
index 929228cd..88d8c808 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipelinerun_conversion.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/pipelinerun_conversion.go
@@ -36,18 +36,6 @@ func (source *PipelineRun) ConvertTo(ctx context.Context, obj apis.Convertible)
 			return err
 		}
 		sink.Status = source.Status
-
-		spec := &v1beta1.PipelineSpec{}
-		if err := deserializeFinally(&sink.ObjectMeta, spec); err != nil {
-			return err
-		}
-		if len(spec.Finally) > 0 {
-			if sink.Spec.PipelineSpec == nil {
-				sink.Spec.PipelineSpec = spec
-			} else {
-				sink.Spec.PipelineSpec.Finally = spec.Finally
-			}
-		}
 		return nil
 	default:
 		return fmt.Errorf("unknown version, got: %T", sink)
@@ -82,13 +70,6 @@ func (sink *PipelineRun) ConvertFrom(ctx context.Context, obj apis.Convertible)
 			return err
 		}
 		sink.Status = source.Status
-
-		ps := source.Spec.PipelineSpec
-		if ps != nil && ps.Finally != nil {
-			if err := serializeFinally(&sink.ObjectMeta, ps.Finally); err != nil {
-				return err
-			}
-		}
 		return nil
 	default:
 		return fmt.Errorf("unknown version, got: %T", sink)
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/storage_resource.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/storage_resource.go
index 6f636bfb..82f55011 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/storage_resource.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1/storage_resource.go
@@ -20,5 +20,11 @@ import (
 	resource "github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1"
 )
 
-// PipelineResourceTypeGCS is the subtype for the GCSResources, which is backed by a GCS blob/directory.
-const PipelineResourceTypeGCS PipelineResourceType = resource.PipelineResourceTypeGCS
+const (
+	// PipelineResourceTypeGCS is the subtype for the GCSResources, which is backed by a GCS blob/directory.
+	PipelineResourceTypeGCS PipelineResourceType = resource.PipelineResourceTypeGCS
+
+	// PipelineResourceTypeBuildGCS is the subtype for the BuildGCSResources, which is simialr to the GCSResource but
+	// with additional functionality that was added to be compatible with knative build.
+	PipelineResourceTypeBuildGCS PipelineResourceType = resource.PipelineResourceTypeBuildGCS
+)
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_types.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_types.go
index 2566f5af..e2160ebc 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_types.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_types.go
@@ -17,18 +17,9 @@ limitations under the License.
 package v1beta1
 
 import (
-	"context"
-	"fmt"
-	"strings"
-
-	"github.com/google/go-containerregistry/pkg/name"
-	"github.com/tektoncd/pipeline/pkg/apis/config"
-
 	"github.com/tektoncd/pipeline/pkg/reconciler/pipeline/dag"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/sets"
-	"k8s.io/apimachinery/pkg/util/validation"
-	"knative.dev/pkg/apis"
 )
 
 // +genclient
@@ -170,80 +161,6 @@ type PipelineTask struct {
 	Timeout *metav1.Duration `json:"timeout,omitempty"`
 }
 
-// validateRefOrSpec validates at least one of taskRef or taskSpec is specified
-func (pt PipelineTask) validateRefOrSpec() (errs *apis.FieldError) {
-	// can't have both taskRef and taskSpec at the same time
-	if pt.TaskRef != nil && pt.TaskSpec != nil {
-		errs = errs.Also(apis.ErrMultipleOneOf("taskRef", "taskSpec"))
-	}
-	// Check that one of TaskRef and TaskSpec is present
-	if pt.TaskRef == nil && pt.TaskSpec == nil {
-		errs = errs.Also(apis.ErrMissingOneOf("taskRef", "taskSpec"))
-	}
-	return errs
-}
-
-// validateCustomTask validates custom task specifications - checking kind and fail if not yet supported features specified
-func (pt PipelineTask) validateCustomTask() (errs *apis.FieldError) {
-	if pt.TaskRef.Kind == "" {
-		errs = errs.Also(apis.ErrInvalidValue("custom task ref must specify kind", "taskRef.kind"))
-	}
-	// Conditions are deprecated so the effort to support them with custom tasks is not justified.
-	// When expressions should be used instead.
-	if len(pt.Conditions) > 0 {
-		errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support conditions - use when expressions instead", "conditions"))
-	}
-	// TODO(#3133): Support these features if possible.
-	if pt.Retries > 0 {
-		errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support retries", "retries"))
-	}
-	if pt.Resources != nil {
-		errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support PipelineResources", "resources"))
-	}
-	if pt.Timeout != nil {
-		errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support timeout", "timeout"))
-	}
-	return errs
-}
-
-// validateBundle validates bundle specifications - checking name and bundle
-func (pt PipelineTask) validateBundle() (errs *apis.FieldError) {
-	// bundle requires a TaskRef to be specified
-	if (pt.TaskRef != nil && pt.TaskRef.Bundle != "") && pt.TaskRef.Name == "" {
-		errs = errs.Also(apis.ErrMissingField("taskRef.name"))
-	}
-	// If a bundle url is specified, ensure it is parsable
-	if pt.TaskRef != nil && pt.TaskRef.Bundle != "" {
-		if _, err := name.ParseReference(pt.TaskRef.Bundle); err != nil {
-			errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("invalid bundle reference (%s)", err.Error()), "taskRef.bundle"))
-		}
-	}
-	return errs
-}
-
-// validateTask validates a pipeline task or a final task for taskRef and taskSpec
-func (pt PipelineTask) validateTask(ctx context.Context) (errs *apis.FieldError) {
-	// Validate TaskSpec if it's present
-	if pt.TaskSpec != nil {
-		errs = errs.Also(pt.TaskSpec.Validate(ctx).ViaField("taskSpec"))
-	}
-	if pt.TaskRef != nil {
-		if pt.TaskRef.Name != "" {
-			// TaskRef name must be a valid k8s name
-			if errSlice := validation.IsQualifiedName(pt.TaskRef.Name); len(errSlice) != 0 {
-				errs = errs.Also(apis.ErrInvalidValue(strings.Join(errSlice, ","), "name"))
-			}
-		} else {
-			errs = errs.Also(apis.ErrInvalidValue("taskRef must specify name", "taskRef.name"))
-		}
-		// fail if bundle is present when EnableTektonOCIBundles feature flag is off (as it won't be allowed nor used)
-		if pt.TaskRef.Bundle != "" {
-			errs = errs.Also(apis.ErrDisallowedFields("taskref.bundle"))
-		}
-	}
-	return errs
-}
-
 func (pt *PipelineTask) TaskSpecMetadata() PipelineTaskMetadata {
 	return pt.TaskSpec.Metadata
 }
@@ -252,37 +169,6 @@ func (pt PipelineTask) HashKey() string {
 	return pt.Name
 }
 
-func (pt PipelineTask) ValidateName() *apis.FieldError {
-	if err := validation.IsDNS1123Label(pt.Name); len(err) > 0 {
-		return &apis.FieldError{
-			Message: fmt.Sprintf("invalid value %q", pt.Name),
-			Paths:   []string{"name"},
-			Details: "Pipeline Task name must be a valid DNS Label." +
-				"For more info refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
-		}
-	}
-	return nil
-}
-
-// Validate classifies whether a task is a custom task, bundle, or a regular task(dag/final)
-// calls the validation routine based on the type of the task
-func (pt PipelineTask) Validate(ctx context.Context) (errs *apis.FieldError) {
-	errs = errs.Also(pt.validateRefOrSpec())
-	cfg := config.FromContextOrDefaults(ctx)
-	// If EnableCustomTasks feature flag is on, validate custom task specifications
-	// pipeline task having taskRef with APIVersion is classified as custom task
-	switch {
-	case cfg.FeatureFlags.EnableCustomTasks && pt.TaskRef != nil && pt.TaskRef.APIVersion != "":
-		errs = errs.Also(pt.validateCustomTask())
-		// If EnableTektonOCIBundles feature flag is on, validate bundle specifications
-	case cfg.FeatureFlags.EnableTektonOCIBundles && pt.TaskRef != nil && pt.TaskRef.Bundle != "":
-		errs = errs.Also(pt.validateBundle())
-	default:
-		errs = errs.Also(pt.validateTask(ctx))
-	}
-	return
-}
-
 func (pt PipelineTask) Deps() []string {
 	deps := []string{}
 
@@ -364,22 +250,6 @@ func (l PipelineTaskList) Names() sets.String {
 	return names
 }
 
-// Validate a list of pipeline tasks including custom task and bundles
-func (l PipelineTaskList) Validate(ctx context.Context, taskNames sets.String, path string) (errs *apis.FieldError) {
-	for i, t := range l {
-		// validate pipeline task name
-		errs = errs.Also(t.ValidateName().ViaFieldIndex(path, i))
-		// names cannot be duplicated - checking that pipelineTask names are unique
-		if _, ok := taskNames[t.Name]; ok {
-			errs = errs.Also(apis.ErrMultipleOneOf("name").ViaFieldIndex(path, i))
-		}
-		taskNames.Insert(t.Name)
-		// validate custom task, bundle, dag, or final task
-		errs = errs.Also(t.Validate(ctx).ViaFieldIndex(path, i))
-	}
-	return errs
-}
-
 // PipelineTaskParam is used to provide arbitrary string parameters to a Task.
 type PipelineTaskParam struct {
 	Name  string `json:"name"`
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_validation.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_validation.go
index b793661e..0db801cf 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_validation.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/pipeline_validation.go
@@ -21,12 +21,15 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/google/go-containerregistry/pkg/name"
+	"github.com/tektoncd/pipeline/pkg/apis/config"
 	"github.com/tektoncd/pipeline/pkg/apis/validate"
 	"github.com/tektoncd/pipeline/pkg/list"
 	"github.com/tektoncd/pipeline/pkg/reconciler/pipeline/dag"
 	"github.com/tektoncd/pipeline/pkg/substitution"
 	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/util/sets"
+	"k8s.io/apimachinery/pkg/util/validation"
 	"knative.dev/pkg/apis"
 )
 
@@ -46,7 +49,7 @@ func (ps *PipelineSpec) Validate(ctx context.Context) (errs *apis.FieldError) {
 		errs = errs.Also(apis.ErrGeneric("expected at least one, got none", "description", "params", "resources", "tasks", "workspaces"))
 	}
 	// PipelineTask must have a valid unique label and at least one of taskRef or taskSpec should be specified
-	errs = errs.Also(ValidatePipelineTasks(ctx, ps.Tasks, ps.Finally))
+	errs = errs.Also(validatePipelineTasks(ctx, ps.Tasks, ps.Finally))
 	// All declared resources should be used, and the Pipeline shouldn't try to use any resources
 	// that aren't declared
 	errs = errs.Also(validateDeclaredResources(ps.Resources, ps.Tasks, ps.Finally))
@@ -71,13 +74,113 @@ func (ps *PipelineSpec) Validate(ctx context.Context) (errs *apis.FieldError) {
 	return errs
 }
 
-// ValidatePipelineTasks ensures that pipeline tasks has unique label, pipeline tasks has specified one of
+// validatePipelineTasks ensures that pipeline tasks has unique label, pipeline tasks has specified one of
 // taskRef or taskSpec, and in case of a pipeline task with taskRef, it has a reference to a valid task (task name)
-func ValidatePipelineTasks(ctx context.Context, tasks []PipelineTask, finalTasks []PipelineTask) *apis.FieldError {
+func validatePipelineTasks(ctx context.Context, tasks []PipelineTask, finalTasks []PipelineTask) *apis.FieldError {
+	// Names cannot be duplicated
 	taskNames := sets.NewString()
 	var errs *apis.FieldError
-	errs = errs.Also(PipelineTaskList(tasks).Validate(ctx, taskNames, "tasks"))
-	errs = errs.Also(PipelineTaskList(finalTasks).Validate(ctx, taskNames, "finally"))
+	for i, t := range tasks {
+		errs = errs.Also(validatePipelineTask(ctx, t, taskNames).ViaFieldIndex("tasks", i))
+	}
+	for i, t := range finalTasks {
+		errs = errs.Also(validatePipelineTask(ctx, t, taskNames).ViaFieldIndex("finally", i))
+	}
+	return errs
+}
+
+func validatePipelineTaskName(name string) *apis.FieldError {
+	if err := validation.IsDNS1123Label(name); len(err) > 0 {
+		return &apis.FieldError{
+			Message: fmt.Sprintf("invalid value %q", name),
+			Paths:   []string{"name"},
+			Details: "Pipeline Task name must be a valid DNS Label." +
+				"For more info refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
+		}
+	}
+	return nil
+}
+
+func validatePipelineTask(ctx context.Context, t PipelineTask, taskNames sets.String) *apis.FieldError {
+	cfg := config.FromContextOrDefaults(ctx)
+	errs := validatePipelineTaskName(t.Name)
+
+	hasTaskRef := t.TaskRef != nil
+	hasTaskSpec := t.TaskSpec != nil
+	isCustomTask := cfg.FeatureFlags.EnableCustomTasks && hasTaskRef && t.TaskRef.APIVersion != ""
+
+	// can't have both taskRef and taskSpec at the same time
+	if hasTaskRef && hasTaskSpec {
+		errs = errs.Also(apis.ErrMultipleOneOf("taskRef", "taskSpec"))
+	}
+	// Check that one of TaskRef and TaskSpec is present
+	if !hasTaskRef && !hasTaskSpec {
+		errs = errs.Also(apis.ErrMissingOneOf("taskRef", "taskSpec"))
+	}
+	// Validate TaskSpec if it's present
+	if hasTaskSpec {
+		errs = errs.Also(t.TaskSpec.Validate(ctx).ViaField("taskSpec"))
+	}
+
+	// Check that PipelineTask names are unique.
+	if _, ok := taskNames[t.Name]; ok {
+		errs = errs.Also(apis.ErrMultipleOneOf("name"))
+	}
+	taskNames[t.Name] = struct{}{}
+
+	if hasTaskRef {
+		if t.TaskRef.Name != "" {
+			// TaskRef name must be a valid k8s name
+			if errSlice := validation.IsQualifiedName(t.TaskRef.Name); len(errSlice) != 0 {
+				errs = errs.Also(apis.ErrInvalidValue(strings.Join(errSlice, ","), "name"))
+			}
+		} else {
+			// Custom Task refs are allowed to have no name.
+			if !isCustomTask {
+				errs = errs.Also(apis.ErrInvalidValue("taskRef must specify name", "taskRef.name"))
+			}
+		}
+	}
+
+	if isCustomTask {
+		if t.TaskRef.Kind == "" {
+			errs = errs.Also(apis.ErrInvalidValue("custom task ref must specify kind", "taskRef.kind"))
+		}
+		// Conditions are deprecated so the effort to support them with custom tasks is not justified.
+		// When expressions should be used instead.
+		if len(t.Conditions) > 0 {
+			errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support conditions - use when expressions instead", "conditions"))
+		}
+		// TODO(#3133): Support these features if possible.
+		if t.Retries > 0 {
+			errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support retries", "retries"))
+		}
+		if t.Resources != nil {
+			errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support PipelineResources", "resources"))
+		}
+		if t.Timeout != nil {
+			errs = errs.Also(apis.ErrInvalidValue("custom tasks do not support timeout", "timeout"))
+		}
+	}
+
+	// If EnableTektonOCIBundles feature flag is on validate it.
+	// Otherwise, fail if it is present (as it won't be allowed nor used)
+	if cfg.FeatureFlags.EnableTektonOCIBundles {
+		// Check that if a bundle is specified, that a TaskRef is specified as well.
+		if (t.TaskRef != nil && t.TaskRef.Bundle != "") && t.TaskRef.Name == "" {
+			errs = errs.Also(apis.ErrMissingField("taskref.name"))
+		}
+
+		// If a bundle url is specified, ensure it is parseable.
+		if t.TaskRef != nil && t.TaskRef.Bundle != "" {
+			if _, err := name.ParseReference(t.TaskRef.Bundle); err != nil {
+				errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("invalid bundle reference (%s)", err.Error()), "taskref.bundle"))
+			}
+		}
+	} else if t.TaskRef != nil && t.TaskRef.Bundle != "" {
+		errs = errs.Also(apis.ErrDisallowedFields("taskref.bundle"))
+	}
+
 	return errs
 }
 
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/task_validation.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/task_validation.go
index c783903f..434345cf 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/task_validation.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1/task_validation.go
@@ -43,7 +43,7 @@ func (ts *TaskSpec) Validate(ctx context.Context) (errs *apis.FieldError) {
 		errs = errs.Also(apis.ErrMissingField("steps"))
 	}
 	errs = errs.Also(ValidateVolumes(ts.Volumes).ViaField("volumes"))
-	errs = errs.Also(validateDeclaredWorkspaces(ts.Workspaces, ts.Steps, ts.StepTemplate).ViaField("workspaces"))
+	errs = errs.Also(ValidateDeclaredWorkspaces(ts.Workspaces, ts.Steps, ts.StepTemplate).ViaField("workspaces"))
 	mergedSteps, err := MergeStepsWithStepTemplate(ts.StepTemplate, ts.Steps)
 	if err != nil {
 		errs = errs.Also(&apis.FieldError{
@@ -79,7 +79,7 @@ func (tr TaskResult) Validate(_ context.Context) *apis.FieldError {
 
 // a mount path which conflicts with any other declared workspaces, with the explicitly
 // declared volume mounts, or with the stepTemplate. The names must also be unique.
-func validateDeclaredWorkspaces(workspaces []WorkspaceDeclaration, steps []Step, stepTemplate *corev1.Container) (errs *apis.FieldError) {
+func ValidateDeclaredWorkspaces(workspaces []WorkspaceDeclaration, steps []Step, stepTemplate *corev1.Container) (errs *apis.FieldError) {
 	mountPaths := sets.NewString()
 	for _, step := range steps {
 		for _, vm := range step.VolumeMounts {
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipeline_resource_types.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipeline_resource_types.go
index 73ad08a7..b1171f87 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipeline_resource_types.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipeline_resource_types.go
@@ -53,6 +53,11 @@ const (
 
 	// PipelineResourceTypeGCS is the subtype for the GCSResources, which is backed by a GCS blob/directory.
 	PipelineResourceTypeGCS PipelineResourceType = "gcs"
+
+	// PipelineResourceTypeBuildGCS is the subtype for the BuildGCSResources, which is simialr to the GCSResource but
+	// with additional functionality that was added to be compatible with knative build.
+	// Deprecated: This PipelineResource type is deprecated and support will be removed in a future release.
+	PipelineResourceTypeBuildGCS PipelineResourceType = "build-gcs"
 )
 
 // AllResourceTypes can be used for validation to check if a provided Resource type is one of the known types.
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipelineresource_validation.go b/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipelineresource_validation.go
index c1c217ac..67e4f477 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipelineresource_validation.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1/pipelineresource_validation.go
@@ -128,7 +128,13 @@ func (rs *PipelineResourceSpec) Validate(ctx context.Context) *apis.FieldError {
 }
 
 func AllowedStorageType(gotType string) bool {
-	return gotType == PipelineResourceTypeGCS
+	switch gotType {
+	case string(PipelineResourceTypeGCS):
+		return true
+	case string(PipelineResourceTypeBuildGCS):
+		return true
+	}
+	return false
 }
 
 func validateURL(u, path string) *apis.FieldError {
diff --git a/vendor/github.com/tektoncd/pipeline/pkg/contexts/contexts.go b/vendor/github.com/tektoncd/pipeline/pkg/contexts/contexts.go
index b721edd3..63fad40d 100644
--- a/vendor/github.com/tektoncd/pipeline/pkg/contexts/contexts.go
+++ b/vendor/github.com/tektoncd/pipeline/pkg/contexts/contexts.go
@@ -18,6 +18,23 @@ package contexts
 
 import "context"
 
+// hdcnKey is used as the key for associating information
+// with a context.Context.
+type hdcnKey struct{}
+
+// WithDefaultConfigurationName notes on the context for nested validation
+// that there is a default configuration name, which affects how an empty
+// configurationName is validated.
+func WithDefaultConfigurationName(ctx context.Context) context.Context {
+	return context.WithValue(ctx, hdcnKey{}, struct{}{})
+}
+
+// HasDefaultConfigurationName checks to see whether the given context has
+// been marked as having a default configurationName.
+func HasDefaultConfigurationName(ctx context.Context) bool {
+	return ctx.Value(hdcnKey{}) != nil
+}
+
 // lemonadeKey is used as the key for associating information
 // with a context.Context. This variable doesn't really matter, so it's
 // a total random name (for history purpose, used lemonade as it was written
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9953128e..53858f40 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -2,10 +2,10 @@
 cloud.google.com/go/compute/metadata
 # github.com/Azure/go-autorest v14.2.0+incompatible => github.com/Azure/go-autorest v14.2.0+incompatible
 github.com/Azure/go-autorest
-# github.com/Azure/go-autorest/autorest v0.11.1
+# github.com/Azure/go-autorest/autorest v0.11.17
 github.com/Azure/go-autorest/autorest
 github.com/Azure/go-autorest/autorest/azure
-# github.com/Azure/go-autorest/autorest/adal v0.9.5
+# github.com/Azure/go-autorest/autorest/adal v0.9.10
 github.com/Azure/go-autorest/autorest/adal
 # github.com/Azure/go-autorest/autorest/date v0.3.0
 github.com/Azure/go-autorest/autorest/date
@@ -229,7 +229,7 @@ github.com/sergi/go-diff/diffmatchpatch
 # github.com/spf13/pflag v1.0.5
 ## explicit
 github.com/spf13/pflag
-# github.com/tektoncd/pipeline v0.23.0
+# github.com/tektoncd/pipeline v0.21.0
 ## explicit
 github.com/tektoncd/pipeline/pkg/apis/config
 github.com/tektoncd/pipeline/pkg/apis/pipeline


Test patch:
diff --git a/pkg/controller/ready/ready_suite_test.go b/pkg/controller/ready/ready_suite_test.go
new file mode 100644
index 00000000..0c733c97
--- /dev/null
+++ b/pkg/controller/ready/ready_suite_test.go
@@ -0,0 +1,17 @@
+// Copyright The Shipwright Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package ready_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestReady(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Ready Suite")
+}
diff --git a/pkg/controller/ready/ready_test.go b/pkg/controller/ready/ready_test.go
new file mode 100644
index 00000000..00be31ba
--- /dev/null
+++ b/pkg/controller/ready/ready_test.go
@@ -0,0 +1,74 @@
+// Copyright The Shipwright Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package ready_test
+
+import (
+	"os"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+
+	. "github.com/shipwright-io/build/pkg/controller/ready"
+)
+
+var _ = Describe("controller ready helper", func() {
+	var fileExists = func(filename string) bool {
+		_, err := os.Stat(filename)
+		return err == nil || os.IsExist(err)
+	}
+
+	Context("setting and unsetting ready file", func() {
+		const filename = "/tmp/foobar"
+
+		BeforeEach(func(){
+			Expect(fileExists(filename)).To(BeFalse())
+		})
+
+		AfterEach(func(){
+			os.Remove(filename)
+		})
+
+		It("creates a ready file with the given name when using Set", func() {
+			r := NewFileReady(filename)
+			Expect(r.Set()).ToNot(HaveOccurred())
+			Expect(fileExists(filename)).To(BeTrue())
+		})
+
+		It("should not break if Set is used multiple times", func() {
+			r := NewFileReady(filename)
+			Expect(r.Set()).ToNot(HaveOccurred())
+			Expect(r.Set()).ToNot(HaveOccurred())
+			Expect(fileExists(filename)).To(BeTrue())
+		})
+
+		It("removes the created file when using Unset", func() {
+			r := NewFileReady(filename)
+			Expect(r.Set()).ToNot(HaveOccurred())
+			Expect(fileExists(filename)).To(BeTrue())
+
+			Expect(r.Unset()).ToNot(HaveOccurred())
+			Expect(fileExists(filename)).To(BeFalse())
+		})
+
+		It("should not break if Unset ist used multiple times", func() {
+			r := NewFileReady(filename)
+			Expect(r.Set()).ToNot(HaveOccurred())
+			Expect(fileExists(filename)).To(BeTrue())
+
+			Expect(r.Unset()).ToNot(HaveOccurred())
+			Expect(r.Unset()).ToNot(HaveOccurred())
+			Expect(fileExists(filename)).To(BeFalse())
+		})
+
+		It("should not fail if the given file is already present", func() {
+			_, err :=os.Create(filename)
+			Expect(err).ToNot(HaveOccurred())
+
+			r := NewFileReady(filename)
+			Expect(r.Set()).ToNot(HaveOccurred())
+			Expect(fileExists(filename)).To(BeTrue())
+		})
+	})
+})
diff --git a/pkg/reconciler/buildrun/resources/runtime_image_test.go b/pkg/reconciler/buildrun/resources/runtime_image_test.go
index dfc9255d..6354c6a9 100644
--- a/pkg/reconciler/buildrun/resources/runtime_image_test.go
+++ b/pkg/reconciler/buildrun/resources/runtime_image_test.go
@@ -92,7 +92,7 @@ var _ = Describe("runtime-image", func() {
 			Expect(dockerfile).ToNot(BeNil())
 
 			Expect(fmt.Sprintf("\n%s", dockerfile)).To(Equal(`
-FROM test/output-image:latest as builder
+FROM $(params.shp-output-image) as builder
 
 FROM test/base-image:latest
 ENV ENVIRONMENT_VARIABLE="VALUE"
diff --git a/pkg/reconciler/buildrun/resources/taskrun_test.go b/pkg/reconciler/buildrun/resources/taskrun_test.go
index 4f3fe0f5..63c7bf94 100644
--- a/pkg/reconciler/buildrun/resources/taskrun_test.go
+++ b/pkg/reconciler/buildrun/resources/taskrun_test.go
@@ -64,7 +64,7 @@ var _ = Describe("GenerateTaskrun", func() {
 				Expect(err).To(BeNil())
 
 				expectedCommandOrArg = []string{
-					"bud", "--tag=$(outputs.resources.image.url)", fmt.Sprintf("--file=$(inputs.params.%s)", "DOCKERFILE"), fmt.Sprintf("$(inputs.params.%s)", "CONTEXT_DIR"),
+					"bud", "--tag=$(params.shp-output-image)", fmt.Sprintf("--file=$(inputs.params.%s)", "DOCKERFILE"), "$(params.shp-source-context)",
 				}
 			})
 
@@ -96,6 +96,52 @@ var _ = Describe("GenerateTaskrun", func() {
 			It("should ensure top level volumes are populated", func() {
 				Expect(len(got.Volumes)).To(Equal(1))
 			})
+
+			It("should contain the shipwright system parameters", func() {
+				params := got.Params
+
+				paramSourceRootFound := false
+				paramSourceContextFound := false
+				paramOutputImageFound := false
+
+				// legacy params
+				paramBuilderImageFound := false
+				paramDockerfileFound := false
+				paramContextDirFound := false
+
+				for _, param := range params {
+					switch param.Name {
+					case "shp-source-root":
+						paramSourceRootFound = true
+
+					case "shp-source-context":
+						paramSourceContextFound = true
+
+					case "shp-output-image":
+						paramOutputImageFound = true
+
+					case "BUILDER_IMAGE":
+						paramBuilderImageFound = true
+
+					case "DOCKERFILE":
+						paramDockerfileFound = true
+
+					case "CONTEXT_DIR":
+						paramContextDirFound = true
+
+					default:
+						Fail(fmt.Sprintf("Unexpected param found: %s", param.Name))
+					}
+				}
+
+				Expect(paramSourceRootFound).To(BeTrue())
+				Expect(paramSourceContextFound).To(BeTrue())
+				Expect(paramOutputImageFound).To(BeTrue())
+
+				Expect(paramBuilderImageFound).To(BeFalse()) // test build has no builder image
+				Expect(paramDockerfileFound).To(BeTrue())
+				Expect(paramContextDirFound).To(BeTrue())
+			})
 		})
 	})
 
@@ -237,17 +283,54 @@ var _ = Describe("GenerateTaskrun", func() {
 
 			It("should ensure generated TaskRun's spec special input params are correct", func() {
 				params := got.Spec.Params
+
+				paramSourceRootFound := false
+				paramSourceContextFound := false
+				paramOutputImageFound := false
+
+				// legacy params
+				paramBuilderImageFound := false
+				paramDockerfileFound := false
+				paramContextDirFound := false
+
 				for _, param := range params {
-					if param.Name == "BUILDER_IMAGE" {
+					switch param.Name {
+					case "shp-source-root":
+						paramSourceRootFound = true
+						Expect(param.Value.StringVal).To(Equal("/workspace/source"))
+
+					case "shp-source-context":
+						paramSourceContextFound = true
+						Expect(param.Value.StringVal).To(Equal("/workspace/source/docker-build"))
+
+					case "shp-output-image":
+						paramOutputImageFound = true
+						Expect(param.Value.StringVal).To(Equal(outputPath))
+
+					case "BUILDER_IMAGE":
+						paramBuilderImageFound = true
 						Expect(param.Value.StringVal).To(Equal(builderImage.Image))
-					}
-					if param.Name == "DOCKERFILE" {
+
+					case "DOCKERFILE":
+						paramDockerfileFound = true
 						Expect(param.Value.StringVal).To(Equal(dockerfile))
-					}
-					if param.Name == "CONTEXT_DIR" {
+
+					case "CONTEXT_DIR":
+						paramContextDirFound = true
 						Expect(param.Value.StringVal).To(Equal(contextDir))
+
+					default:
+						Fail(fmt.Sprintf("Unexpected param found: %s", param.Name))
 					}
 				}
+
+				Expect(paramSourceRootFound).To(BeTrue())
+				Expect(paramSourceContextFound).To(BeTrue())
+				Expect(paramOutputImageFound).To(BeTrue())
+
+				Expect(paramBuilderImageFound).To(BeTrue())
+				Expect(paramDockerfileFound).To(BeTrue())
+				Expect(paramContextDirFound).To(BeTrue())
 			})
 
 			It("should ensure resource replacements happen when needed", func() {
@@ -309,7 +392,7 @@ var _ = Describe("GenerateTaskrun", func() {
 				Expect(err).To(BeNil())
 			})
 
-			It("should use the imageURL from the BuildRun", func() {
+			It("should use the imageURL from the BuildRun in the resource", func() {
 				outputResources := got.Spec.Resources.Outputs
 				for _, outputResource := range outputResources {
 					Expect(outputResource.ResourceSpec.Type).To(Equal(v1beta1.PipelineResourceTypeImage))
@@ -321,6 +404,22 @@ var _ = Describe("GenerateTaskrun", func() {
 					}
 				}
 			})
+
+			It("should use the imageURL from the BuildRun for the param", func() {
+				params := got.Spec.Params
+
+				paramOutputImageFound := false
+
+				for _, param := range params {
+					switch param.Name {
+					case "shp-output-image":
+						paramOutputImageFound = true
+						Expect(param.Value.StringVal).To(Equal(outputPathBuildRun))
+					}
+				}
+
+				Expect(paramOutputImageFound).To(BeTrue())
+			})
 		})
 	})
 })
diff --git a/test/buildstrategy_samples.go b/test/buildstrategy_samples.go
index 4e325b75..51900580 100644
--- a/test/buildstrategy_samples.go
+++ b/test/buildstrategy_samples.go
@@ -16,16 +16,16 @@ spec:
   buildSteps:
     - name: buildah-bud
       image: quay.io/buildah/stable:latest
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         privileged: true
       command:
         - /usr/bin/buildah
       args:
         - bud
-        - --tag=$(build.output.image)
+        - --tag=$(params.shp-output-image)
         - --file=$(build.dockerfile)
-        - $(build.source.contextDir)
+        - $(params.shp-source-context)
       resources:
         limits:
           cpu: 500m
@@ -45,7 +45,7 @@ spec:
       args:
         - push
         - --tls-verify=false
-        - docker://$(build.output.image)
+        - docker://$(params.shp-output-image)
       resources:
         limits:
           cpu: 100m
@@ -75,7 +75,7 @@ spec:
   buildSteps:
     - name: build
       image: "$(build.builder.image)"
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       command:
         - buildah
         - bud
@@ -84,8 +84,8 @@ spec:
         - -f
         - $(build.dockerfile)
         - -t
-        - $(build.output.image)
-        - $(build.source.contextDir)
+        - $(params.shp-output-image)
+        - $(params.shp-source-context)
       resources:
         limits:
           cpu: 500m
@@ -110,11 +110,11 @@ spec:
   buildSteps:
     - name: build
       image: "$(build.builder.image)"
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       command:
         - /cnb/lifecycle/builder
         - -app
-        - /workspace/source
+        - $(params.shp-source-context)
         - -layers
         - /layers
         - -group
diff --git a/test/clusterbuildstrategy_samples.go b/test/clusterbuildstrategy_samples.go
index a06ee4eb..dace60b4 100644
--- a/test/clusterbuildstrategy_samples.go
+++ b/test/clusterbuildstrategy_samples.go
@@ -16,16 +16,16 @@ spec:
   buildSteps:
     - name: buildah-bud
       image: quay.io/buildah/stable:latest
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         privileged: true
       command:
         - /usr/bin/buildah
       args:
         - bud
-        - --tag=$(build.output.image)
+        - --tag=$(params.shp-output-image)
         - --file=$(build.dockerfile)
-        - $(build.source.contextDir)
+        - $(params.shp-source-context)
       resources:
         limits:
           cpu: 500m
@@ -45,7 +45,7 @@ spec:
       args:
         - push
         - --tls-verify=false
-        - docker://$(build.output.image)
+        - docker://$(params.shp-output-image)
       resources:
         limits:
           cpu: 100m
@@ -70,16 +70,16 @@ spec:
   buildSteps:
     - name: buildah-bud
       image: quay.io/buildah/stable:latest
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         privileged: true
       command:
         - /usr/bin/buildah
       args:
         - bud
-        - --tag=$(build.output.image)
+        - --tag=$(params.shp-output-image)
         - --file=$(build.dockerfile)
-        - $(build.source.contextDir)
+        - $(params.shp-source-context)
       resources:
         limits:
           cpu: 500m
@@ -99,7 +99,7 @@ spec:
       args:
         - push
         - --tls-verify=false
-        - docker://$(build.output.image)
+        - docker://$(params.shp-output-image)
       resources:
         limits:
           cpu: 500m
@@ -124,7 +124,7 @@ spec:
   buildSteps:
     - name: step-build-and-push
       image: gcr.io/kaniko-project/executor:v1.5.2
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         runAsUser: 0
         capabilities:
@@ -148,8 +148,8 @@ spec:
       args:
         - --skip-tls-verify=true
         - --dockerfile=$(build.dockerfile)
-        - --context=/workspace/source/$(build.source.contextDir)
-        - --destination=$(build.output.image)
+        - --context=$(params.shp-source-context)
+        - --destination=$(params.shp-output-image)
         - --oci-layout-path=/workspace/output/image
         - --snapshotMode=redo
         - --push-retry=3
@@ -174,7 +174,7 @@ spec:
   buildSteps:
     - name: step-build-and-push
       image: gcr.io/kaniko-project/executor:v1.5.2
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         runAsUser: 0
         capabilities:
@@ -198,8 +198,8 @@ spec:
       args:
         - --skips-tlss-verifys=true
         - --dockerfile=$(build.dockerfile)
-        - --context=/workspace/source/$(build.source.contextDir)
-        - --destination=$(build.output.image)
+        - --context=$(params.shp-source-context)
+        - --destination=$(params.shp-output-image)
         - --oci-layout-path=/workspace/output/image
         - --snapshotMode=redo
         - --push-retry=3
@@ -222,7 +222,7 @@ spec:
   buildSteps:
   - name: step-no-and-op
     image: alpine:latest
-    workingDir: /workspace/source
+    workingDir: $(params.shp-source-root)
     securityContext:
       runAsUser: 0
       capabilities:
@@ -289,7 +289,7 @@ spec:
   buildSteps:
     - name: step-build-and-push
       image: gcr.io/kaniko-project/executor:v1.5.2
-      workingDir: /workspace/source
+      workingDir: $(params.shp-source-root)
       securityContext:
         runAsUser: 0
         capabilities:
@@ -313,8 +313,8 @@ spec:
       args:
         - --skip-tls-verify=true
         - --dockerfile=$(build.dockerfile)
-        - --context=/workspace/source/$(build.source.contextDir)
-        - --destination=$(build.output.image)
+        - --context=$(params.shp-source-root)
+        - --destination=$(params.shp-output-image)
         - --oci-layout-path=/workspace/output/image
         - --snapshotMode=redo
         - --push-retry=3