Repository: openshift-pipelines/pipelines-as-code
Pull request #229 (2021-09-20 09:20:43)

Refactoring webvcs
Split Runinfo and pass it around with clients
Remove some dead code imported from tekton cli 🤷🏻
Abstract all github operations to an interface and implementation 

Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>

codecov-commenter: # [Codecov](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#229](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (c8c8750) into [main](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/commit/445d0c7340723c60cec5693d78e7b521a40214d5?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (445d0c7) will **decrease** coverage by `0.76%`.
> The diff coverage is `79.56%`.

[![Impacted file tree graph](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/graphs/tree.svg?width=650&height=150&src=pr&token=XOBPWX11IU&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

```diff
@@            Coverage Diff             @@
##             main     #229      +/-   ##
==========================================
- Coverage   67.49%   66.72%   -0.77%     
==========================================
  Files          27       26       -1     
  Lines        1646     1590      -56     
==========================================
- Hits         1111     1061      -50     
+ Misses        420      415       -5     
+ Partials      115      114       -1     
```


| [Impacted Files](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [pkg/kubeinteraction/cleanups.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2t1YmVpbnRlcmFjdGlvbi9jbGVhbnVwcy5nbw==) | `0.00% <0.00%> (ø)` | |
| [pkg/kubeinteraction/kubeinteraction.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2t1YmVpbnRlcmFjdGlvbi9rdWJlaW50ZXJhY3Rpb24uZ28=) | `0.00% <0.00%> (ø)` | |
| [pkg/kubeinteraction/namespace.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2t1YmVpbnRlcmFjdGlvbi9uYW1lc3BhY2UuZ28=) | `0.00% <0.00%> (ø)` | |
| [pkg/cmd/repository/create.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NtZC9yZXBvc2l0b3J5L2NyZWF0ZS5nbw==) | `53.73% <25.00%> (-0.21%)` | :arrow_down: |
| [pkg/cmd/pipelineascode/pipelineascode.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NtZC9waXBlbGluZWFzY29kZS9waXBlbGluZWFzY29kZS5nbw==) | `39.21% <46.66%> (-31.46%)` | :arrow_down: |
| [pkg/cmd/repository/describe.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NtZC9yZXBvc2l0b3J5L2Rlc2NyaWJlLmdv) | `53.57% <70.00%> (ø)` | |
| [pkg/webvcs/github.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL3dlYnZjcy9naXRodWIuZ28=) | `75.78% <81.81%> (+0.12%)` | :arrow_up: |
| [pkg/cmd/resolve/resolve.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2NtZC9yZXNvbHZlL3Jlc29sdmUuZ28=) | `78.08% <83.33%> (-1.41%)` | :arrow_down: |
| [pkg/kubeinteraction/secrets.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL2t1YmVpbnRlcmFjdGlvbi9zZWNyZXRzLmdv) | `75.00% <87.50%> (ø)` | |
| [pkg/pipelineascode/acl.go](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-cGtnL3BpcGVsaW5lYXNjb2RlL2FjbC5nbw==) | `70.58% <94.73%> (-0.57%)` | :arrow_down: |
| ... and [10 more](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Last update [445d0c7...c8c8750](https://codecov.io/gh/openshift-pipelines/pipelines-as-code/pull/229?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).

chmouel: /retest

Patch:
diff --git a/.golangci.yml b/.golangci.yml
index b265dc9a..76e9e3ec 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -8,56 +8,56 @@ linters-settings:
     exclude: .errcheck.txt
 linters:
   enable:
-  - asciicheck
-  - bodyclose
-  - depguard
-  - dogsled
-  - durationcheck
-  - exhaustive
-  # - exhaustivestruct
-  - exportloopref
-  - forbidigo
-  - forcetypeassert
-  - gochecknoinits
-  - dupl
-  - errcheck
-  - errorlint
-  - gofumpt
-  - goimports
-  - gosec
-  - gocritic
-  - misspell
-  - deadcode
-  - gosec
-  - gosimple
-  - govet
-  - ifshort
-  - importas
-  - makezero
-  - nakedret
-  - predeclared
-  - revive
-  - staticcheck
-  - stylecheck
-  - unused
-  - unparam
-  - gochecknoinits
-  - goconst
-    # - gocyclo
+    - asciicheck
+    - bodyclose
+    - depguard
+    - dogsled
+    - durationcheck
+    - exhaustive
+    # - exhaustivestruct
+    - exportloopref
+    - forbidigo
+    - forcetypeassert
+    - gochecknoinits
+    - dupl
+    - errcheck
+    - errorlint
+    - gofumpt
+    - goimports
+    - gosec
+    - gocritic
+    - misspell
+    - deadcode
+    - gosec
+    - gosimple
+    - govet
+    - ifshort
+    - importas
+    - makezero
+    - nakedret
+    - predeclared
+    - revive
+    - staticcheck
+    - stylecheck
+    - unused
+    - unparam
+    - gochecknoinits
+    - goconst
+      # - gocyclo
     # - goerr113
-  - gofmt
-  - goheader
-  - gomodguard
-  - goprintffuncname
-  - nestif
-  - nilerr
-  - noctx
-  - nolintlint
-  - prealloc
-  - promlinter
-  - rowserrcheck
-  - sqlclosecheck
-  - tparallel
+    - gofmt
+    - goheader
+    - gomodguard
+    - goprintffuncname
+    - nestif
+    - nilerr
+    - noctx
+    - nolintlint
+    - prealloc
+    - promlinter
+    - rowserrcheck
+    - sqlclosecheck
+    - tparallel
     #- unconvert
-  - wastedassign
-  - whitespace
+    - wastedassign
+    - whitespace
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 08b2062b..3c025cd2 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -1,27 +1,27 @@
 # This is an example goreleaser.yaml file with some sane defaults.
 # Make sure to check the documentation at http://goreleaser.com
 builds:
-- env:
-  - CGO_ENABLED=0
-  main: ./cmd/tkn-pac
-  binary: tkn-pac
-  goos:
-  - linux
-  - darwin
-  - windows
-  goarch:
-  - amd64
+  - env:
+      - CGO_ENABLED=0
+    main: ./cmd/tkn-pac
+    binary: tkn-pac
+    goos:
+      - linux
+      - darwin
+      - windows
+    goarch:
+      - amd64
 archives:
-- name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
-  replacements:
-    darwin: MacOS
-    linux: Linux
-    windows: Windows
-    386: i386
-    amd64: x86_64
-  format_overrides:
-    - goos: windows
-      format: zip
+  - name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
+    replacements:
+      darwin: MacOS
+      linux: Linux
+      windows: Windows
+      386: i386
+      amd64: x86_64
+    format_overrides:
+      - goos: windows
+        format: zip
 checksum:
   name_template: 'checksums.txt'
 snapshot:
@@ -30,10 +30,10 @@ changelog:
   sort: asc
   filters:
     exclude:
-    - '^docs:'
-    - '^test:'
-    - Merge pull request
-    - Merge branch
+      - '^docs:'
+      - '^test:'
+      - Merge pull request
+      - Merge branch
 release:
   prerelease: true
   header: |
@@ -78,8 +78,8 @@ nfpms:
     license: BSD
     vendor: Red Hat
     formats:
-    - deb
-    - rpm
+      - deb
+      - rpm
     bindir: /usr/bin
     replacements:
       amd64: 64bit
diff --git a/.markdownlint.json b/.markdownlint.json
index fb4a09d3..0e69ba56 100644
--- a/.markdownlint.json
+++ b/.markdownlint.json
@@ -1,4 +1,4 @@
 {
-    "line-length": false,
-    "first-header-h1": false
+  "line-length": false,
+  "first-header-h1": false
 }
diff --git a/.tekton/release-pipeline.yaml b/.tekton/release-pipeline.yaml
index 974b0daf..8d9c9bf9 100644
--- a/.tekton/release-pipeline.yaml
+++ b/.tekton/release-pipeline.yaml
@@ -94,11 +94,11 @@ spec:
           - name: source
             workspace: source
   workspaces:
-  - name: source
-    volumeClaimTemplate:
-      spec:
-        accessModes:
-          - ReadWriteOnce
-        resources:
-          requests:
-            storage: 1Gi
+    - name: source
+      volumeClaimTemplate:
+        spec:
+          accessModes:
+            - ReadWriteOnce
+          resources:
+            requests:
+              storage: 1Gi
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index a72fbe38..0ba2b4f0 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -3,11 +3,9 @@ SETUP
 
 ## Dev setup
 
-* Configure and use [ko](https://github.com/google/ko) to easily push your change to a
-  registry.
-* You should be able to use it against a kind/minikube cluster but bear in mind
-  we are trying to be compatible from at least the pipeline/triggers version
-  from openshift-pipelines.
+* Configure and use [ko](https://github.com/google/ko) to easily push your change to a registry.
+* You should be able to use it against a kind/minikube cluster but bear in mind we are trying to be compatible from at
+  least the pipeline/triggers version from openshift-pipelines.
 * Install your cluster with ko or from release yaml :
 
     ```shell
@@ -18,22 +16,20 @@ SETUP
 
 * Configure a few Repository CR and a namespace target.
 
-* If you go to your GitHub app setting in `Advanced` you can see the json and
-  payload GitHub is sending to the eventlistenner.
+* If you go to your GitHub app setting in `Advanced` you can see the json and payload GitHub is sending to the
+  eventlistenner.
 
-* If you want to replay an event without having to `git commmit --amend
-  --no-edit && git push --force`, you can capture that json blob into a file
+* If you want to replay an event without having to `git commmit --amend --no-edit && git push --force`, you can capture
+  that json blob into a file
   (ie: /tmp/payload.json) and do :
 
   ```shell
   ./hack/dev/replay-gh-events.py /tmp/payload.json
   ```
 
-  That script would detect github webhook secret and payload content and replay
-  it to the event listenner.
+  That script would detect github webhook secret and payload content and replay it to the event listenner.
 
-  If you don't have a OpenShift route setup to the eventlistenner, you can
-  override the route with :
+  If you don't have a OpenShift route setup to the eventlistenner, you can override the route with :
 
   ```shell
   export EL_ROUTE=http://localhost:8080
@@ -47,9 +43,8 @@ SETUP
 
   will give you an easy way to debug payloads on kind.
 
-* If you need to debug your binary from your IDE, you will need an user token
-  generated from the app, at first you need to grab the installation_id of your
-  repository id, you can get that from the payload :
+* If you need to debug your binary from your IDE, you will need an user token generated from the app, at first you need
+  to grab the installation_id of your repository id, you can get that from the payload :
 
   ```shell
   jq .installation_id /tmp/payload.json
@@ -65,8 +60,7 @@ SETUP
 
   This only can be used for that installation_id if you target another repo it will fail.
 
-  You want to use a cache-file or it will generate a token every time and you
-  may get ratelimited.
+  You want to use a cache-file or it will generate a token every time and you may get ratelimited.
 
   You can then run the binary with :
 
@@ -74,15 +68,13 @@ SETUP
   go run cmd/pipelines-as-code/main.go --trigger-target=issue-recheck --webhook-type=check_run --payload-file=/tmp/payload.json --token=$(cat /tmp/token.for.my.repo)
   ```
 
-  To guess the trigger target and webhook-type you can simply get the logs of
-  the pipelines-as-code pr pod which gets printed there (along with a token you
-  can use quickly).
+  To guess the trigger target and webhook-type you can simply get the logs of the pipelines-as-code pr pod which gets
+  printed there (along with a token you can use quickly).
 
   You can plug that command into your IDE of choice for debugging.
 
-  On vscode argument cannot be a shell script (i.e: that cat command would not
-  work), you can use [this
-  plugin](https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input)
+  On vscode argument cannot be a shell script (i.e: that cat command would not work), you can
+  use [this plugin](https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input)
   for that.
 
 * There is a bunch of payload example in test/fixtures/ which you can use for
@@ -93,8 +85,7 @@ SETUP
 
   I grab the SHA locally and generate a payload out of it :
 
-  My shell script has a few variables which I configure and it autodetect from
-  the local repository the REF and SHA :
+  My shell script has a few variables which I configure and it autodetect from the local repository the REF and SHA :
 
   ```shell
   OWNER_REPO=${1:-"chmouel/scratchmyback"}
@@ -149,7 +140,7 @@ SETUP
 
 ## Code
 
-* 100% coverage is not a goal, coverage of corner case errors handling
-  is really not necessary.
-* Make sure you make it easy to reproduce the bug for reviewers, i.e: copy the problematic payload in the `test/fixtures`
+* 100% coverage is not a goal, coverage of corner case errors handling is really not necessary.
+* Make sure you make it easy to reproduce the bug for reviewers, i.e: copy the problematic payload in
+  the `test/fixtures`
   directory.
diff --git a/INSTALL.md b/INSTALL.md
index d26a1570..d7512e98 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,6 +1,7 @@
 # Installation Guides
 
 In order to install and use Pipelines-as-Code, you need to
+
 * Install the Pipelines-as-Code infrastructure on your cluster
 * Create a Pipelines-as-Code GitHub App on your GitHub account or organization
 * Configure Pipelines-as-Code on your cluster to access the GitHub App
@@ -24,13 +25,15 @@ If you would like to install the current development version you can simply inst
 kubectl apply -f https://raw.githubusercontent.com/openshift-pipelines/pipelines-as-code/nightly/release.yaml
 ```
 
-It will apply the release.yaml to your kubernetes cluster, creating the
-admin namespace `pipelines-as-code`, the roles and all other bits needed.
+It will apply the release.yaml to your kubernetes cluster, creating the admin namespace `pipelines-as-code`, the roles
+and all other bits needed.
 
-The `pipelines-as-code` namespace is where the Pipelines-as-Code infrastructure runs and is supposed to be accessible only by the admin.
+The `pipelines-as-code` namespace is where the Pipelines-as-Code infrastructure runs and is supposed to be accessible
+only by the admin.
 
-The Route for the EventListener URL is automatically created when you apply the release.yaml.
-You will need to grab the url for the next section when creating the GitHub App. You can run this command to get the route created on your cluster:
+The Route for the EventListener URL is automatically created when you apply the release.yaml. You will need to grab the
+url for the next section when creating the GitHub App. You can run this command to get the route created on your
+cluster:
 
 ```shell
 echo https://$(oc get route -n pipelines-as-code el-pipelines-as-code-interceptor -o jsonpath='{.spec.host}')
@@ -38,33 +41,36 @@ echo https://$(oc get route -n pipelines-as-code el-pipelines-as-code-intercepto
 
 ### Create a Pipelines-as-Code GitHub App
 
-You should now create a Pipelines-as-Code GitHub App which acts as the integration point with OpenShift Pipelines and brings the Git workflow into Tekton pipelines. You need the webhook of the GitHub App pointing to your Pipelines-as-Code EventListener route endpoint which would then trigger pipelines on GitHub events.
+You should now create a Pipelines-as-Code GitHub App which acts as the integration point with OpenShift Pipelines and
+brings the Git workflow into Tekton pipelines. You need the webhook of the GitHub App pointing to your Pipelines-as-Code
+EventListener route endpoint which would then trigger pipelines on GitHub events.
 
-* Go to https://github.com/settings/apps (or *Settings > Developer settings > GitHub Apps*) and click on **New GitHub App** button
+* Go to https://github.com/settings/apps (or *Settings > Developer settings > GitHub Apps*) and click on **New GitHub
+  App** button
 * Provide the following info in the GitHub App form
-  * **GitHub Application Name**: `OpenShift Pipelines`
-  * **Homepage URL**: *[OpenShift Console URL]*
-  * **Webhook URL**: *[the EventListener route URL copies in the previous section]*
-  * **Webhook secret**: *[an arbitrary secret, you can generate one with `openssl rand -hex 20`]*
+    * **GitHub Application Name**: `OpenShift Pipelines`
+    * **Homepage URL**: *[OpenShift Console URL]*
+    * **Webhook URL**: *[the EventListener route URL copies in the previous section]*
+    * **Webhook secret**: *[an arbitrary secret, you can generate one with `openssl rand -hex 20`]*
 
 * Select the following repository permissions:
-  * **Checks**: `Read & Write`
-  * **Contents**: `Read & Write`
-  * **Issues**: `Read & Write`
-  * **Metadata**: `Readonly`
-  * **Pull request**: `Read & Write`
+    * **Checks**: `Read & Write`
+    * **Contents**: `Read & Write`
+    * **Issues**: `Read & Write`
+    * **Metadata**: `Readonly`
+    * **Pull request**: `Read & Write`
 
 * Select the following organization permissions:
-  * **Members**: `Readonly`
-  * **Plan**: `Readonly`
+    * **Members**: `Readonly`
+    * **Plan**: `Readonly`
 
 * Select the following user permissions:
-  * Commit comment
-  * Issue comment
-  * Pull request
-  * Pull request review
-  * Pull request review comment
-  * Push
+    * Commit comment
+    * Issue comment
+    * Pull request
+    * Pull request review
+    * Pull request review comment
+    * Push
 
 > You can see a screenshot of how the GitHub App permissions look like [here](https://user-images.githubusercontent.com/98980/124132813-7e53f580-da81-11eb-9eb4-e4f1487cf7a0.png)
 
@@ -72,13 +78,21 @@ You should now create a Pipelines-as-Code GitHub App which acts as the integrati
 
 * Take note of the **App ID** at the top of the page on the details page of the GitHub App you just created.
 
-* In **Private keys** section, click on **Generate Private key* to generate a private key for the GitHub app. It will download automatically. Store the private key in a safe place as you need it in the next section and in future when reconfiguring this app to use a different cluster.
+* In **Private keys** section, click on **Generate Private key* to generate a private key for the GitHub app. It will
+  download automatically. Store the private key in a safe place as you need it in the next section and in future when
+  reconfiguring this app to use a different cluster.
 
 ### Configure Pipelines-as-Code on your cluster to access the GitHub App
 
-In order for Pipelines-as-Code to be able to authenticate to the GitHub App and have the GitHub App securely trigger the Pipelines-as-Code webhook, you need to create a Kubernetes secret containing the private key of the GitHub App and the webhook secret of the Pipelines-as-Code as it was provided when you created the GitHub App in the previous section. This secret is [used to generate](https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps) a token on behalf of the user running the event and make sure to validate the webhook via the webhook secret.
+In order for Pipelines-as-Code to be able to authenticate to the GitHub App and have the GitHub App securely trigger the
+Pipelines-as-Code webhook, you need to create a Kubernetes secret containing the private key of the GitHub App and the
+webhook secret of the Pipelines-as-Code as it was provided when you created the GitHub App in the previous section. This
+secret
+is [used to generate](https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps)
+a token on behalf of the user running the event and make sure to validate the webhook via the webhook secret.
 
 Run the following command and replace:
+
 * `APP_ID` with the GitHub App **App ID** copied in the previous section
 * `WEBHOOK_SECRET` with the webhook secret provided when created the GitHub App in the previous section
 * `PATH_PRIVATE_KEY` with the path to the private key that was downloaded in the previous section
@@ -94,12 +108,16 @@ kubectl -n pipelines-as-code create secret generic github-app-secret \
 
 Pipelines as Code supports Github Enterprise.
 
-You don't need to do anything special to get Pipelines as code working with GHE.
-Pipelines as code will automatically detects the header as set from GHE and use it  the GHE API auth url instead of the public github.
+You don't need to do anything special to get Pipelines as code working with GHE. Pipelines as code will automatically
+detects the header as set from GHE and use it the GHE API auth url instead of the public github.
 
 ### Kubernetes
 
-Pipelines as Code should work directly on kubernetes/minikube/kind. You just need to install the release.yaml for [pipeline](https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml), [triggers](https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml) and its [interceptors](https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml) on your cluster. The release yaml to install pipelines are for the relesaed version :
+Pipelines as Code should work directly on kubernetes/minikube/kind. You just need to install the release.yaml
+for [pipeline](https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml)
+, [triggers](https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml) and
+its [interceptors](https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml) on your cluster.
+The release yaml to install pipelines are for the relesaed version :
 
 ```shell
 VERSION=0.3
@@ -116,7 +134,8 @@ Kubernetes Dashboard is not yet supported for logs links but help is always welc
 
 ## CLI
 
-`Pipelines as Code` provide a CLI which is design to work as tkn plugin. To install the plugin see the instruction below.
+`Pipelines as Code` provide a CLI which is design to work as tkn plugin. To install the plugin see the instruction
+below.
 
 ### Binary releases
 
@@ -134,7 +153,8 @@ go install github.com/openshift-pipelines/pipelines-as-code/cmd/tkn-pac
 
 ### Brew release
 
-On [LinuxBrew](https://docs.brew.sh/Homebrew-on-Linux) or [OSX brew](https://brew.sh/) you can simply add the Brew tap to have the tkn-pac plugin and its completion installed :
+On [LinuxBrew](https://docs.brew.sh/Homebrew-on-Linux) or [OSX brew](https://brew.sh/) you can simply add the Brew tap
+to have the tkn-pac plugin and its completion installed :
 
 ```shell
 brew install openshift-pipelines/pipelines-as-code/tektoncd-pac
diff --git a/README.md b/README.md
index 3cb50542..858a66af 100644
--- a/README.md
+++ b/README.md
@@ -6,23 +6,21 @@ Pipelines as Code -- An opinionated CI based on OpenShift Pipelines / Tekton.
 
 ## Introduction
 
-Pipelines as Code let you use the [Pipelines as Code flow]([https://www.thoughtworks.com/radar/techniques/pipelines-as-code](https://www.thoughtworks.com/radar/techniques/pipelines-as-code)) directly with OpenShift
-Pipelines.
+Pipelines as Code let you use
+the [Pipelines as Code flow]([https://www.thoughtworks.com/radar/techniques/pipelines-as-code](https://www.thoughtworks.com/radar/techniques/pipelines-as-code))
+directly with OpenShift Pipelines.
 
 The goal of Pipelines as Code is to let you define your
-[Tekton](https://tekton.cd) templates inside your source code repository and
-have the pipeline run and report the status of the execution when triggered by a
-Pull Request or a Push.
+[Tekton](https://tekton.cd) templates inside your source code repository and have the pipeline run and report the status
+of the execution when triggered by a Pull Request or a Push.
 
 See a walkthought video about it here :
 
 [![Pipelines as Code Walkthought](https://img.youtube.com/vi/Uh1YhOGPOes/0.jpg)](https://www.youtube.com/watch?v=Uh1YhOGPOes)
 
-
 Pipelines as Code features:
 
-- Pull-request status support: When iterating over a Pull Request, status and control is
-  done on the platform.
+- Pull-request status support: When iterating over a Pull Request, status and control is done on the platform.
 
 - GitHub Checks API support to set the status of a PipelineRun including rechecks
 
@@ -46,11 +44,17 @@ Please follow [this document](INSTALL.md) for installing Pipelines as Code on Op
 
 ## Getting Started
 
-The flow for using pipelines as code generally begins with admin installing the Pipelines-as-Code infrastructure, creating a GitHub App and sharing the GitHub App url across the organization for app teams to enable the app on their GitHub repositories.
+The flow for using pipelines as code generally begins with admin installing the Pipelines-as-Code infrastructure,
+creating a GitHub App and sharing the GitHub App url across the organization for app teams to enable the app on their
+GitHub repositories.
 
-In order to enable the GitHub App provided by admin on your Git repository as documented [here](https://docs.github.com/en/developers/apps/managing-github-apps/installing-github-apps). Otherwise you can go to the *Settings > Applications* and then click on *Configure* button near the GitHub App you had created. In the **Repository access** section, select the repositories that you want to enable and have access to Pipelines-as-code.
+In order to enable the GitHub App provided by admin on your Git repository as
+documented [here](https://docs.github.com/en/developers/apps/managing-github-apps/installing-github-apps). Otherwise you
+can go to the *Settings > Applications* and then click on *Configure* button near the GitHub App you had created. In
+the **Repository access** section, select the repositories that you want to enable and have access to Pipelines-as-code.
 
-Once you have enabled your GitHub App for your GitHub repository, you can use the `pac` Tekton CLI plugin to bootstrap pipelines as code:
+Once you have enabled your GitHub App for your GitHub repository, you can use the `pac` Tekton CLI plugin to bootstrap
+pipelines as code:
 
 ```
 $ git clone https://github.com/siamaksade/pipeline-as-code-demo
@@ -77,14 +81,15 @@ tkn pac resolve --generateName \
 
 ```
 
-The above command would create a `Repository` CRD in your `demo` namespace which is used to determine where the PipelineRuns for your GitHub repository should run. It also generates an example pipeline in the `.tekton` folder. Commit and push the pipeline to your repo to start using pipelines as code.
+The above command would create a `Repository` CRD in your `demo` namespace which is used to determine where the
+PipelineRuns for your GitHub repository should run. It also generates an example pipeline in the `.tekton` folder.
+Commit and push the pipeline to your repo to start using pipelines as code.
 
 ## Usage Guide
 
 ### Pipelines As Code Configurations
 
-There is a few things you can configure via the configmap `pipelines-as-code` in
-the `pipelines-as-code` namespace.
+There is a few things you can configure via the configmap `pipelines-as-code` in the `pipelines-as-code` namespace.
 
 - `application-name`
 
@@ -92,11 +97,17 @@ the `pipelines-as-code` namespace.
 
 - `max-keep-days`
 
-  The number of the day to keep the PipelineRuns runs in the `pipelines-as-code` namespace. We install by default a cronjob that cleans up the PipelineRuns generated on events in pipelines-as-code namespace. Note that these PipelineRuns are internal to Pipelines-as-code are separate from the PipelineRuns that exist in the user's GitHub repository. The cronjob runs every hour and by default cleanups PipelineRuns over a day. This configmap setting doesn't affect the cleanups of the user's PipelineRuns which are controlled by the [annotations on the PipelineRun definition in the user's GitHub repository](#pipelineruns-cleanups).
+  The number of the day to keep the PipelineRuns runs in the `pipelines-as-code` namespace. We install by default a
+  cronjob that cleans up the PipelineRuns generated on events in pipelines-as-code namespace. Note that these
+  PipelineRuns are internal to Pipelines-as-code are separate from the PipelineRuns that exist in the user's GitHub
+  repository. The cronjob runs every hour and by default cleanups PipelineRuns over a day. This configmap setting
+  doesn't affect the cleanups of the user's PipelineRuns which are controlled by
+  the [annotations on the PipelineRun definition in the user's GitHub repository](#pipelineruns-cleanups).
 
 - `secret-auto-create`
 
-    Wether to auto create a secret with the token generated via the Github application to be used with private repositories. This feature is enabled by default.
+  Wether to auto create a secret with the token generated via the Github application to be used with private
+  repositories. This feature is enabled by default.
 
 ### Namespace Configuration
 
@@ -115,44 +126,39 @@ spec:
 EOF
 ```
 
-This will match all Pull Request coming to `github.com/linda/project` on branch
-main into the namespace `my-pipeline-ci`
+This will match all Pull Request coming to `github.com/linda/project` on branch main into the namespace `my-pipeline-ci`
 
-For security reasons, the Repository CR needs to be created
-in the namespace where Tekton Pipelines associated with the source code repository would be executed.
+For security reasons, the Repository CR needs to be created in the namespace where Tekton Pipelines associated with the
+source code repository would be executed.
 
-There is another optional layer of security where PipelineRun can have an
-annotation to explicitely target a specific namespace. It would stilll need to
-have a Repository CRD created in that namespace to be able to be matched.
+There is another optional layer of security where PipelineRun can have an annotation to explicitely target a specific
+namespace. It would stilll need to have a Repository CRD created in that namespace to be able to be matched.
 
-With this annotation there is no way a bad actor on a cluster can hijack the
-pipelineRun execution to a namespace they don't have access to. To use that
-feature you need to add this annotation :
+With this annotation there is no way a bad actor on a cluster can hijack the pipelineRun execution to a namespace they
+don't have access to. To use that feature you need to add this annotation :
 
 ```yaml
 pipelinesascode.tekton.dev/target-namespace: "mynamespace"
 ```
 
-and Pipelines as Code will only match the repository in the mynamespace Namespace
-instead of trying to match it from all available repository on cluster.
+and Pipelines as Code will only match the repository in the mynamespace Namespace instead of trying to match it from all
+available repository on cluster.
 
 ### Authoring PipelineRun in `.tekton/` directory
 
-- Pipelines as Code will always try to be as close to the tekton template as possible.
-  Usually you would write your template and save them with a ".yaml" extension  and
-  Pipelines as Code will run them.
+- Pipelines as Code will always try to be as close to the tekton template as possible. Usually you would write your
+  template and save them with a ".yaml" extension and Pipelines as Code will run them.
 
-- Inside your pipeline you would need to be able to consume the commit as received from the
-  webhook by checking it out the repository from that ref. You would usually use
+- Inside your pipeline you would need to be able to consume the commit as received from the webhook by checking it out
+  the repository from that ref. You would usually use
   the [git-clone](https://github.com/tektoncd/catalog/blob/main/task/git-clone/)
-  task from catalog for the same. To be able to specify those parameters, Pipelines
-  as Code allows you to have those two variables filled between double brackets,
-  i.e: `{{ var }}`:
+  task from catalog for the same. To be able to specify those parameters, Pipelines as Code allows you to have those two
+  variables filled between double brackets, i.e: `{{ var }}`:
 
-  - `{{repo_owner}}`: The repository owner.
-  - `{{repo_name}}`: The repository name.
-  - `{{repo_url}}`: The repository full URL.
-  - `{{revision}}`: The commit full sha revision.
+    - `{{repo_owner}}`: The repository owner.
+    - `{{repo_name}}`: The repository name.
+    - `{{repo_url}}`: The repository full URL.
+    - `{{revision}}`: The commit full sha revision.
 
 - You need at least one `PipelineRun` with a `PipelineSpec` or a separated
   `Pipeline` object. You can have embedded `TaskSpec` inside
@@ -164,8 +170,8 @@ instead of trying to match it from all available repository on cluster.
 
 #### Event matching to a Pipeline
 
-Each `PipelineRun` can match different vcs events via some special annotations
-on the `PipelineRun`. For example when you have these metadatas in your `PipelineRun`:
+Each `PipelineRun` can match different vcs events via some special annotations on the `PipelineRun`. For example when
+you have these metadatas in your `PipelineRun`:
 
 ```yaml
  metadata:
@@ -175,18 +181,16 @@ on the `PipelineRun`. For example when you have these metadatas in your `Pipelin
     pipelinesascode.tekton.dev/on-event: "[pull_request]"
 ```
 
-`Pipelines as Code` will match the piplinerun `pipeline-pr-main` if the VCS
-events target the branch `main` and it's coming from a `[pull_request]`
+`Pipelines as Code` will match the piplinerun `pipeline-pr-main` if the VCS events target the branch `main` and it's
+coming from a `[pull_request]`
 
 Multiple target branch can be specified separated by comma, i.e:
 
 `[main, release-nightly]`
 
-You can match on `pull_request` events as above and you can as well match
-pipelineRuns on `push` events to a repository
+You can match on `pull_request` events as above and you can as well match pipelineRuns on `push` events to a repository
 
-For example this will match the pipeline when there is a push to a commit in
-the `main` branch :
+For example this will match the pipeline when there is a push to a commit in the `main` branch :
 
 ```yaml
  metadata:
@@ -197,8 +201,8 @@ the `main` branch :
 ```
 
 You can specify the full refs like `refs/heads/main` or the shortref like
-`main`. You can as well specify globs, for example `refs/heads/*` will match any
-target branch or `refs/tags/1.*` will match all the tags starting from `1.`.
+`main`. You can as well specify globs, for example `refs/heads/*` will match any target branch or `refs/tags/1.*` will
+match all the tags starting from `1.`.
 
 A full example for a push of a tag :
 
@@ -210,35 +214,32 @@ A full example for a push of a tag :
     pipelinesascode.tekton.dev/on-event: "[push]"
 ```
 
-This will match the pipeline `pipeline-push-on-1.0-tags` when you push the 1.0 tags
-into your repository.
+This will match the pipeline `pipeline-push-on-1.0-tags` when you push the 1.0 tags into your repository.
 
-Matching annotations are currently mandated or `Pipelines as Code` will not
-match your `PiplineRun`.
+Matching annotations are currently mandated or `Pipelines as Code` will not match your `PiplineRun`.
 
-If there is multiple pipeline matching an event, it will match the first one.
-We are currently not supporting multiple PipelineRuns on a single event but
-this may be something we can consider to implement in the future.
+If there is multiple pipeline matching an event, it will match the first one. We are currently not supporting multiple
+PipelineRuns on a single event but this may be something we can consider to implement in the future.
 
 #### Private repositories
 
-Pipelines as Code support private repositories by creating or updating a secret
-in the target namespace with the user token for the [git-clone](https://github.com/tektoncd/catalog/blob/main/task/git-clone) task to use and
-be able to clone private repositories.
+Pipelines as Code support private repositories by creating or updating a secret in the target namespace with the user
+token for the [git-clone](https://github.com/tektoncd/catalog/blob/main/task/git-clone) task to use and be able to clone
+private repositories.
 
-Whenever Pipelines as Code create a new PipelineRun in the target namespace it
-will create or update a secret called :
+Whenever Pipelines as Code create a new PipelineRun in the target namespace it will create or update a secret called :
 
 `pac-git-basic-auth-REPOSITORY_OWNER-REPOSITORY_NAME`
 
-The secret contains a `.gitconfig` and a git credentials `.git-credentials` with the
-https url using the short lived token generated from the Github application for accessing the private repository.
+The secret contains a `.gitconfig` and a git credentials `.git-credentials` with the https url using the short lived
+token generated from the Github application for accessing the private repository.
 
 As documented :
 
 <https://github.com/tektoncd/catalog/blob/main/task/git-clone/0.4/README.md>
 
-the secret needs to be referenced inside your PipelineRun and Pipeline as a workspace called basic-auth to be passed to the `git-clone` task.
+the secret needs to be referenced inside your PipelineRun and Pipeline as a workspace called basic-auth to be passed to
+the `git-clone` task.
 
 For example in your PipelineRun you will add the workspace referencing the Secret :
 
@@ -275,8 +276,8 @@ tasks:
           value: $(params.revision)
 ```
 
-The git-clone task will pick up the basic-auth (optional) workspace and automatically
-use it to be able to clone the private repository.
+The git-clone task will pick up the basic-auth (optional) workspace and automatically use it to be able to clone the
+private repository.
 
 You can see as well a full example [here](./test/testdata/pipelinerun_git_clone_private.yaml)
 
@@ -285,8 +286,8 @@ This behaviour can be disabled by configuration the `secret-auto-create` key ins
 
 #### PipelineRuns Cleanups
 
-There can be a lot of PipelineRuns into an user namespace and Pipelines as Code
-has the ability to only keep a number of PipelineRuns that matches an event.
+There can be a lot of PipelineRuns into an user namespace and Pipelines as Code has the ability to only keep a number of
+PipelineRuns that matches an event.
 
 For example if the PipelineRun has this annotation :
 
@@ -294,8 +295,8 @@ For example if the PipelineRun has this annotation :
 pipelinesascode.tekton.dev/max-keep-runs: "maxNumber"
 ```
 
-Pipelines as Code sees this and will start cleaning up right after it finishes a
-successful execution keeping only the maxNumber of PipelineRuns.
+Pipelines as Code sees this and will start cleaning up right after it finishes a successful execution keeping only the
+maxNumber of PipelineRuns.
 
 It will skip the `Running` PipelineRuns but will not skip the PipelineRuns with
 `Unknown` status.
@@ -305,29 +306,26 @@ It will skip the `Running` PipelineRuns but will not skip the PipelineRuns with
 If `Pipelines as Code` sees a PipelineRun with a reference to a `Task` or a
 `Pipeline`, it will tries to *resolves* it as a single PipelineRun with an embedded `PipelineSpec` to a `PipelineRun`.
 
-It will as well transform the Pipeline Name  to a `generateName`
+It will as well transform the Pipeline Name to a `generateName`
 based on the Pipeline name as well.
 
-This allows you to have multiple runs in the same namespace from the same
-PipelineRun with no risk of conflicts.
+This allows you to have multiple runs in the same namespace from the same PipelineRun with no risk of conflicts.
 
 Everything that runs your pipelinerun and its references need to be inside the
-`.tekton/` directory or referenced via a remote task (see below on how the remote
-tasks are referenced).
+`.tekton/` directory or referenced via a remote task (see below on how the remote tasks are referenced).
 
-If pipelines as code cannot resolve the referenced tasks in the `Pipeline` or `PipelineSpec` it will fails before applying the pipelinerun onto the cluster.
+If pipelines as code cannot resolve the referenced tasks in the `Pipeline` or `PipelineSpec` it will fails before
+applying the pipelinerun onto the cluster.
 
-If you need to test your `PipelineRun` locally before sending it in a PR, you can use
-the `resolve` command from the `tkn-pac` CLI See the `--help` of the command to learn about
-how to use it.
+If you need to test your `PipelineRun` locally before sending it in a PR, you can use the `resolve` command from
+the `tkn-pac` CLI See the `--help` of the command to learn about how to use it.
 
 #### Remote Task support
 
-`Pipelines as Code` support fetching remote tasks from remote location via
-annotations on PipelineRun.
+`Pipelines as Code` support fetching remote tasks from remote location via annotations on PipelineRun.
 
-If the resolver sees a PipelineRun referencing a remote task via its name in a
-Pipeline or a PipelineSpec it will automatically inlines it.
+If the resolver sees a PipelineRun referencing a remote task via its name in a Pipeline or a PipelineSpec it will
+automatically inlines it.
 
 An annotation to a remote task looks like this :
 
@@ -335,9 +333,10 @@ An annotation to a remote task looks like this :
   pipelinesascode.tekton.dev/task: "[git-clone]"
   ```
 
-this installs the [git-clone](https://github.com/tektoncd/catalog/tree/main/task/git-clone) task from the [tekton hub](https://hub.tekton.dev) repository via its API.
+this installs the [git-clone](https://github.com/tektoncd/catalog/tree/main/task/git-clone) task from
+the [tekton hub](https://hub.tekton.dev) repository via its API.
 
-You can have multiple tasks in there if you separate  them by a comma `,`:
+You can have multiple tasks in there if you separate them by a comma `,`:
 
 ```yaml
 pipelinesascode.tekton.dev/task: "[git-clone, golang-test, tkn]"
@@ -351,9 +350,11 @@ You can have multiple lines if you add a `-NUMBER` suffix to the annotation, for
   pipelinesascode.tekton.dev/task-2: "[tkn]"
 ```
 
-By default `Pipelines as Code` will interpret the string as the `latest` task to grab from [tekton hub](https://hub.tekton.dev).
+By default `Pipelines as Code` will interpret the string as the `latest` task to grab
+from [tekton hub](https://hub.tekton.dev).
 
-If you want to have a specific version of the task, you can add a colon `:` to the string and a version number, like in this example :
+If you want to have a specific version of the task, you can add a colon `:` to the string and a version number, like in
+this example :
 
 ```yaml
   pipelinesascode.tekton.dev/task: "[git-clone:0.1]" # will install git-clone 0.1 from tekton.hub
@@ -366,13 +367,15 @@ will fetch the task directly from that remote url :
   pipelinesascode.tekton.dev/task: "[https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.3/git-clone.yaml]"
 ```
 
-Additionally you can as well a reference to a task from a yaml file inside your repo if you specify the relative path to it, for example :
+Additionally you can as well a reference to a task from a yaml file inside your repo if you specify the relative path to
+it, for example :
 
   ```yaml
   pipelinesascode.tekton.dev/task: "[.tekton/tasks/git-clone.yaml]"
   ```
 
-will grab the `.tekton/tasks/git-clone.yaml` from the current repository on the `SHA` where the event come from (i.e: the current pull request or the current branch push).
+will grab the `.tekton/tasks/git-clone.yaml` from the current repository on the `SHA` where the event come from (i.e:
+the current pull request or the current branch push).
 
 If there is any error fetching those resources, `Pipelines as Code` will error out and not process the pipeline.
 
@@ -382,9 +385,11 @@ If the object fetched cannot be parsed as a Tekton `Task` it will error out.
 
 - A user create a Pull Request.
 
-- If the user sending the Pull Request is not the owner of the repository or not a public member of the organization where the repository belong to, `Pipelines as Code` will not run.
+- If the user sending the Pull Request is not the owner of the repository or not a public member of the organization
+  where the repository belong to, `Pipelines as Code` will not run.
 
-- If the user sending the Pull Request is inside an OWNER file located in the repository root in the main branch (the main branch as defined in the Github configuration for the repo) in the `approvers` or `reviewers` section like this :
+- If the user sending the Pull Request is inside an OWNER file located in the repository root in the main branch (the
+  main branch as defined in the Github configuration for the repo) in the `approvers` or `reviewers` section like this :
 
 ```yaml
 approvers:
@@ -393,7 +398,8 @@ approvers:
 
 then the user `approved` will be allowed.
 
-If the sender of a PR is not allowed to run CI but one of allowed user issue a `/ok-to-test` in any line of a comment the PR will be allowed to run CI.
+If the sender of a PR is not allowed to run CI but one of allowed user issue a `/ok-to-test` in any line of a comment
+the PR will be allowed to run CI.
 
 If the user is allowed, `Pipelines as Code` will start creating the `PipelineRun` in the target user namespace.
 
@@ -410,13 +416,12 @@ Or via your kubernetes UI like the OpenShift console inside your namespace to fo
 
 #### GitHub
 
-When the pipeline finishes the status will be added in the Github Check tabs
-with a short recap of how long each task of your pipeline took and the output of
+When the pipeline finishes the status will be added in the Github Check tabs with a short recap of how long each task of
+your pipeline took and the output of
 `tkn pr describe`.
 
-If there was a failure you can click on the "Re-Run" button on the left to rerun
-the Pipeline or you can issue a issue comment with a line starting and finishing
-with the string `/retest` to ask Pipelines as Code to retest the current PR.
+If there was a failure you can click on the "Re-Run" button on the left to rerun the Pipeline or you can issue a issue
+comment with a line starting and finishing with the string `/retest` to ask Pipelines as Code to retest the current PR.
 
 Example :
 
@@ -429,7 +434,7 @@ The failure is not with your PR but seems to be an infra issue.
 
 #### CRD
 
-Status of  your pipeline execution is stored inside the Repo CustomResource :
+Status of your pipeline execution is stored inside the Repo CustomResource :
 
 ```bash
 % kubectl get repo -n pipelines-as-code-ci
@@ -437,8 +442,7 @@ NAME                  URL
 pipelines-as-code-ci   https://github.com/openshift-pipelines/pipelines-as-code   pipelines-as-code-ci   True        Succeeded   59m         56m
 ```
 
-The last 5 status are stored inside the CustomResource and can be accessed
-directly like this :
+The last 5 status are stored inside the CustomResource and can be accessed directly like this :
 
 ```json
 % kubectl get repo -n pipelines-as-code-ci -o json|jq .items[].pipelinerun_status
@@ -476,14 +480,14 @@ directly like this :
 
 ### Notifications
 
-Notifications is not handled by Pipelines as Code, the only place
-where we notify a status in a interface is when we do a Pull Request on for example the
-Github checks interface to show the results of the pull request.
+Notifications is not handled by Pipelines as Code, the only place where we notify a status in a interface is when we do
+a Pull Request on for example the Github checks interface to show the results of the pull request.
 
-If you need some other type of notification you can use the [finally feature of tekton pipeline](https://github.com/tektoncd/pipeline/blob/main/docs/pipelines.md#adding-finally-to-the-pipeline).
+If you need some other type of notification you can use
+the [finally feature of tekton pipeline](https://github.com/tektoncd/pipeline/blob/main/docs/pipelines.md#adding-finally-to-the-pipeline)
+.
 
-Here is an example task to send a slack message on failures (or
-success if you like) :
+Here is an example task to send a slack message on failures (or success if you like) :
 
 <https://github.com/chmouel/tekton-slack-task-status>
 
@@ -493,7 +497,8 @@ The push pipeline of Pipelines as Code use this task, you can see the example he
 
 ## CLI
 
-`Pipelines as Code` provide a CLI which is design to work as tkn plugin. See the installation instruction in the [INSTALL.md](INSTALL.md#CLI) documentation
+`Pipelines as Code` provide a CLI which is design to work as tkn plugin. See the installation instruction in
+the [INSTALL.md](INSTALL.md#CLI) documentation
 
 ### CLI commands
 
@@ -507,9 +512,8 @@ You can easily create a new repo CR with the command :
 tkn pac repo create
 ```
 
-It will detect your current GIT repo URL and branch your current namespace and
-ask you for a target, it will ask you if you want to create sample pipelinerun
-for you to customize it.
+It will detect your current GIT repo URL and branch your current namespace and ask you for a target, it will ask you if
+you want to create sample pipelinerun for you to customize it.
 
 for example to list all repo status in your system (if you have the right for it) :
 
diff --git a/cmd/pipelines-as-code/main.go b/cmd/pipelines-as-code/main.go
index 29371cd5..475e8282 100644
--- a/cmd/pipelines-as-code/main.go
+++ b/cmd/pipelines-as-code/main.go
@@ -1,36 +1,19 @@
 package main
 
 import (
-	"fmt"
+	"log"
 	"os"
-	"path/filepath"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/pipelineascode"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/tknpac"
-	"github.com/spf13/cobra"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 )
 
-// RouteBinary according to $0
-func RouteBinary(binary string) *cobra.Command {
-	tp := &cli.PacParams{}
-	binary = filepath.Base(binary)
-	if binary == "tkn-pac" {
-		return tknpac.Root(tp)
-	}
-	return pipelineascode.Command(tp)
-}
-
 func main() {
-	executable, err := os.Executable()
-	if err != nil {
-		fmt.Fprint(os.Stderr, err.Error())
-		os.Exit(1)
-	}
-
-	cmd := RouteBinary(executable)
-
+	clients := &params.Run{Info: info.Info{Event: &info.Event{}}}
+	cmd := pipelineascode.Command(clients)
 	if err := cmd.Execute(); err != nil {
+		log.Fatal(err)
 		os.Exit(1)
 	}
 }
diff --git a/cmd/tkn-pac/main.go b/cmd/tkn-pac/main.go
index fbaa32fc..6f6382e6 100644
--- a/cmd/tkn-pac/main.go
+++ b/cmd/tkn-pac/main.go
@@ -3,13 +3,15 @@ package main
 import (
 	"os"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/tknpac"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 )
 
 func main() {
-	tp := &cli.PacParams{}
-	pac := tknpac.Root(tp)
+	clients := &params.Run{}
+	clients.Info.Event = &info.Event{}
+	pac := tknpac.Root(clients)
 
 	if err := pac.Execute(); err != nil {
 		os.Exit(1)
diff --git a/code-of-conduct.md b/code-of-conduct.md
index 5f04b318..3618a6ae 100644
--- a/code-of-conduct.md
+++ b/code-of-conduct.md
@@ -2,17 +2,14 @@
 
 ## Our Pledge
 
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, gender identity and expression, level of
-experience, education, socio-economic status, nationality, personal appearance,
-race, religion, or sexual identity and orientation.
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making
+participation in our project and our community a harassment-free experience for everyone, regardless of age, body size,
+disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity and orientation.
 
 ## Our Standards
 
-Examples of behavior that contributes to creating a positive environment
-include:
+Examples of behavior that contributes to creating a positive environment include:
 
 - Using welcoming and inclusive language
 - Being respectful of differing viewpoints and experiences
@@ -22,54 +19,41 @@ include:
 
 Examples of unacceptable behavior by participants include:
 
-- The use of sexualized language or imagery and unwelcome sexual attention or
-  advances
+- The use of sexualized language or imagery and unwelcome sexual attention or advances
 - Trolling, insulting/derogatory comments, and personal or political attacks
 - Public or private harassment
-- Publishing others' private information, such as a physical or electronic
-  address, without explicit permission
-- Other conduct which could reasonably be considered inappropriate in a
-  professional setting
+- Publishing others' private information, such as a physical or electronic address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a professional setting
 
 ## Our Responsibilities
 
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take
+appropriate and fair corrective action in response to any instances of unacceptable behavior.
 
-Project maintainers have the right and responsibility to remove, edit, or reject
-comments, commits, code, wiki edits, issues, and other contributions that are
-not aligned to this Code of Conduct, or to ban temporarily or permanently any
-contributor for other behaviors that they deem inappropriate, threatening,
-offensive, or harmful.
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
+issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any
+contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
 
 ## Scope
 
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an appointed
-representative at an online or offline event. Representation of a project may be
-further defined and clarified by project maintainers.
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the
+project or its community. Examples of representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed representative at an online or offline
+event. Representation of a project may be further defined and clarified by project maintainers.
 
 ## Enforcement
 
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at
-knative-code-of-conduct@googlegroups.com. All complaints will be reviewed and
-investigated and will result in a response that is deemed necessary and
-appropriate to the circumstances. The project team is obligated to maintain
-confidentiality with regard to the reporter of an incident. Further details of
-specific enforcement policies may be posted separately.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at
+knative-code-of-conduct@googlegroups.com. All complaints will be reviewed and investigated and will result in a response
+that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality
+with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
 
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent
+repercussions as determined by other members of the project's leadership.
 
 ## Attribution
 
-This Code of Conduct is adapted from the [Contributor Covenant][homepage],
-version 1.4, available at
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at
 https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
 
 [homepage]: https://www.contributor-covenant.org
diff --git a/config/401-trigger-issue-recheck.yaml b/config/401-trigger-issue-recheck.yaml
index 7e3d9d24..8e1faa74 100644
--- a/config/401-trigger-issue-recheck.yaml
+++ b/config/401-trigger-issue-recheck.yaml
@@ -176,16 +176,22 @@ spec:
                     imagePullPolicy: Always
                     image: "ko://github.com/openshift-pipelines/pipelines-as-code/cmd/pipelines-as-code"
                     env:
-                    - name: PAC_APPLICATION_NAME
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: application-name
-                    - name: PAC_SECRET_AUTO_CREATE
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: secret-auto-create
+                      - name: PAC_APPLICATION_NAME
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: application-name
+                      - name: PAC_SECRET_AUTO_CREATE
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: secret-auto-create
+                      - name: PAC_WEBVCS_URL
+                        value: $(params.ghe_host)
+                      - name: PAC_WEBVCS_TOKEN
+                        value: $(params.token)
+                      - name: PAC_WEBVCS_TYPE
+                        value: "github"
                     script: |
                       #!/usr/bin/env bash
                       set -eux
@@ -214,11 +220,10 @@ spec:
                         }
                       }
                       EOF
+                      env|grep '^PAC'|sed 's/TOKEN=.*/TOKEN=HIDDENTOKEN/'
                       cat /tmp/payload.json
-                      pipelines-as-code --trigger-target=$(params.trigger_target) \
-                        --api-url="$(params.ghe_host)" \
-                        --payload-file=/tmp/payload.json --token="$(params.token)" --webhook-type="$(params.event_type)"
-
+                      pipelines-as-code --trigger-target=$(params.trigger_target) --webhook-type="$(params.event_type)" \
+                        --payload-file=/tmp/payload.json
               params:
                 - name: ghe_host
                   value: $(params.ghe_host)
diff --git a/config/402-trigger-pull-request.yaml b/config/402-trigger-pull-request.yaml
index edcbc890..ff3839e8 100644
--- a/config/402-trigger-pull-request.yaml
+++ b/config/402-trigger-pull-request.yaml
@@ -165,16 +165,22 @@ spec:
                 steps:
                   - name: apply-and-launch
                     env:
-                    - name: PAC_APPLICATION_NAME
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: application-name
-                    - name: PAC_SECRET_AUTO_CREATE
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: secret-auto-create
+                      - name: PAC_APPLICATION_NAME
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: application-name
+                      - name: PAC_SECRET_AUTO_CREATE
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: secret-auto-create
+                      - name: PAC_WEBVCS_URL
+                        value: $(params.ghe_host)
+                      - name: PAC_WEBVCS_TOKEN
+                        value: $(params.token)
+                      - name: PAC_WEBVCS_TYPE
+                        value: "github"
                     imagePullPolicy: Always
                     image: "ko://github.com/openshift-pipelines/pipelines-as-code/cmd/pipelines-as-code"
                     script: |
@@ -202,10 +208,10 @@ spec:
                           }
                       }
                       EOF
+                      env|grep '^PAC'|sed 's/TOKEN=.*/TOKEN=HIDDENTOKEN/'
                       cat /tmp/payload.json
                       pipelines-as-code --trigger-target=$(params.trigger_target) \
-                        --api-url="$(params.ghe_host)" \
-                        --payload-file=/tmp/payload.json --token="$(params.token)" \
+                        --payload-file=/tmp/payload.json  \
                         --webhook-type="$(params.event_type)"
               params:
                 - name: ghe_host
diff --git a/config/403-trigger-push.yaml b/config/403-trigger-push.yaml
index 57802ad2..d3fe10af 100644
--- a/config/403-trigger-push.yaml
+++ b/config/403-trigger-push.yaml
@@ -167,16 +167,22 @@ spec:
                     imagePullPolicy: Always
                     image: "ko://github.com/openshift-pipelines/pipelines-as-code/cmd/pipelines-as-code"
                     env:
-                    - name: PAC_APPLICATION_NAME
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: application-name
-                    - name: PAC_SECRET_AUTO_CREATE
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: secret-auto-create
+                      - name: PAC_APPLICATION_NAME
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: application-name
+                      - name: PAC_SECRET_AUTO_CREATE
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: secret-auto-create
+                      - name: PAC_WEBVCS_URL
+                        value: $(params.ghe_host)
+                      - name: PAC_WEBVCS_TOKEN
+                        value: $(params.token)
+                      - name: PAC_WEBVCS_TYPE
+                        value: "github"
                     script: |
                       cat << EOF > /tmp/payload.json
                       {
@@ -197,9 +203,10 @@ spec:
                         }
                       }
                       EOF
-                      pipelines-as-code --trigger-target=$(params.trigger_target) \
-                        --api-url="$(params.ghe_host)" \
-                        --payload-file=/tmp/payload.json --token="$(params.token)" --webhook-type="$(params.event_type)"
+                      env|grep '^PAC'|sed 's/TOKEN=.*/TOKEN=HIDDENTOKEN/'
+                      cat /tmp/payload.json
+                      pipelines-as-code --trigger-target=$(params.trigger_target) --webhook-type="$(params.event_type)" \
+                      --payload-file=/tmp/payload.json
               params:
                 - name: ghe_host
                   value: $(params.ghe_host)
diff --git a/hack/tools.go b/hack/tools.go
index 5c2bad81..a85a4589 100644
--- a/hack/tools.go
+++ b/hack/tools.go
@@ -1,3 +1,4 @@
+//go:build tools
 // +build tools
 
 /*
diff --git a/pkg/cli/interface.go b/pkg/cli/interface.go
deleted file mode 100644
index e4bcf1e3..00000000
--- a/pkg/cli/interface.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package cli
-
-import (
-	"context"
-	"net/http"
-	"time"
-
-	pacversioned "github.com/openshift-pipelines/pipelines-as-code/pkg/generated/clientset/versioned"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
-	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
-	tektonversioned "github.com/tektoncd/pipeline/pkg/client/clientset/versioned"
-	tektonv1beta1client "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/typed/pipeline/v1beta1"
-	"go.uber.org/zap"
-	"k8s.io/client-go/dynamic"
-	k8s "k8s.io/client-go/kubernetes"
-)
-
-type Clients struct {
-	PipelineAsCode pacversioned.Interface
-	Tekton         tektonversioned.Interface
-	Kube           k8s.Interface
-	HTTPClient     http.Client
-	Log            *zap.SugaredLogger
-	GithubClient   webvcs.GithubVCS
-	Dynamic        dynamic.Interface
-}
-
-type Params interface {
-	// SetKubeConfigPath uses the kubeconfig path to instantiate tekton
-	// returned by Clientset function
-	SetKubeConfigPath(string)
-
-	// SetGitHubToken Set github token TODO: rename to a generic vcs
-	SetGitHubToken(string)
-
-	// SetGitAPIURL Set github token TODO: rename to a generic vcs
-	SetGitHubAPIURL(string)
-
-	// GetNamespace Get namesace
-	GetNamespace() string
-
-	Clients() (*Clients, error)
-	KubeClient() (k8s.Interface, error)
-}
-
-type KubeInteractionIntf interface {
-	GetConsoleUI(context.Context, string, string) (string, error)
-	GetNamespace(context.Context, string) error
-	// TODO: we don't need tektonv1beta1client stuff here
-	WaitForPipelineRunSucceed(context.Context, tektonv1beta1client.TektonV1beta1Interface, *v1beta1.PipelineRun, time.Duration) error
-	CleanupPipelines(context.Context, string, string, int) error
-	CreateBasicAuthSecret(context.Context, webvcs.RunInfo, string) error
-}
diff --git a/pkg/cli/params.go b/pkg/cli/params.go
deleted file mode 100644
index 2fcdb4ce..00000000
--- a/pkg/cli/params.go
+++ /dev/null
@@ -1,169 +0,0 @@
-package cli
-
-import (
-	"github.com/pkg/errors"
-	tektonversioned "github.com/tektoncd/pipeline/pkg/client/clientset/versioned"
-
-	pacversioned "github.com/openshift-pipelines/pipelines-as-code/pkg/generated/clientset/versioned"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
-	"go.uber.org/zap"
-	"k8s.io/client-go/dynamic"
-	k8s "k8s.io/client-go/kubernetes"
-	"k8s.io/client-go/rest"
-	"k8s.io/client-go/tools/clientcmd"
-)
-
-type PacParams struct {
-	clients        *Clients
-	kubeConfigPath string
-	kubeContext    string
-	namespace      string
-	githubToken    string
-	githubAPIURL   string
-}
-
-var _ Params = (*PacParams)(nil)
-
-func (p *PacParams) GetNamespace() string {
-	return p.namespace
-}
-
-func (p *PacParams) SetKubeConfigPath(path string) {
-	p.kubeConfigPath = path
-}
-
-func (p *PacParams) SetGitHubToken(token string) {
-	p.githubToken = token
-}
-
-func (p *PacParams) SetGitHubAPIURL(url string) {
-	p.githubAPIURL = url
-}
-
-// Set kube client based on config
-func (p *PacParams) kubeClient(config *rest.Config) (k8s.Interface, error) {
-	k8scs, err := k8s.NewForConfig(config)
-	if err != nil {
-		return nil, errors.Wrapf(err, "failed to create k8s client from config")
-	}
-
-	return k8scs, nil
-}
-
-func (p *PacParams) dynamicClient(config *rest.Config) (dynamic.Interface, error) {
-	dynamicClient, err := dynamic.NewForConfig(config)
-	if err != nil {
-		return nil, errors.Wrapf(err, "failed to create dynamic client from config")
-	}
-	return dynamicClient, err
-}
-
-func (p *PacParams) config() (*rest.Config, error) {
-	loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
-	if p.kubeConfigPath != "" {
-		loadingRules.ExplicitPath = p.kubeConfigPath
-	}
-	configOverrides := &clientcmd.ConfigOverrides{}
-	if p.kubeContext != "" {
-		configOverrides.CurrentContext = p.kubeContext
-	}
-	kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
-	if p.namespace == "" {
-		namespace, _, err := kubeConfig.Namespace()
-		if err != nil {
-			return nil, errors.Wrap(err, "Couldn't get kubeConfiguration namespace")
-		}
-		p.namespace = namespace
-	}
-	config, err := kubeConfig.ClientConfig()
-	if err != nil {
-		return nil, errors.Wrap(err, "Parsing kubeconfig failed")
-	}
-	return config, nil
-}
-
-func (p *PacParams) tektonClient(config *rest.Config) (tektonversioned.Interface, error) {
-	cs, err := tektonversioned.NewForConfig(config)
-	if err != nil {
-		return nil, err
-	}
-
-	return cs, nil
-}
-
-func (p *PacParams) pacClient(config *rest.Config) (pacversioned.Interface, error) {
-	cs, err := pacversioned.NewForConfig(config)
-	if err != nil {
-		return nil, err
-	}
-
-	return cs, nil
-}
-
-func (p *PacParams) githubClient() webvcs.GithubVCS {
-	return webvcs.NewGithubVCS(p.githubToken, p.githubAPIURL)
-}
-
-// KubeClient returns only the kube client, not the tekton client
-func (p *PacParams) KubeClient() (k8s.Interface, error) {
-	config, err := p.config()
-	if err != nil {
-		return nil, err
-	}
-
-	kube, err := p.kubeClient(config)
-	if err != nil {
-		return nil, err
-	}
-
-	return kube, nil
-}
-
-func (p *PacParams) Clients() (*Clients, error) {
-	if p.clients != nil {
-		return p.clients, nil
-	}
-
-	prod, _ := zap.NewProduction()
-	logger := prod.Sugar()
-	defer func() {
-		_ = logger.Sync() // flushes buffer, if any
-	}()
-	config, err := p.config()
-	if err != nil {
-		return nil, err
-	}
-
-	kube, err := p.kubeClient(config)
-	if err != nil {
-		return nil, err
-	}
-
-	tekton, err := p.tektonClient(config)
-	if err != nil {
-		return nil, err
-	}
-
-	pacc, err := p.pacClient(config)
-	if err != nil {
-		return nil, err
-	}
-
-	ghClient := p.githubClient()
-
-	dynamic, err := p.dynamicClient(config)
-	if err != nil {
-		return nil, err
-	}
-
-	p.clients = &Clients{
-		Tekton:         tekton,
-		Kube:           kube,
-		PipelineAsCode: pacc,
-		Log:            logger,
-		GithubClient:   ghClient,
-		Dynamic:        dynamic,
-	}
-
-	return p.clients, nil
-}
diff --git a/pkg/cmd/pipelineascode/pipelineascode.go b/pkg/cmd/pipelineascode/pipelineascode.go
index 8c6ce358..05eb9445 100644
--- a/pkg/cmd/pipelineascode/pipelineascode.go
+++ b/pkg/cmd/pipelineascode/pipelineascode.go
@@ -5,128 +5,104 @@ import (
 	"fmt"
 	"io/ioutil"
 	"os"
-	"strings"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction"
-	pacpkg "github.com/openshift-pipelines/pipelines-as-code/pkg/pipelineascode"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/pipelineascode"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs/github"
+
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/spf13/cobra"
 )
 
 const (
-	defaultURL             = "https://giphy.com/explore/cat"
-	defaultApplicationName = "Pipelines as Code CI"
+	defaultURL = "https://giphy.com/explore/cat"
 )
 
-func Command(p cli.Params) *cobra.Command {
-	opts := &pacpkg.Options{}
+func Command(cs *params.Run) *cobra.Command {
 	cmd := &cobra.Command{
-		Use:   "pipelines-as-code",
-		Short: "Pipelines as code Run",
-		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
-			return flags.GetWebCVSOptions(p, cmd)
-		},
+		Use:          "pipelines-as-code",
+		Short:        "Pipelines as code Run",
 		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			token, err := cmd.LocalFlags().GetString("token")
-			if token == "" || err != nil {
-				return fmt.Errorf("token option is not set properly")
-			}
-			cs, err := p.Clients()
+			err := cs.Clients.NewClients(&cs.Info)
 			if err != nil {
 				return err
 			}
+
 			kinteract, err := kubeinteraction.NewKubernetesInteraction(cs)
 			if err != nil {
 				return err
 			}
-
 			ctx := context.Background()
-			return runWrap(ctx, opts, cs, kinteract)
+			vcsintf, err := getVCS(ctx, cs.Info.Pac)
+			if err != nil {
+				return err
+			}
+			return runWrap(ctx, cs, vcsintf, kinteract)
 		},
 	}
 
-	flags.AddPacOptions(cmd)
-	flags.AddWebCVSOptions(cmd)
-
-	cmd.Flags().StringVarP(&opts.RunInfo.EventType, "webhook-type", "", os.Getenv("PAC_EVENT_TYPE"), "Payload event type as set from Github (ie: X-GitHub-Event header)")
-	cmd.Flags().StringVarP(&opts.RunInfo.TriggerTarget, "trigger-target", "", os.Getenv("PAC_TRIGGER_TARGET"), "The trigger target from where this event comes from")
-	cmd.Flags().StringVarP(&opts.PayloadFile, "payload-file", "", os.Getenv("PAC_PAYLOAD_FILE"), "A file containing the webhook payload")
+	cs.Info.Pac.AddFlags(cmd)
+	cs.Info.Kube.AddFlags(cmd)
 
-	applicationName := os.Getenv("PAC_APPLICATION_NAME")
-	if applicationName == "" {
-		applicationName = defaultApplicationName
-	}
-	cmd.Flags().StringVar(&opts.RunInfo.ApplicationName,
-		"application-name", applicationName,
-		"The name of the application.")
-
-	secretAutoCreation := false
-	secretAutoCreationEnv := os.Getenv("PAC_SECRET_AUTO_CREATE")
-	if strings.ToLower(secretAutoCreationEnv) == "true" ||
-		strings.ToLower(secretAutoCreationEnv) == "yes" || secretAutoCreationEnv == "1" {
-		secretAutoCreation = true
-	}
-	cmd.Flags().BoolVar(&opts.RunInfo.SecretAutoCreation,
-		"secret-auto-creation",
-		secretAutoCreation,
-		"Wether to create automatically secrets.")
+	cmd.Flags().StringVarP(&cs.Info.Event.EventType, "webhook-type", "", os.Getenv("PAC_EVENT_TYPE"), "Payload event type as set from Github (ie: X-GitHub-Event header)")
+	cmd.Flags().StringVarP(&cs.Info.Event.TriggerTarget, "trigger-target", "", os.Getenv("PAC_TRIGGER_TARGET"), "The trigger target from where this event comes from")
 
 	return cmd
 }
 
-func parsePayload(ctx context.Context, cs *cli.Clients, opts *pacpkg.Options) (*webvcs.RunInfo, error) {
+func getPayloadFromFile(opts info.PacOpts) (string, error) {
 	if opts.PayloadFile == "" {
-		return nil, fmt.Errorf("no payload file has been passed")
+		return "", fmt.Errorf("no payload file has been passed")
 	}
 	_, err := os.Stat(opts.PayloadFile)
 	if err != nil {
-		return nil, err
+		return "", err
 	}
 
 	payloadB, err := ioutil.ReadFile(opts.PayloadFile)
-	if err != nil {
-		return nil, err
-	}
+	return string(payloadB), err
+}
 
-	payloadinfo, err := cs.GithubClient.ParsePayload(ctx, cs.Log, opts.RunInfo, string(payloadB))
-	if err != nil {
-		return &webvcs.RunInfo{}, err
+func getVCS(ctx context.Context, pacopts info.PacOpts) (webvcs.Interface, error) {
+	switch pacopts.VCSType {
+	case "github":
+		return github.NewGithubVCS(ctx, pacopts), nil
+	default:
+		return nil, fmt.Errorf("no supported VCS is detected")
 	}
-	payloadinfo.ApplicationName = opts.RunInfo.ApplicationName
+}
 
-	if err := payloadinfo.Check(); err != nil {
-		return &webvcs.RunInfo{}, fmt.Errorf("invalid Payload, missing some values : %+v", payloadinfo)
-	}
+func runWrap(ctx context.Context, cs *params.Run, vcx webvcs.Interface, kinteract kubeinteraction.Interface) error {
+	var err error
 
-	return payloadinfo, nil
-}
+	cs.Info.Pac.LogURL, err = kinteract.GetConsoleUI(ctx, "", "")
+	if err != nil {
+		cs.Clients.Log.Warn("could not detect a Console URL, skipping")
+		cs.Info.Pac.LogURL = defaultURL
+	}
 
-// Wrap around a Run, create a CheckStatusID if there is a failure.
-func runWrap(ctx context.Context, opts *pacpkg.Options, cs *cli.Clients, kinteract cli.KubeInteractionIntf) error {
-	runinfo, err := parsePayload(ctx, cs, opts)
+	payload, err := getPayloadFromFile(cs.Info.Pac)
 	if err != nil {
 		return err
 	}
 
-	// Get webconsole url as soon as possible to have a link to click there
-	url, err := kinteract.GetConsoleUI(ctx, "", "")
+	cs.Info.Event, err = vcx.ParsePayload(ctx, cs.Clients.Log, cs.Info.Event, payload)
 	if err != nil {
-		cs.Log.Error(err)
-		url = defaultURL
+		return err
 	}
-	runinfo.LogURL = url
-
-	err = pacpkg.Run(ctx, cs, kinteract, runinfo)
+	err = pipelineascode.Run(ctx, cs, vcx, kinteract)
 	if err != nil {
-		if runinfo.CheckRunID != nil && !strings.Contains(err.Error(), "403 Resource not accessible by integration") {
-			_, _ = cs.GithubClient.CreateStatus(ctx, runinfo, "completed", "failure",
-				fmt.Sprintf("There was an issue validating the commit: %q", err),
-				runinfo.LogURL)
-		} else {
-			cs.Log.Debug("There was an error: %s", err.Error())
+		createStatusErr := vcx.CreateStatus(ctx, cs.Info.Event, cs.Info.Pac, webvcs.StatusOpts{
+			Status:     "completed",
+			Conclusion: "failure",
+			Text:       fmt.Sprintf("There was an issue validating the commit: %q", err),
+			DetailsURL: "",
+		})
+		if createStatusErr != nil {
+			cs.Clients.Log.Errorf("Cannot create status: %s %s", err, createStatusErr)
 		}
 	}
 	return err
diff --git a/pkg/cmd/repository/create.go b/pkg/cmd/repository/create.go
index dc542a39..4f0f539e 100644
--- a/pkg/cmd/repository/create.go
+++ b/pkg/cmd/repository/create.go
@@ -10,10 +10,9 @@ import (
 
 	"github.com/AlecAivazis/survey/v2"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli/ui"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/git"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/ui"
 	"github.com/spf13/cobra"
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -29,12 +28,12 @@ type CreateOptions struct {
 	CurrentNS string
 
 	IOStreams *ui.IOStreams
-	Clients   *cli.Clients
-	CLIOpts   *flags.CliOpts
+	Run       *params.Run
+	CLIOpts   *params.PacCliOpts
 	AssumeYes bool
 }
 
-func CreateCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
+func CreateCommand(run *params.Run, ioStreams *ui.IOStreams) *cobra.Command {
 	createOpts := CreateOptions{}
 	cmd := &cobra.Command{
 		Use:     "create",
@@ -43,16 +42,17 @@ func CreateCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			var err error
 			createOpts.IOStreams = ioStreams
-			createOpts.CLIOpts, err = flags.NewCliOptions(cmd)
+			createOpts.CLIOpts, err = params.NewCliOptions(cmd)
 			if err != nil {
 				return err
 			}
 			createOpts.IOStreams.SetColorEnabled(!createOpts.CLIOpts.NoColoring)
-			createOpts.Clients, err = p.Clients()
+			err = run.Clients.NewClients(&run.Info)
 			if err != nil {
 				return err
 			}
-			createOpts.CurrentNS = p.GetNamespace()
+			createOpts.Run = run
+			createOpts.CurrentNS = run.Info.Kube.Namespace
 			cwd, err := os.Getwd()
 			if err != nil {
 				return err
@@ -301,7 +301,7 @@ func create(ctx context.Context, gitdir string, opts CreateOptions) error {
 			return err
 		}
 	}
-	_, err = opts.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(opts.Namespace).Create(ctx,
+	_, err = opts.Run.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(opts.Namespace).Create(ctx,
 		&v1alpha1.Repository{
 			ObjectMeta: metav1.ObjectMeta{
 				Name: opts.RepositoryName,
@@ -365,7 +365,7 @@ func askNameForResource(opts CreateOptions, question string) (string, error) {
 }
 
 func askCreateNamespace(ctx context.Context, opts CreateOptions, cs *ui.ColorScheme) error {
-	_, err := opts.Clients.Kube.CoreV1().Namespaces().Get(ctx, opts.Namespace, metav1.GetOptions{})
+	_, err := opts.Run.Clients.Kube.CoreV1().Namespaces().Get(ctx, opts.Namespace, metav1.GetOptions{})
 	if err != nil {
 		fmt.Fprintf(opts.IOStreams.Out, "%s Namespace %s is not created yet\n",
 			cs.WarningIcon(),
@@ -380,7 +380,7 @@ func askCreateNamespace(ctx context.Context, opts CreateOptions, cs *ui.ColorSch
 		if !createNamespace {
 			return fmt.Errorf("you need to create the target namespace")
 		}
-		_, err = opts.Clients.Kube.CoreV1().Namespaces().Create(ctx,
+		_, err = opts.Run.Clients.Kube.CoreV1().Namespaces().Create(ctx,
 			&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: opts.Namespace}},
 			metav1.CreateOptions{})
 		if err != nil {
diff --git a/pkg/cmd/repository/describe.go b/pkg/cmd/repository/describe.go
index ddee0a05..8d5e5a15 100644
--- a/pkg/cmd/repository/describe.go
+++ b/pkg/cmd/repository/describe.go
@@ -10,10 +10,9 @@ import (
 	"github.com/AlecAivazis/survey/v2"
 	"github.com/jonboulle/clockwork"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli/ui"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/completion"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/ui"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/pipelineascode"
 	"github.com/spf13/cobra"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -66,8 +65,8 @@ func formatStatus(status v1alpha1.RepositoryRunStatus, cs *ui.ColorScheme, c clo
 		cs.ColorStatus(status.Status.Conditions[0].Reason))
 }
 
-func askRepo(ctx context.Context, cs *cli.Clients, opts *flags.CliOpts, namespace string) (*v1alpha1.Repository, error) {
-	repositories, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(namespace).List(ctx, metav1.ListOptions{})
+func askRepo(ctx context.Context, cs *params.Run, opts *params.PacCliOpts, namespace string) (*v1alpha1.Repository, error) {
+	repositories, err := cs.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(namespace).List(ctx, metav1.ListOptions{})
 	if err != nil {
 		return nil, err
 	}
@@ -120,7 +119,7 @@ func askRepo(ctx context.Context, cs *cli.Clients, opts *flags.CliOpts, namespac
 	return nil, fmt.Errorf("cannot match repository")
 }
 
-func DescribeCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
+func DescribeCommand(run *params.Run, ioStreams *ui.IOStreams) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:     "describe",
 		Aliases: []string{"desc"},
@@ -131,7 +130,7 @@ func DescribeCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
 		ValidArgsFunction: completion.ParentCompletion,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			var repoName string
-			opts, err := flags.NewCliOptions(cmd)
+			opts, err := params.NewCliOptions(cmd)
 			if err != nil {
 				return err
 			}
@@ -147,12 +146,12 @@ func DescribeCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
 
 			ctx := context.Background()
 			clock := clockwork.NewRealClock()
-			cs, err := p.Clients()
+			err = run.Clients.NewClients(&run.Info)
 			if err != nil {
 				return err
 			}
 			ioStreams.SetColorEnabled(!opts.NoColoring)
-			return describe(ctx, cs, clock, opts, ioStreams, p.GetNamespace(), repoName)
+			return describe(ctx, run, clock, opts, ioStreams, repoName)
 		},
 	}
 
@@ -168,23 +167,23 @@ func DescribeCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
 	return cmd
 }
 
-func describe(ctx context.Context, cs *cli.Clients, clock clockwork.Clock, opts *flags.CliOpts,
-	ioStreams *ui.IOStreams, namespace, repoName string) error {
+func describe(ctx context.Context, cs *params.Run, clock clockwork.Clock, opts *params.PacCliOpts,
+	ioStreams *ui.IOStreams, repoName string) error {
 	var repository *v1alpha1.Repository
 	var err error
 
 	if opts.Namespace != "" {
-		namespace = opts.Namespace
+		cs.Info.Kube.Namespace = opts.Namespace
 	}
 
 	if repoName != "" {
-		repository, err = cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(namespace).Get(ctx,
+		repository, err = cs.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(cs.Info.Kube.Namespace).Get(ctx,
 			repoName, metav1.GetOptions{})
 		if err != nil {
 			return err
 		}
 	} else {
-		repository, err = askRepo(ctx, cs, opts, namespace)
+		repository, err = askRepo(ctx, cs, opts, cs.Info.Kube.Namespace)
 		if err != nil {
 			return err
 		}
diff --git a/pkg/cmd/repository/list.go b/pkg/cmd/repository/list.go
index 3215d5ca..83f0f6a9 100644
--- a/pkg/cmd/repository/list.go
+++ b/pkg/cmd/repository/list.go
@@ -6,10 +6,9 @@ import (
 	"text/tabwriter"
 
 	"github.com/jonboulle/clockwork"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli/ui"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/completion"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/ui"
 	"github.com/spf13/cobra"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
@@ -22,7 +21,7 @@ var (
 	noColorFlag       = "no-color"
 )
 
-func ListCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
+func ListCommand(run *params.Run, ioStreams *ui.IOStreams) *cobra.Command {
 	var noheaders, allNamespaces bool
 	var selectors string
 
@@ -31,7 +30,7 @@ func ListCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
 		Aliases: []string{"ls"},
 		Short:   "List repositories",
 		RunE: func(cmd *cobra.Command, args []string) error {
-			opts, err := flags.NewCliOptions(cmd)
+			opts, err := params.NewCliOptions(cmd)
 			if err != nil {
 				return err
 			}
@@ -46,13 +45,13 @@ func ListCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
 			}
 			ioStreams.SetColorEnabled(!opts.NoColoring)
 
-			cs, err := p.Clients()
+			err = run.Clients.NewClients(&run.Info)
 			if err != nil {
 				return err
 			}
 			ctx := context.Background()
 			cw := clockwork.NewRealClock()
-			return list(ctx, cs, opts, ioStreams, cw, p.GetNamespace(), selectors, noheaders)
+			return list(ctx, run, opts, ioStreams, cw, selectors, noheaders)
 		},
 	}
 
@@ -81,20 +80,17 @@ func ListCommand(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command {
 	return cmd
 }
 
-func list(ctx context.Context, cs *cli.Clients, opts *flags.CliOpts, ioStreams *ui.IOStreams,
-	cw clockwork.Clock,
-	currentNamespace, selectors string,
-	noheaders bool) error {
+func list(ctx context.Context, cs *params.Run, opts *params.PacCliOpts, ioStreams *ui.IOStreams, cw clockwork.Clock, selectors string, noheaders bool) error {
 	if opts.Namespace != "" {
-		currentNamespace = opts.Namespace
+		cs.Info.Kube.Namespace = opts.Namespace
 	}
 	if opts.AllNameSpaces {
-		currentNamespace = ""
+		cs.Info.Kube.Namespace = ""
 	}
 
 	lopt := metav1.ListOptions{LabelSelector: selectors}
 
-	repositories, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(currentNamespace).List(
+	repositories, err := cs.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(cs.Info.Kube.Namespace).List(
 		ctx, lopt)
 	if err != nil {
 		return err
diff --git a/pkg/cmd/repository/root.go b/pkg/cmd/repository/root.go
index 0827823b..39066206 100644
--- a/pkg/cmd/repository/root.go
+++ b/pkg/cmd/repository/root.go
@@ -1,12 +1,12 @@
 package repository
 
 import (
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli/ui"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/ui"
 	"github.com/spf13/cobra"
 )
 
-func Root(p cli.Params) *cobra.Command {
+func Root(clients *params.Run) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "repository",
 		Aliases:      []string{"repo", "repsitories"},
@@ -16,9 +16,9 @@ func Root(p cli.Params) *cobra.Command {
 	}
 	ioStreams := ui.NewIOStreams()
 
-	cmd.AddCommand(ListCommand(p, ioStreams))
-	cmd.AddCommand(DescribeCommand(p, ioStreams))
-	cmd.AddCommand(CreateCommand(p, ioStreams))
+	cmd.AddCommand(ListCommand(clients, ioStreams))
+	cmd.AddCommand(DescribeCommand(clients, ioStreams))
+	cmd.AddCommand(CreateCommand(clients, ioStreams))
 
 	return cmd
 }
diff --git a/pkg/cmd/resolve/resolve.go b/pkg/cmd/resolve/resolve.go
index 8d3568a7..a5f93f16 100644
--- a/pkg/cmd/resolve/resolve.go
+++ b/pkg/cmd/resolve/resolve.go
@@ -9,18 +9,17 @@ import (
 	"path/filepath"
 	"strings"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/pipelineascode"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/resolve"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs/github"
 	"github.com/spf13/cobra"
 	"sigs.k8s.io/yaml"
 )
 
 var (
 	filenames    []string
-	params       []string
+	parameters   []string
 	skipInlining []string
 	generateName bool
 	remoteTask   bool
@@ -54,16 +53,13 @@ pipelines-as-code resolve -f .tekton/
 *It does not support task from local directory referenced in annotations at the
  moment*.`
 
-func Command(p cli.Params) *cobra.Command {
+func Command(run *params.Run) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "resolve",
 		Long:  longhelp,
 		Short: "Embed PipelineRun references as a single resource.",
-		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
-			return flags.GetWebCVSOptions(p, cmd)
-		},
 		RunE: func(cmd *cobra.Command, args []string) error {
-			cs, err := p.Clients()
+			err := run.Clients.NewClients(&run.Info)
 			if err != nil {
 				// this check allows resolve to be run without
 				// a kubeconfig so users can verify the tkn version
@@ -75,13 +71,13 @@ func Command(p cli.Params) *cobra.Command {
 			if len(filenames) == 0 {
 				return fmt.Errorf("you need to at least specify a file with -f")
 			}
-			s, err := resolveFilenames(cs, filenames, params)
+			s, err := resolveFilenames(run, filenames, parameters)
 			// nolint: forbidigo
 			fmt.Println(s)
 			return err
 		},
 	}
-	cmd.Flags().StringSliceVarP(&params, "params", "p", filenames,
+	cmd.Flags().StringSliceVarP(&parameters, "params", "p", filenames,
 		"Params to resolve")
 	cmd.Flags().StringSliceVarP(&filenames, "filename", "f", filenames,
 		"Filename, directory, or URL to files to use to create the resource")
@@ -91,8 +87,7 @@ func Command(p cli.Params) *cobra.Command {
 		"Wether to switch name to a generateName on pipelinerun")
 	cmd.Flags().BoolVar(&remoteTask, "remoteTask", true,
 		"Wether parse annotation to fetch remote task")
-	flags.AddPacOptions(cmd)
-	flags.AddWebCVSOptions(cmd)
+	run.Info.Pac.AddFlags(cmd)
 
 	return cmd
 }
@@ -106,20 +101,21 @@ func splitArgsInMap(args []string) map[string]string {
 	return m
 }
 
-func resolveFilenames(cs *cli.Clients, filenames []string, params []string) (string, error) {
+func resolveFilenames(cs *params.Run, filenames []string, params []string) (string, error) {
 	var ret string
 
 	allTemplates := enumerateFiles(filenames)
 	// TODO: flags
 	allTemplates = pipelineascode.ReplacePlaceHoldersVariables(allTemplates, splitArgsInMap(params))
 	ctx := context.Background()
-	runinfo := &webvcs.RunInfo{}
 	ropt := &resolve.Opts{
 		GenerateName: generateName,
 		RemoteTasks:  remoteTask,
 		SkipInlining: skipInlining,
 	}
-	prun, err := resolve.Resolve(ctx, cs, runinfo, allTemplates, ropt)
+	// We use github here but since we don't do remotetask we would not care
+	vcsintf := github.NewGithubVCS(ctx, cs.Info.Pac)
+	prun, err := resolve.Resolve(ctx, cs, vcsintf, allTemplates, ropt)
 	if err != nil {
 		return "", err
 	}
diff --git a/pkg/cmd/tknpac/root.go b/pkg/cmd/tknpac/root.go
index 5dc92679..4e9fe03a 100644
--- a/pkg/cmd/tknpac/root.go
+++ b/pkg/cmd/tknpac/root.go
@@ -1,28 +1,24 @@
 package tknpac
 
 import (
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/completion"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/repository"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/cmd/resolve"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/spf13/cobra"
 )
 
-func Root(p cli.Params) *cobra.Command {
+func Root(clients *params.Run) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:          "tkn-pac",
 		Short:        "Pipelines as Code CLI",
-		Long:         `This is the Pipelines as Code CLI`,
+		Long:         `This is the the tkn plugin for Pipelines as Code CLI`,
 		SilenceUsage: true,
-		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
-			return flags.InitParams(p, cmd)
-		},
 	}
-	flags.AddPacOptions(cmd)
+	clients.Info.Kube.AddFlags(cmd)
 
-	cmd.AddCommand(repository.Root(p))
-	cmd.AddCommand(resolve.Command(p))
+	cmd.AddCommand(repository.Root(clients))
+	cmd.AddCommand(resolve.Command(clients))
 	cmd.AddCommand(completion.Command())
 
 	return cmd
diff --git a/pkg/consoleui/consoleui.go b/pkg/consoleui/consoleui.go
index 94cf8fdf..0871d72b 100644
--- a/pkg/consoleui/consoleui.go
+++ b/pkg/consoleui/consoleui.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"fmt"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 )
@@ -20,9 +20,12 @@ const (
 
 // getOpenshiftConsole use dynamic client to get the route of the openshift
 // console where we can point to.
-func getOpenshiftConsole(ctx context.Context, cs *cli.Clients, ns, pr string) (string, error) {
-	gvr := schema.GroupVersionResource{Group: openShiftRouteGroup, Version: openShiftRouteVersion, Resource: openShiftRouteResource}
-	route, err := cs.Dynamic.Resource(gvr).Namespace(openShiftConsoleNS).Get(ctx, openShiftConsoleRouteName, metav1.GetOptions{})
+func getOpenshiftConsole(ctx context.Context, cs *params.Run, ns, pr string) (string, error) {
+	gvr := schema.GroupVersionResource{
+		Group: openShiftRouteGroup, Version: openShiftRouteVersion, Resource: openShiftRouteResource,
+	}
+
+	route, err := cs.Clients.Dynamic.Resource(gvr).Namespace(openShiftConsoleNS).Get(ctx, openShiftConsoleRouteName, metav1.GetOptions{})
 	if err != nil {
 		return "", err
 	}
@@ -49,13 +52,13 @@ func getOpenshiftConsole(ctx context.Context, cs *cli.Clients, ns, pr string) (s
 
 // GetConsoleUI Get a Console URL, OpenShift Console or Tekton Dashboard.
 // don't error if we can't find it.
-func GetConsoleUI(ctx context.Context, cs *cli.Clients, ns, pr string) (string, error) {
+func GetConsoleUI(ctx context.Context, cs *params.Run, ns, pr string) (string, error) {
 	var url string
 	var err error
 	url, err = getOpenshiftConsole(ctx, cs, ns, pr)
 	if err != nil {
 		return "", err
 	}
-	cs.Log.Infof("Web Console PR url: %s", url)
+	cs.Clients.Log.Infof("Web Console PR url: %s", url)
 	return url, nil
 }
diff --git a/pkg/flags/flags.go b/pkg/flags/flags.go
deleted file mode 100644
index d2f83d39..00000000
--- a/pkg/flags/flags.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package flags
-
-import (
-	"fmt"
-	"os"
-
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/spf13/cobra"
-)
-
-const (
-	kubeConfig = "kubeconfig"
-	tokenFlag  = "token"
-	apiURLFlag = "api-url"
-)
-
-// PacOptions holds struct of Pipelines as code Options
-type PacOptions struct {
-	KubeConfig, GithubToken, GithubAPIURL string
-}
-
-// InitParams initializes cli.Params based on flags defined in command
-func InitParams(p cli.Params, cmd *cobra.Command) error {
-	kcPath, err := cmd.Flags().GetString(kubeConfig)
-	if err != nil {
-		return err
-	}
-	p.SetKubeConfigPath(kcPath)
-	return nil
-}
-
-// AddPacOptions amends command to add flags required to initialize a cli.Param
-func AddPacOptions(cmd *cobra.Command) {
-	envkconfig := os.Getenv("KUBECONFIG")
-	if envkconfig == "" {
-		envkconfig = "$HOME/.kube/config"
-	}
-
-	cmd.PersistentFlags().StringP(
-		kubeConfig, "k", "",
-		fmt.Sprintf("kubectl config file (default: %s)", envkconfig))
-}
-
-func AddWebCVSOptions(cmd *cobra.Command) {
-	cmd.PersistentFlags().StringP(tokenFlag, "", os.Getenv("PAC_WEBVCS_TOKEN"),
-		"Web VCS (ie: GitHub) Token")
-
-	cmd.PersistentFlags().StringP(apiURLFlag, "", os.Getenv("PAC_WEBVCS_URL"),
-		"Web VCS (ie: GitHub Enteprise) API URL")
-}
-
-func GetWebCVSOptions(p cli.Params, cmd *cobra.Command) error {
-	githubToken, err := cmd.Flags().GetString(tokenFlag)
-	if err != nil {
-		return err
-	}
-	p.SetGitHubToken(githubToken)
-
-	githubAPIURL, err := cmd.Flags().GetString(apiURLFlag)
-	if err != nil {
-		return err
-	}
-	p.SetGitHubAPIURL(githubAPIURL)
-	return nil
-}
diff --git a/pkg/hub/get.go b/pkg/hub/get.go
index f7de828d..6a15f077 100644
--- a/pkg/hub/get.go
+++ b/pkg/hub/get.go
@@ -8,7 +8,7 @@ import (
 	"net/http"
 	"strings"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 )
 
 var (
@@ -16,12 +16,12 @@ var (
 	hubBaseURL           = `https://api.hub.tekton.dev/v1`
 )
 
-func getURL(ctx context.Context, cli *cli.Clients, url string) ([]byte, error) {
+func getURL(ctx context.Context, cli *params.Run, url string) ([]byte, error) {
 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
 	if err != nil {
 		return []byte{}, err
 	}
-	res, err := cli.HTTPClient.Do(req)
+	res, err := cli.Clients.HTTP.Do(req)
 	if err != nil {
 		return []byte{}, err
 	}
@@ -33,7 +33,7 @@ func getURL(ctx context.Context, cli *cli.Clients, url string) ([]byte, error) {
 	return data, nil
 }
 
-func getSpecificVersion(ctx context.Context, cli *cli.Clients, task string) (string, error) {
+func getSpecificVersion(ctx context.Context, cli *params.Run, task string) (string, error) {
 	split := strings.Split(task, ":")
 	version := split[len(split)-1]
 	taskName := split[0]
@@ -50,7 +50,7 @@ func getSpecificVersion(ctx context.Context, cli *cli.Clients, task string) (str
 	return *hr.Data.RawURL, nil
 }
 
-func getLatestVersion(ctx context.Context, cli *cli.Clients, task string) (string, error) {
+func getLatestVersion(ctx context.Context, cli *params.Run, task string) (string, error) {
 	hr := new(hubResource)
 	data, err := getURL(ctx, cli, fmt.Sprintf("%s/resource/%s/task/%s", hubBaseURL, tektonCatalogHubName, task))
 	if err != nil {
@@ -63,7 +63,7 @@ func getLatestVersion(ctx context.Context, cli *cli.Clients, task string) (strin
 	return *hr.Data.LatestVersion.RawURL, nil
 }
 
-func GetTask(ctx context.Context, cli *cli.Clients, task string) (string, error) {
+func GetTask(ctx context.Context, cli *params.Run, task string) (string, error) {
 	var rawURL string
 	var err error
 
diff --git a/pkg/kubeinteraction/cleanups.go b/pkg/kubeinteraction/cleanups.go
index 65c31941..0089c66e 100644
--- a/pkg/kubeinteraction/cleanups.go
+++ b/pkg/kubeinteraction/cleanups.go
@@ -28,7 +28,7 @@ func (prs prByCompletionTime) Less(i, j int) bool {
 func (k Interaction) CleanupPipelines(ctx context.Context, namespace string, repositoryName string, maxKeep int) error {
 	labelSelector := fmt.Sprintf("pipelinesascode.tekton.dev/repository=%s", repositoryName)
 
-	pruns, err := k.Clients.Tekton.TektonV1beta1().PipelineRuns(namespace).List(ctx, metav1.ListOptions{
+	pruns, err := k.Run.Clients.Tekton.TektonV1beta1().PipelineRuns(namespace).List(ctx, metav1.ListOptions{
 		LabelSelector: labelSelector,
 	})
 
@@ -36,12 +36,12 @@ func (k Interaction) CleanupPipelines(ctx context.Context, namespace string, rep
 
 	for c, v := range pruns.Items {
 		if v.GetStatusCondition().GetCondition(apis.ConditionSucceeded).GetReason() == "Running" {
-			k.Clients.Log.Infof("Skipping Cleanining up %s since it is currently Running", v.GetName())
+			k.Run.Clients.Log.Infof("Skipping Cleanining up %s since it is currently Running", v.GetName())
 			continue
 		}
 		if c >= maxKeep {
-			k.Clients.Log.Infof("Cleaning old PipelineRun: %s", v.GetName())
-			err := k.Clients.Tekton.TektonV1beta1().PipelineRuns(namespace).Delete(ctx, v.GetName(), metav1.DeleteOptions{})
+			k.Run.Clients.Log.Infof("Cleaning old PipelineRun: %s", v.GetName())
+			err := k.Run.Clients.Tekton.TektonV1beta1().PipelineRuns(namespace).Delete(ctx, v.GetName(), metav1.DeleteOptions{})
 			if err != nil {
 				return err
 			}
diff --git a/pkg/kubeinteraction/kubeinteraction.go b/pkg/kubeinteraction/kubeinteraction.go
index f36e7710..863722c8 100644
--- a/pkg/kubeinteraction/kubeinteraction.go
+++ b/pkg/kubeinteraction/kubeinteraction.go
@@ -2,21 +2,35 @@ package kubeinteraction
 
 import (
 	"context"
+	"time"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/consoleui"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+
+	tektonv1beta1client "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/typed/pipeline/v1beta1"
 )
 
+type Interface interface {
+	GetConsoleUI(context.Context, string, string) (string, error)
+	GetNamespace(context.Context, string) error
+	// TODO: we don't need tektonv1beta1client stuff here
+	WaitForPipelineRunSucceed(context.Context, tektonv1beta1client.TektonV1beta1Interface, *v1beta1.PipelineRun, time.Duration) error
+	CleanupPipelines(context.Context, string, string, int) error
+	CreateBasicAuthSecret(context.Context, *info.Event, info.PacOpts, string) error
+}
+
 type Interaction struct {
-	Clients *cli.Clients
+	Run *params.Run
 }
 
 func (k Interaction) GetConsoleUI(ctx context.Context, ns, pr string) (string, error) {
-	return consoleui.GetConsoleUI(ctx, k.Clients, ns, pr)
+	return consoleui.GetConsoleUI(ctx, k.Run, ns, pr)
 }
 
-func NewKubernetesInteraction(c *cli.Clients) (*Interaction, error) {
+func NewKubernetesInteraction(c *params.Run) (*Interaction, error) {
 	return &Interaction{
-		Clients: c,
+		Run: c,
 	}, nil
 }
diff --git a/pkg/kubeinteraction/namespace.go b/pkg/kubeinteraction/namespace.go
index aa28bdd8..cd372b12 100644
--- a/pkg/kubeinteraction/namespace.go
+++ b/pkg/kubeinteraction/namespace.go
@@ -8,11 +8,11 @@ import (
 
 // GetNamespace get a namespace
 func (k Interaction) GetNamespace(ctx context.Context, namespace string) error {
-	_, err := k.Clients.Kube.CoreV1().Namespaces().Get(ctx, namespace, v1.GetOptions{})
+	_, err := k.Run.Clients.Kube.CoreV1().Namespaces().Get(ctx, namespace, v1.GetOptions{})
 	if err != nil {
-		k.Clients.Log.Infof("namespace: %s cannot be found", namespace)
+		k.Run.Clients.Log.Infof("namespace: %s cannot be found", namespace)
 		return err
 	}
-	k.Clients.Log.Infof("namespace is: %s", namespace)
+	k.Run.Clients.Log.Infof("namespace is: %s", namespace)
 	return nil
 }
diff --git a/pkg/kubeinteraction/secrets.go b/pkg/kubeinteraction/secrets.go
index c1647cfd..0cfa0eb1 100644
--- a/pkg/kubeinteraction/secrets.go
+++ b/pkg/kubeinteraction/secrets.go
@@ -5,7 +5,7 @@ import (
 	"fmt"
 	"net/url"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
@@ -20,37 +20,40 @@ const (
 )
 
 func (k Interaction) createSecret(ctx context.Context, secretData map[string]string, targetNamespace, secretName string) error {
-	secret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{
-		Name:   secretName,
-		Labels: map[string]string{"app.kubernetes.io/managed-by": "pipelines-as-code"},
-	}}
+	secret := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:   secretName,
+			Labels: map[string]string{"app.kubernetes.io/managed-by": "pipelines-as-code"},
+		},
+	}
 	secret.StringData = secretData
-	_, err := k.Clients.Kube.CoreV1().Secrets(targetNamespace).Create(ctx, secret, metav1.CreateOptions{})
+	_, err := k.Run.Clients.Kube.CoreV1().Secrets(targetNamespace).Create(ctx, secret, metav1.CreateOptions{})
 	return err
 }
 
 // CreateBasicAuthSecret Create a secret for git-clone basic-auth workspace
-func (k Interaction) CreateBasicAuthSecret(ctx context.Context, runinfo webvcs.RunInfo, targetNamespace string) error {
-	repoURL, err := url.Parse(runinfo.URL)
+func (k Interaction) CreateBasicAuthSecret(ctx context.Context, runevent *info.Event, pacopts info.PacOpts, targetNamespace string) error {
+	repoURL, err := url.Parse(runevent.URL)
 	if err != nil {
 		return err
 	}
-	urlWithToken := fmt.Sprintf("%s://git:%s@%s%s", repoURL.Scheme, k.Clients.GithubClient.Token, repoURL.Host, repoURL.Path)
+
+	urlWithToken := fmt.Sprintf("%s://git:%s@%s%s", repoURL.Scheme, pacopts.VCSToken, repoURL.Host, repoURL.Path)
 	secretData := map[string]string{
-		".gitconfig":       fmt.Sprintf(basicAuthGitConfigData, runinfo.URL),
+		".gitconfig":       fmt.Sprintf(basicAuthGitConfigData, runevent.URL),
 		".git-credentials": urlWithToken,
 	}
 
 	// Try to create secrete if that fails then delete it first and then create
 	// This allows up not to give List and Get right clusterwide
-	secretName := fmt.Sprintf(basicAuthSecretName, runinfo.Owner, runinfo.Repository)
+	secretName := fmt.Sprintf(basicAuthSecretName, runevent.Owner, runevent.Repository)
 	err = k.createSecret(ctx, secretData, targetNamespace, secretName)
 	if err != nil {
-		err = k.Clients.Kube.CoreV1().Secrets(targetNamespace).Delete(ctx, secretName, metav1.DeleteOptions{})
+		err = k.Run.Clients.Kube.CoreV1().Secrets(targetNamespace).Delete(ctx, secretName, metav1.DeleteOptions{})
 		if err == nil {
 			err = k.createSecret(ctx, secretData, targetNamespace, secretName)
 		}
 	}
-	k.Clients.Log.Infof("Secret %s has been generated in namespace %s", secretName, targetNamespace)
+	k.Run.Clients.Log.Infof("Secret %s has been generated in namespace %s", secretName, targetNamespace)
 	return err
 }
diff --git a/pkg/config/annotation_matcher.go b/pkg/matcher/annotation_matcher.go
similarity index 76%
rename from pkg/config/annotation_matcher.go
rename to pkg/matcher/annotation_matcher.go
index 2c3f860d..8d09961a 100644
--- a/pkg/config/annotation_matcher.go
+++ b/pkg/matcher/annotation_matcher.go
@@ -1,4 +1,4 @@
-package config
+package matcher
 
 import (
 	"context"
@@ -9,8 +9,7 @@ import (
 
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode"
 	apipac "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 )
 
@@ -43,14 +42,13 @@ func getAnnotationValues(annotation string) ([]string, error) {
 	return splitted, nil
 }
 
-func MatchPipelinerunByAnnotation(ctx context.Context, pruns []*v1beta1.PipelineRun, cs *cli.Clients,
-	runinfo *webvcs.RunInfo) (*v1beta1.PipelineRun, *apipac.Repository, map[string]string, error) {
+func MatchPipelinerunByAnnotation(ctx context.Context, pruns []*v1beta1.PipelineRun, cs *params.Run) (*v1beta1.PipelineRun, *apipac.Repository, map[string]string, error) {
 	configurations := map[string]map[string]string{}
 	repo := &apipac.Repository{}
 	for _, prun := range pruns {
 		configurations[prun.GetGenerateName()] = map[string]string{}
 		if prun.GetObjectMeta().GetAnnotations() == nil {
-			cs.Log.Warnf("PipelineRun %s does not have any annotations", prun.GetName())
+			cs.Clients.Log.Warnf("PipelineRun %s does not have any annotations", prun.GetName())
 			continue
 		}
 
@@ -62,16 +60,16 @@ func MatchPipelinerunByAnnotation(ctx context.Context, pruns []*v1beta1.Pipeline
 		if targetNS, ok := prun.GetObjectMeta().GetAnnotations()[pipelinesascode.
 			GroupName+"/"+onTargetNamespace]; ok {
 			configurations[prun.GetGenerateName()]["target-namespace"] = targetNS
-			repo, _ = GetRepoByCR(ctx, cs, targetNS, runinfo)
+			repo, _ = GetRepoByCR(ctx, cs, targetNS)
 			if repo == nil {
-				cs.Log.Warnf("could not find Repository CRD in %s while pipelineRun %s targets it", targetNS, prun.GetGenerateName())
+				cs.Clients.Log.Warnf("could not find Repository CRD in %s while pipelineRun %s targets it", targetNS, prun.GetGenerateName())
 				continue
 			}
 		}
 
 		if targetEvent, ok := prun.GetObjectMeta().GetAnnotations()[pipelinesascode.
 			GroupName+"/"+onEventAnnotation]; ok {
-			matched, err := matchOnAnnotation(targetEvent, runinfo.EventType, false)
+			matched, err := matchOnAnnotation(targetEvent, cs.Info.Event.EventType, false)
 			configurations[prun.GetGenerateName()]["target-event"] = targetEvent
 			if err != nil {
 				return nil, nil, map[string]string{}, err
@@ -83,7 +81,7 @@ func MatchPipelinerunByAnnotation(ctx context.Context, pruns []*v1beta1.Pipeline
 
 		if targetBranch, ok := prun.GetObjectMeta().GetAnnotations()[pipelinesascode.
 			GroupName+"/"+onTargetBranchAnnotation]; ok {
-			matched, err := matchOnAnnotation(targetBranch, runinfo.BaseBranch, true)
+			matched, err := matchOnAnnotation(targetBranch, cs.Info.Event.BaseBranch, true)
 			configurations[prun.GetGenerateName()]["target-branch"] = targetBranch
 			if err != nil {
 				return nil, nil, map[string]string{}, err
@@ -96,14 +94,14 @@ func MatchPipelinerunByAnnotation(ctx context.Context, pruns []*v1beta1.Pipeline
 		return prun, repo, configurations[prun.GetGenerateName()], nil
 	}
 
-	cs.Log.Infof("cannot match between event and pipelineRuns: URL=%s baseBranch=%s, "+
-		"eventType=%s", runinfo.URL,
-		runinfo.BaseBranch,
-		runinfo.EventType)
+	cs.Clients.Log.Infof("cannot match between event and pipelineRuns: URL=%s baseBranch=%s, "+
+		"eventType=%s", cs.Info.Event.URL,
+		cs.Info.Event.BaseBranch,
+		cs.Info.Event.EventType)
 
-	cs.Log.Info("available configuration in pipelineRuns annotations")
+	cs.Clients.Log.Info("available configuration in pipelineRuns annotations")
 	for prunname, maps := range configurations {
-		cs.Log.Infof("pipelineRun: %s, baseBranch=%s, targetEvent=%s, targetNs=%s",
+		cs.Clients.Log.Infof("pipelineRun: %s, baseBranch=%s, targetEvent=%s, targetNs=%s",
 			prunname, maps["target-branch"], maps["target-event"], maps["target-namespace"])
 	}
 
diff --git a/pkg/config/annotation_tasks_install.go b/pkg/matcher/annotation_tasks_install.go
similarity index 78%
rename from pkg/config/annotation_tasks_install.go
rename to pkg/matcher/annotation_tasks_install.go
index 46becb67..9ae10b26 100644
--- a/pkg/config/annotation_tasks_install.go
+++ b/pkg/matcher/annotation_tasks_install.go
@@ -1,4 +1,4 @@
-package config
+package matcher
 
 import (
 	"context"
@@ -8,8 +8,8 @@ import (
 	"strings"
 
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/hub"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	tektonv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	k8scheme "k8s.io/client-go/kubernetes/scheme"
@@ -20,8 +20,7 @@ const (
 )
 
 type RemoteTasks struct {
-	Clients *cli.Clients
-	Runinfo *webvcs.RunInfo
+	Run *params.Run
 }
 
 func (rt RemoteTasks) convertTotask(data string) (*tektonv1beta1.Task, error) {
@@ -35,14 +34,14 @@ func (rt RemoteTasks) convertTotask(data string) (*tektonv1beta1.Task, error) {
 	return obj.(*tektonv1beta1.Task), nil
 }
 
-func (rt RemoteTasks) getTask(ctx context.Context, task string) (*tektonv1beta1.Task, error) {
+func (rt RemoteTasks) getTask(ctx context.Context, vcsintf webvcs.Interface, task string) (*tektonv1beta1.Task, error) {
 	var ret *tektonv1beta1.Task
 
 	// TODO: print a log info when getting the task from which location
 	switch {
 	case strings.HasPrefix(task, "https://"), strings.HasPrefix(task, "http://"):
-		// nolint:  noctx // TODO: Add a context
-		res, err := rt.Clients.HTTPClient.Get(task)
+		// TODO: Add a context
+		res, err := rt.Run.Clients.HTTP.Get(task)
 		if err != nil {
 			return ret, err
 		}
@@ -50,13 +49,13 @@ func (rt RemoteTasks) getTask(ctx context.Context, task string) (*tektonv1beta1.
 		defer res.Body.Close()
 		return rt.convertTotask(string(data))
 	case strings.Contains(task, "/"):
-		data, err := rt.Clients.GithubClient.GetFileInsideRepo(ctx, task, false, rt.Runinfo)
+		data, err := vcsintf.GetFileInsideRepo(ctx, rt.Run.Info.Event, task, false)
 		if err != nil {
 			return ret, err
 		}
 		return rt.convertTotask(string(data))
 	default:
-		data, err := hub.GetTask(ctx, rt.Clients, task)
+		data, err := hub.GetTask(ctx, rt.Run, task)
 		if err != nil {
 			return nil, err
 		}
@@ -65,7 +64,8 @@ func (rt RemoteTasks) getTask(ctx context.Context, task string) (*tektonv1beta1.
 }
 
 // GetTaskFromAnnotations Get task remotely if they are on Annotations
-func (rt RemoteTasks) GetTaskFromAnnotations(ctx context.Context, annotations map[string]string) ([]*tektonv1beta1.Task, error) {
+func (rt RemoteTasks) GetTaskFromAnnotations(ctx context.Context, vcsintf webvcs.Interface,
+	annotations map[string]string) ([]*tektonv1beta1.Task, error) {
 	var ret []*tektonv1beta1.Task
 	rtareg := regexp.MustCompile(fmt.Sprintf("%s/%s", pipelinesascode.GroupName, taskAnnotationsRegexp))
 	for annotationK, annotationV := range annotations {
@@ -77,7 +77,7 @@ func (rt RemoteTasks) GetTaskFromAnnotations(ctx context.Context, annotations ma
 			return ret, err
 		}
 		for _, v := range tasks {
-			task, err := rt.getTask(ctx, v)
+			task, err := rt.getTask(ctx, vcsintf, v)
 			if err != nil {
 				return ret, err
 			}
diff --git a/pkg/config/repo_runinfo_matcher.go b/pkg/matcher/repo_runinfo_matcher.go
similarity index 69%
rename from pkg/config/repo_runinfo_matcher.go
rename to pkg/matcher/repo_runinfo_matcher.go
index d5eaf638..cc2e7eb2 100644
--- a/pkg/config/repo_runinfo_matcher.go
+++ b/pkg/matcher/repo_runinfo_matcher.go
@@ -1,4 +1,4 @@
-package config
+package matcher
 
 import (
 	"context"
@@ -7,8 +7,7 @@ import (
 
 	"github.com/gobwas/glob"
 	apipac "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -24,8 +23,8 @@ func branchMatch(prunBranch, baseBranch string) bool {
 	return g.Match(baseBranch)
 }
 
-func GetRepoByCR(ctx context.Context, cs *cli.Clients, ns string, runinfo *webvcs.RunInfo) (*apipac.Repository, error) {
-	repositories, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(ns).List(
+func GetRepoByCR(ctx context.Context, cs *params.Run, ns string) (*apipac.Repository, error) {
+	repositories, err := cs.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(ns).List(
 		ctx, metav1.ListOptions{})
 	if err != nil {
 		return nil, err
@@ -36,10 +35,10 @@ func GetRepoByCR(ctx context.Context, cs *cli.Clients, ns string, runinfo *webvc
 			fmt.Sprintf("RepositoryValue: URL=%s, eventType=%s BaseBranch:=%s", value.Spec.URL,
 				value.Spec.EventType, value.Spec.Branch))
 
-		if value.Spec.URL == runinfo.URL &&
-			value.Spec.EventType == runinfo.EventType {
-			if value.Spec.Branch != runinfo.BaseBranch {
-				if !branchMatch(value.Spec.Branch, runinfo.BaseBranch) {
+		if value.Spec.URL == cs.Info.Event.URL &&
+			value.Spec.EventType == cs.Info.Event.EventType {
+			if value.Spec.Branch != cs.Info.Event.BaseBranch {
+				if !branchMatch(value.Spec.Branch, cs.Info.Event.BaseBranch) {
 					continue
 				}
 			}
@@ -57,7 +56,7 @@ func GetRepoByCR(ctx context.Context, cs *cli.Clients, ns string, runinfo *webvc
 		}
 	}
 	for _, value := range matches {
-		cs.Log.Debug(value)
+		cs.Clients.Log.Debug(value)
 	}
 
 	return nil, nil
diff --git a/pkg/flags/cli.go b/pkg/params/cli.go
similarity index 75%
rename from pkg/flags/cli.go
rename to pkg/params/cli.go
index f01534fa..e1db927c 100644
--- a/pkg/flags/cli.go
+++ b/pkg/params/cli.go
@@ -1,4 +1,4 @@
-package flags
+package params
 
 import (
 	"os"
@@ -10,16 +10,16 @@ import (
 
 var noColorFlag = "no-color"
 
-type CliOpts struct {
+type PacCliOpts struct {
 	NoColoring    bool
 	AllNameSpaces bool
 	Namespace     string
 	AskOpts       survey.AskOpt
 }
 
-func NewCliOptions(cmd *cobra.Command) (*CliOpts, error) {
+func NewCliOptions(cmd *cobra.Command) (*PacCliOpts, error) {
 	var err error
-	c := &CliOpts{
+	c := &PacCliOpts{
 		AskOpts: func(opt *survey.AskOptions) error {
 			opt.Stdio = terminal.Stdio{
 				In:  os.Stdin,
@@ -36,6 +36,6 @@ func NewCliOptions(cmd *cobra.Command) (*CliOpts, error) {
 	return c, err
 }
 
-func (c *CliOpts) Ask(qs []*survey.Question, ans interface{}) error {
+func (c *PacCliOpts) Ask(qs []*survey.Question, ans interface{}) error {
 	return survey.Ask(qs, ans, c.AskOpts)
 }
diff --git a/pkg/params/clients/clients.go b/pkg/params/clients/clients.go
new file mode 100644
index 00000000..1be2ef9c
--- /dev/null
+++ b/pkg/params/clients/clients.go
@@ -0,0 +1,122 @@
+package clients
+
+import (
+	"net/http"
+
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/generated/clientset/versioned"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"github.com/pkg/errors"
+	versioned2 "github.com/tektoncd/pipeline/pkg/client/clientset/versioned"
+	"go.uber.org/zap"
+	"k8s.io/client-go/dynamic"
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/rest"
+	"k8s.io/client-go/tools/clientcmd"
+)
+
+type Clients struct {
+	ClientInitialized bool
+	PipelineAsCode    versioned.Interface
+	Tekton            versioned2.Interface
+	Kube              kubernetes.Interface
+	HTTP              http.Client
+	Log               *zap.SugaredLogger
+	Dynamic           dynamic.Interface
+}
+
+// Set kube client based on config
+func (c *Clients) kubeClient(config *rest.Config) (kubernetes.Interface, error) {
+	k8scs, err := kubernetes.NewForConfig(config)
+	if err != nil {
+		return nil, errors.Wrapf(err, "failed to create k8s client from config")
+	}
+
+	return k8scs, nil
+}
+
+func (c *Clients) dynamicClient(config *rest.Config) (dynamic.Interface, error) {
+	dynamicClient, err := dynamic.NewForConfig(config)
+	if err != nil {
+		return nil, errors.Wrapf(err, "failed to create dynamic client from config")
+	}
+	return dynamicClient, err
+}
+
+func (c *Clients) kubeConfig(info *info.Info) (*rest.Config, error) {
+	loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
+	if info.Kube.ConfigPath != "" {
+		loadingRules.ExplicitPath = info.Kube.ConfigPath
+	}
+	configOverrides := &clientcmd.ConfigOverrides{}
+	if info.Kube.Context != "" {
+		configOverrides.CurrentContext = info.Kube.Context
+	}
+	kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
+	if info.Kube.Namespace == "" {
+		namespace, _, err := kubeConfig.Namespace()
+		if err != nil {
+			return nil, errors.Wrap(err, "Couldn't get kubeConfiguration namespace")
+		}
+		info.Kube.Namespace = namespace
+	}
+	config, err := kubeConfig.ClientConfig()
+	if err != nil {
+		return nil, errors.Wrap(err, "Parsing kubeconfig failed")
+	}
+	return config, nil
+}
+
+func (c *Clients) tektonClient(config *rest.Config) (versioned2.Interface, error) {
+	cs, err := versioned2.NewForConfig(config)
+	if err != nil {
+		return nil, err
+	}
+	return cs, nil
+}
+
+func (c *Clients) pacClient(config *rest.Config) (versioned.Interface, error) {
+	cs, err := versioned.NewForConfig(config)
+	if err != nil {
+		return nil, err
+	}
+
+	return cs, nil
+}
+
+func (c *Clients) NewClients(info *info.Info) error {
+	if c.ClientInitialized {
+		return nil
+	}
+	prod, _ := zap.NewProduction()
+	logger := prod.Sugar()
+	defer func() {
+		_ = logger.Sync() // flushes buffer, if any
+	}()
+	c.Log = logger
+
+	config, err := c.kubeConfig(info)
+	if err != nil {
+		return err
+	}
+
+	c.Kube, err = c.kubeClient(config)
+	if err != nil {
+		return err
+	}
+	c.Tekton, err = c.tektonClient(config)
+	if err != nil {
+		return err
+	}
+
+	c.PipelineAsCode, err = c.pacClient(config)
+	if err != nil {
+		return err
+	}
+
+	c.Dynamic, err = c.dynamicClient(config)
+	if err != nil {
+		return err
+	}
+	c.ClientInitialized = true
+	return nil
+}
diff --git a/pkg/params/info/events.go b/pkg/params/info/events.go
new file mode 100644
index 00000000..6f18184d
--- /dev/null
+++ b/pkg/params/info/events.go
@@ -0,0 +1,19 @@
+package info
+
+type Event struct {
+	Event         interface{}
+	EventType     string
+	TriggerTarget string
+
+	BaseBranch    string // branch against where we are making the PR
+	CheckRunID    *int64
+	DefaultBranch string
+	HeadBranch    string // branch from where our SHA get tested
+	Owner         string
+	Repository    string
+	SHA           string
+	SHAURL        string
+	Sender        string
+	URL           string
+	SHATitle      string
+}
diff --git a/pkg/params/info/kube.go b/pkg/params/info/kube.go
new file mode 100644
index 00000000..d3a19d2e
--- /dev/null
+++ b/pkg/params/info/kube.go
@@ -0,0 +1,30 @@
+package info
+
+import (
+	"fmt"
+	"os"
+
+	"github.com/spf13/cobra"
+)
+
+type KubeOpts struct {
+	ConfigPath string
+	Context    string
+	Namespace  string
+}
+
+func (k *KubeOpts) AddFlags(cmd *cobra.Command) {
+	envkconfig := os.Getenv("KUBECONFIG")
+	if envkconfig == "" {
+		envkconfig = "$HOME/.kube/config"
+	}
+	cmd.PersistentFlags().StringVarP(
+		&k.ConfigPath,
+		"kubeconfig", "k", envkconfig,
+		fmt.Sprintf("Path to the kubeconfig file to use for CLI requests (default: %s)", envkconfig))
+
+	cmd.PersistentFlags().StringVarP(
+		&k.ConfigPath,
+		"namespace", "n", "",
+		"If present, the namespace scope for this CLI request")
+}
diff --git a/pkg/params/info/pac.go b/pkg/params/info/pac.go
new file mode 100644
index 00000000..cb706f32
--- /dev/null
+++ b/pkg/params/info/pac.go
@@ -0,0 +1,51 @@
+package info
+
+import (
+	"os"
+	"strings"
+
+	"github.com/spf13/cobra"
+)
+
+type PacOpts struct {
+	LogURL             string
+	ApplicationName    string // the Application Name for example "Pipelines as Code"
+	SecretAutoCreation bool   // secret auto creation in target namespace
+	VCSToken           string
+	VCSAPIURL          string
+	VCSType            string
+	PayloadFile        string
+}
+
+func (p *PacOpts) AddFlags(cmd *cobra.Command) {
+	cmd.PersistentFlags().StringVarP(&p.VCSType, "webvcs-type", "", os.Getenv("PAC_WEBVCS_TYPE"),
+		"Web VCS (ie: GitHub) Token")
+
+	cmd.PersistentFlags().StringVarP(&p.VCSToken, "webvcs-token", "", os.Getenv("PAC_WEBVCS_TOKEN"),
+		"Web VCS (ie: GitHub) Token")
+
+	cmd.PersistentFlags().StringVarP(&p.VCSAPIURL, "webvcs-api-url", "", os.Getenv("PAC_WEBVCS_URL"),
+		"Web VCS (ie: GitHub Enteprise) API URL")
+
+	cmd.PersistentFlags().StringVarP(&p.PayloadFile,
+		"payload-file", "", os.Getenv("PAC_PAYLOAD_FILE"), "A file containing the webhook payload")
+
+	applicationName := os.Getenv("PAC_APPLICATION_NAME")
+	if applicationName == "" {
+		applicationName = defaultApplicationName
+	}
+	cmd.Flags().StringVar(&p.ApplicationName,
+		"application-name", applicationName,
+		"The name of the application.")
+
+	secretAutoCreation := false
+	secretAutoCreationEnv := os.Getenv("PAC_SECRET_AUTO_CREATE")
+	if strings.ToLower(secretAutoCreationEnv) == "true" ||
+		strings.ToLower(secretAutoCreationEnv) == "yes" || secretAutoCreationEnv == "1" {
+		secretAutoCreation = true
+	}
+	cmd.Flags().BoolVar(&p.SecretAutoCreation,
+		"secret-auto-creation",
+		secretAutoCreation,
+		"Wether to create automatically secrets.")
+}
diff --git a/pkg/params/info/runinfo.go b/pkg/params/info/runinfo.go
new file mode 100644
index 00000000..d688a729
--- /dev/null
+++ b/pkg/params/info/runinfo.go
@@ -0,0 +1,9 @@
+package info
+
+const defaultApplicationName = "Pipelines as Code CI"
+
+type Info struct {
+	Event *Event
+	Pac   PacOpts
+	Kube  KubeOpts
+}
diff --git a/pkg/params/run.go b/pkg/params/run.go
new file mode 100644
index 00000000..62cab189
--- /dev/null
+++ b/pkg/params/run.go
@@ -0,0 +1,11 @@
+package params
+
+import (
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+)
+
+type Run struct {
+	Clients clients.Clients
+	Info    info.Info
+}
diff --git a/pkg/cli/ui/color.go b/pkg/params/ui/color.go
similarity index 100%
rename from pkg/cli/ui/color.go
rename to pkg/params/ui/color.go
diff --git a/pkg/cli/ui/formating.go b/pkg/params/ui/formating.go
similarity index 100%
rename from pkg/cli/ui/formating.go
rename to pkg/params/ui/formating.go
diff --git a/pkg/cli/ui/iostreams.go b/pkg/params/ui/iostreams.go
similarity index 100%
rename from pkg/cli/ui/iostreams.go
rename to pkg/params/ui/iostreams.go
diff --git a/pkg/pipelineascode/acl.go b/pkg/pipelineascode/acl.go
deleted file mode 100644
index 2dcfce81..00000000
--- a/pkg/pipelineascode/acl.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package pipelineascode
-
-import (
-	"context"
-	"strings"
-
-	"github.com/google/go-github/v35/github"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
-	"sigs.k8s.io/yaml"
-)
-
-var okToTestCommentRegexp = `(^|\n)/ok-to-test(\r\n|$)`
-
-// OwnersConfig prow owner, only supporting approvers or reviewers in yaml
-type OwnersConfig struct {
-	Approvers []string `json:"approvers,omitempty"`
-	Reviewers []string `json:"reviewers,omitempty"`
-}
-
-// allowedOkToTestFromAnOwner Goes on evry comments in a pull-request and sess
-// if there is a /ok-to-test in there running an aclCheck again on the commment
-// Sender if she is an OWNER and then allow it to run CI.
-// TODO: pull out the github logic from there in an agnostic way.
-func aclAllowedOkToTestFromAnOwner(ctx context.Context, cs *cli.Clients, runinfo *webvcs.RunInfo) (bool, error) {
-	rinfo := &webvcs.RunInfo{}
-	runinfo.DeepCopyInto(rinfo)
-	rinfo.EventType = ""
-	rinfo.TriggerTarget = ""
-	if rinfo.Event == nil {
-		return false, nil
-	}
-
-	switch event := rinfo.Event.(type) {
-	case *github.IssueCommentEvent:
-		rinfo.URL = event.Issue.GetPullRequestLinks().GetHTMLURL()
-	case *github.PullRequestEvent:
-		rinfo.URL = event.GetPullRequest().GetHTMLURL()
-	default:
-		return false, nil
-	}
-
-	comments, err := cs.GithubClient.GetStringPullRequestComment(ctx, rinfo, okToTestCommentRegexp)
-	if err != nil {
-		return false, err
-	}
-
-	for _, comment := range comments {
-		rinfo.Sender = comment.User.GetLogin()
-		allowed, err := aclCheckAll(ctx, cs, rinfo)
-		if err != nil {
-			return false, err
-		}
-		if allowed {
-			return true, nil
-		}
-	}
-	return false, nil
-}
-
-// aclCheck check if we are allowed to run the pipeline on that PR
-func aclCheckAll(ctx context.Context, cs *cli.Clients, runinfo *webvcs.RunInfo) (bool, error) {
-	if runinfo.Owner == runinfo.Sender {
-		return true, nil
-	}
-
-	// If the user who has submitted the pr is a owner on the repo then allows
-	// the CI to be run.
-	isUserMemberRepo, err := cs.GithubClient.CheckSenderOrgMembership(ctx, runinfo)
-	if err != nil {
-		return false, err
-	}
-
-	if isUserMemberRepo {
-		return true, nil
-	}
-
-	// If we have a prow OWNERS file in the defaultBranch (ie: master) then
-	// parse it in approvers and reviewers field and check if sender is in there.
-	ownerFile, err := cs.GithubClient.GetFileFromDefaultBranch(ctx, "OWNERS", runinfo)
-
-	// Don't error out if the OWNERS file cannot be found
-	if err != nil && !strings.Contains(err.Error(), "cannot find") {
-		return false, err
-	} else if ownerFile != "" {
-		var ownerConfig OwnersConfig
-		err := yaml.Unmarshal([]byte(ownerFile), &ownerConfig)
-		if err != nil {
-			return false, err
-		}
-		for _, owner := range append(ownerConfig.Approvers, ownerConfig.Reviewers...) {
-			if owner == runinfo.Sender {
-				return true, nil
-			}
-		}
-	}
-
-	return false, nil
-}
-
-func aclCheck(ctx context.Context, cs *cli.Clients, runinfo *webvcs.RunInfo) (bool, error) {
-	// Do most of the checks first, if user is a owner or in a organisation
-	allowed, err := aclCheckAll(ctx, cs, runinfo)
-	if err != nil {
-		return false, err
-	}
-	if allowed {
-		return true, nil
-	}
-
-	// Finally try to parse all comments
-	return aclAllowedOkToTestFromAnOwner(ctx, cs, runinfo)
-}
diff --git a/pkg/pipelineascode/pipelineascode.go b/pkg/pipelineascode/pipelineascode.go
index 4299c447..0383d2d8 100644
--- a/pkg/pipelineascode/pipelineascode.go
+++ b/pkg/pipelineascode/pipelineascode.go
@@ -8,8 +8,9 @@ import (
 	"time"
 
 	apipac "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/config"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/matcher"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/resolve"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -18,52 +19,37 @@ import (
 const (
 	tektonDir               = ".tekton"
 	maxPipelineRunStatusRun = 5
+	startingPipelineRunText = `Starting Pipelinerun <b>%s</b> in namespace
+	<b>%s</b><br><br>You can follow the execution on the command line with :
+	<br><br><code>tkn pr logs -f -n %s %s</code>`
 )
 
-type Options struct {
-	PayloadFile string
-	RunInfo     webvcs.RunInfo
-}
-
 // The time to wait for a pipelineRun, maybe we should not restrict this?
 const pipelineRunTimeout = 2 * time.Hour
 
-func createStatus(ctx context.Context, cs *cli.Clients, runinfo *webvcs.RunInfo, status, conclusion, text, detailsURL string, logit bool) error {
-	if logit {
-		cs.Log.Infof(text)
-	}
-	_, err := cs.GithubClient.CreateStatus(ctx, runinfo, status, conclusion, text, detailsURL)
-	return err
-}
-
 func fmtDuration(d time.Duration) string {
 	d = d.Round(time.Minute)
 	m := d / time.Minute
 	return fmt.Sprintf("%02d", m)
 }
 
-// Run over the main loop
-func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, runinfo *webvcs.RunInfo) error {
+func Run(ctx context.Context, cs *params.Run, vcsintf webvcs.Interface, k8int kubeinteraction.Interface) error {
 	var err error
 
-	// Create first check run to let know the user we have started the pipeline
-	// TODO: Refactor this bit in a function
-	checkRun, err := cs.GithubClient.CreateCheckRun(ctx, "in_progress", runinfo)
-	if err != nil {
-		return err
-	}
-	// Set the runId on runInfo so if we have an error we can report it on UI (GH checks UI for GH PR)
-	runinfo.CheckRunID = checkRun.ID
-
-	// Check if submitted is allowed to run this.
-	allowed, err := aclCheck(ctx, cs, runinfo)
+	// Check if the submitter is allowed to run this.
+	allowed, err := vcsintf.IsAllowed(ctx, cs.Info.Event)
 	if err != nil {
 		return err
 	}
 
 	if !allowed {
-		msg := fmt.Sprintf("User %s is not allowed to run CI on this repo.", runinfo.Sender)
-		err = createStatus(ctx, cs, runinfo, "completed", "skipped", msg, "https://tenor.com/search/police-cat-gifs", true)
+		msg := fmt.Sprintf("User %s is not allowed to run CI on this repo.", cs.Info.Event.Sender)
+		err = createStatus(ctx, vcsintf, cs, webvcs.StatusOpts{
+			Status:     "completed",
+			Conclusion: "skipped",
+			Text:       msg,
+			DetailsURL: "https://tenor.com/search/police-cat-gifs",
+		}, true)
 		if err != nil {
 			return err
 		}
@@ -73,39 +59,51 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 	// Match the Event to a Repository Resource,
 	// We are going to match on targetNamespace annotation later on in
 	// `MatchPipelinerunByAnnotation`
-	repo, err := config.GetRepoByCR(ctx, cs, "", runinfo)
+	repo, err := matcher.GetRepoByCR(ctx, cs, "")
 	if err != nil {
 		return err
 	}
 
 	if repo == nil || repo.Spec.Namespace == "" {
-		msg := fmt.Sprintf("Could not find a namespace match for %s/%s on target-branch:%s event-type: %s", runinfo.Owner, runinfo.Repository, runinfo.BaseBranch, runinfo.EventType)
-		if runinfo.EventType == "pull_request" || runinfo.TriggerTarget == "issue-recheck" {
-			err = createStatus(ctx, cs, runinfo, "completed", "skipped", msg, "https://tenor.com/search/sad-cat-gifs", true)
+		msg := fmt.Sprintf("Could not find a namespace match for %s/%s on target-branch:%s event-type: %s", cs.Info.Event.Owner, cs.Info.Event.Repository, cs.Info.Event.BaseBranch, cs.Info.Event.EventType)
+		if cs.Info.Event.EventType == "pull_request" || cs.Info.Event.TriggerTarget == "issue-recheck" {
+			err = createStatus(ctx, vcsintf, cs, webvcs.StatusOpts{
+				Status:     "completed",
+				Conclusion: "skipped",
+				Text:       msg,
+				DetailsURL: "https://tenor.com/search/sad-cat-gifs",
+			}, true)
+
 			if err != nil {
 				return err
 			}
 		} else {
-			cs.Log.Infof("Skipping creating status check: %s", msg)
+			cs.Clients.Log.Infof("Skipping creating status check: %s", msg)
 		}
 		return nil
 	}
 
 	// Get everything in tekton directory
-	objects, err := cs.GithubClient.GetTektonDir(ctx, tektonDir, runinfo)
-	if len(objects) == 0 || err != nil {
+	allTemplates, err := vcsintf.GetTektonDir(ctx, cs.Info.Event, tektonDir)
+	if allTemplates == "" || err != nil {
 		msg := "😿 Could not find a <b>.tekton/</b> directory for this repository"
-		err := createStatus(ctx, cs, runinfo, "completed", "skipped",
-			msg, "https://tenor.com/search/sad-cat-gifs", true)
+
+		err = createStatus(ctx, vcsintf, cs, webvcs.StatusOpts{
+			Status:     "completed",
+			Conclusion: "skipped",
+			Text:       msg,
+			DetailsURL: "https://tenor.com/search/sad-cat-gifs",
+		}, true)
+
 		if err != nil {
 			return err
 		}
 		return err
 	}
-	cs.Log.Infow("Loading payload",
-		"url", runinfo.URL,
-		"branch", runinfo.BaseBranch,
-		"sha", runinfo.SHA,
+	cs.Clients.Log.Infow("Loading payload",
+		"url", cs.Info.Event.URL,
+		"branch", cs.Info.Event.BaseBranch,
+		"sha", cs.Info.Event.SHA,
 		"event_type", "pull_request")
 
 	// Make sure we have the namespace already created or error it.
@@ -116,32 +114,26 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 		return err
 	}
 
-	// Concat all yaml files as one multi document yaml string
-	allTemplates, err := cs.GithubClient.ConcatAllYamlFiles(ctx, objects, runinfo)
-	if err != nil {
-		return err
-	}
-
-	// Replace those {{var}} placeholders user has in her template to the runinfo variable
+	// Replace those {{var}} placeholders user has in her template to the cs.Info variable
 	allTemplates = ReplacePlaceHoldersVariables(allTemplates, map[string]string{
-		"revision":   runinfo.SHA,
-		"repo_url":   runinfo.URL,
-		"repo_owner": runinfo.Owner,
-		"repo_name":  runinfo.Repository,
+		"revision":   cs.Info.Event.SHA,
+		"repo_url":   cs.Info.Event.URL,
+		"repo_owner": cs.Info.Event.Owner,
+		"repo_name":  cs.Info.Event.Repository,
 	})
 
 	ropt := &resolve.Opts{
 		GenerateName: true,
-		RemoteTasks:  true,
+		RemoteTasks:  true, // TODO: add an option to disable remote tasking,
 	}
 	// Merge everything (i.e: tasks/pipeline etc..) as a single pipelinerun
-	pipelineRuns, err := resolve.Resolve(ctx, cs, runinfo, allTemplates, ropt)
+	pipelineRuns, err := resolve.Resolve(ctx, cs, vcsintf, allTemplates, ropt)
 	if err != nil {
 		return err
 	}
 
 	// Match the pipelinerun with annotation
-	pipelineRun, annotationRepo, config, err := config.MatchPipelinerunByAnnotation(ctx, pipelineRuns, cs, runinfo)
+	pipelineRun, annotationRepo, config, err := matcher.MatchPipelinerunByAnnotation(ctx, pipelineRuns, cs)
 	if err != nil {
 		return err
 	}
@@ -151,8 +143,8 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 	}
 
 	// Automatically create a secret with the token to be reused by git-clone task
-	if runinfo.SecretAutoCreation {
-		err = k8int.CreateBasicAuthSecret(ctx, *runinfo, repo.Spec.Namespace)
+	if cs.Info.Pac.SecretAutoCreation {
+		err = k8int.CreateBasicAuthSecret(ctx, cs.Info.Event, cs.Info.Pac, repo.Spec.Namespace)
 		if err != nil {
 			return err
 		}
@@ -162,23 +154,23 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 	// query them. Since K8s do not like slash in labels value and on push we
 	// have the full ref, we replace the "/" by "-". The tools probably need to
 	// be aware of it when querying.
-	refTomakeK8Happy := strings.ReplaceAll(runinfo.BaseBranch, "/", "-")
+	refTomakeK8Happy := strings.ReplaceAll(cs.Info.Event.BaseBranch, "/", "-")
 	pipelineRun.Labels = map[string]string{
 		"app.kubernetes.io/managed-by":              "pipelines-as-code",
-		"pipelinesascode.tekton.dev/url-org":        runinfo.Owner,
-		"pipelinesascode.tekton.dev/url-repository": runinfo.Repository,
-		"pipelinesascode.tekton.dev/sha":            runinfo.SHA,
-		"pipelinesascode.tekton.dev/sender":         runinfo.Sender,
-		"pipelinesascode.tekton.dev/event-type":     runinfo.EventType,
+		"pipelinesascode.tekton.dev/url-org":        cs.Info.Event.Owner,
+		"pipelinesascode.tekton.dev/url-repository": cs.Info.Event.Repository,
+		"pipelinesascode.tekton.dev/sha":            cs.Info.Event.SHA,
+		"pipelinesascode.tekton.dev/sender":         cs.Info.Event.Sender,
+		"pipelinesascode.tekton.dev/event-type":     cs.Info.Event.EventType,
 		"pipelinesascode.tekton.dev/branch":         refTomakeK8Happy,
 		"pipelinesascode.tekton.dev/repository":     repo.GetName(),
 	}
 
-	pipelineRun.Annotations["pipelinesascode.tekton.dev/sha-title"] = runinfo.SHATitle
-	pipelineRun.Annotations["pipelinesascode.tekton.dev/sha-url"] = runinfo.SHAURL
+	pipelineRun.Annotations["pipelinesascode.tekton.dev/sha-title"] = cs.Info.Event.SHATitle
+	pipelineRun.Annotations["pipelinesascode.tekton.dev/sha-url"] = cs.Info.Event.SHAURL
 
 	// Create the actual pipeline
-	pr, err := cs.Tekton.TektonV1beta1().PipelineRuns(repo.Spec.Namespace).Create(ctx, pipelineRun, metav1.CreateOptions{})
+	pr, err := cs.Clients.Tekton.TektonV1beta1().PipelineRuns(repo.Spec.Namespace).Create(ctx, pipelineRun, metav1.CreateOptions{})
 	if err != nil {
 		return err
 	}
@@ -191,17 +183,21 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 	}
 
 	// Create status with the log url
-	err = createStatus(ctx, cs, runinfo, "in_progress", "",
-		fmt.Sprintf(`Starting Pipelinerun <b>%s</b> in namespace <b>%s</b><br><br>You can follow the execution on the command line with : <br><br><code>tkn pr logs -f -n %s %s</code>`,
-			pr.GetName(), repo.Spec.Namespace, repo.Spec.Namespace, pr.GetName()),
-		consoleURL, false)
+	msg := fmt.Sprintf(startingPipelineRunText,
+		pr.GetName(), repo.Spec.Namespace, repo.Spec.Namespace, pr.GetName())
+	err = createStatus(ctx, vcsintf, cs, webvcs.StatusOpts{
+		Status:     "in_progress",
+		Conclusion: "",
+		Text:       msg,
+		DetailsURL: consoleURL,
+	}, false)
 	if err != nil {
 		return err
 	}
 
-	cs.Log.Infof("Waiting for PipelineRun %s/%s to Succeed in a maximum time of %s minutes", pr.Namespace, pr.Name, fmtDuration(pipelineRunTimeout))
-	if err := k8int.WaitForPipelineRunSucceed(ctx, cs.Tekton.TektonV1beta1(), pr, pipelineRunTimeout); err != nil {
-		cs.Log.Info("PipelineRun has failed.")
+	cs.Clients.Log.Infof("Waiting for PipelineRun %s/%s to Succeed in a maximum time of %s minutes", pr.Namespace, pr.Name, fmtDuration(pipelineRunTimeout))
+	if err := k8int.WaitForPipelineRunSucceed(ctx, cs.Clients.Tekton.TektonV1beta1(), pr, pipelineRunTimeout); err != nil {
+		cs.Clients.Log.Info("PipelineRun has failed.")
 	}
 
 	// Do cleanups
@@ -219,7 +215,7 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 
 	// Post the final status to GitHub check status with a nice breakdown and
 	// tekton cli describe output.
-	newPr, err := postFinalStatus(ctx, cs, k8int, runinfo, pr.Name, repo.Spec.Namespace)
+	newPr, err := postFinalStatus(ctx, cs, k8int, vcsintf, pr.Name, repo.Spec.Namespace)
 	if err != nil {
 		return err
 	}
@@ -228,16 +224,16 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 		PipelineRunName: newPr.Name,
 		StartTime:       newPr.Status.StartTime,
 		CompletionTime:  newPr.Status.CompletionTime,
-		SHA:             &runinfo.SHA,
-		SHAURL:          &runinfo.SHAURL,
-		Title:           &runinfo.SHATitle,
+		SHA:             &cs.Info.Event.SHA,
+		SHAURL:          &cs.Info.Event.SHAURL,
+		Title:           &cs.Info.Event.SHATitle,
 		LogURL:          &consoleURL,
 	}
 
 	// Get repo again in case it was updated while we were running the CI
 	// NOTE: there may be a race issue we should maybe solve here, between the Get and
 	// Update but we are talking sub-milliseconds issue here.
-	lastrepo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(repo.Spec.Namespace).Get(ctx, repo.Name, metav1.GetOptions{})
+	lastrepo, err := cs.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(repo.Spec.Namespace).Get(ctx, repo.Name, metav1.GetOptions{})
 	if err != nil {
 		return err
 	}
@@ -249,12 +245,12 @@ func Run(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, ru
 	}
 
 	lastrepo.Status = append(lastrepo.Status, repoStatus)
-	nrepo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(lastrepo.Namespace).Update(
+	nrepo, err := cs.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(lastrepo.Namespace).Update(
 		ctx, lastrepo, metav1.UpdateOptions{})
 	if err != nil {
 		return err
 	}
 
-	cs.Log.Infof("Repository status of %s has been updated", nrepo.Name)
+	cs.Clients.Log.Infof("Repository status of %s has been updated", nrepo.Name)
 	return err
 }
diff --git a/pkg/pipelineascode/status.go b/pkg/pipelineascode/status.go
index 55bdb404..47de9cf4 100644
--- a/pkg/pipelineascode/status.go
+++ b/pkg/pipelineascode/status.go
@@ -7,7 +7,8 @@ import (
 	"sort"
 	"text/template"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	tektonv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	corev1 "k8s.io/api/core/v1"
@@ -132,10 +133,19 @@ func statusOfAllTaskListForCheckRun(pr *tektonv1beta1.PipelineRun, consoleURL st
 	return outputBuffer.String(), nil
 }
 
-func postFinalStatus(ctx context.Context, cs *cli.Clients, k8int cli.KubeInteractionIntf, runinfo *webvcs.RunInfo, prName, namespace string) (*tektonv1beta1.PipelineRun, error) {
+func createStatus(ctx context.Context, vcsintf webvcs.Interface,
+	cs *params.Run, status webvcs.StatusOpts, logit bool) error {
+	if logit {
+		cs.Clients.Log.Infof(status.Text)
+	}
+	return vcsintf.CreateStatus(ctx, cs.Info.Event, cs.Info.Pac, status)
+}
+
+func postFinalStatus(ctx context.Context, cs *params.Run, k8int kubeinteraction.Interface, vcsintf webvcs.Interface,
+	prName, namespace string) (*tektonv1beta1.PipelineRun, error) {
 	var outputBuffer bytes.Buffer
 
-	pr, err := cs.Tekton.TektonV1beta1().PipelineRuns(namespace).Get(ctx, prName, v1.GetOptions{})
+	pr, err := cs.Clients.Tekton.TektonV1beta1().PipelineRuns(namespace).Get(ctx, prName, v1.GetOptions{})
 	if err != nil {
 		return pr, err
 	}
@@ -160,8 +170,12 @@ func postFinalStatus(ctx context.Context, cs *cli.Clients, k8int cli.KubeInterac
 		return pr, err
 	}
 
-	err = createStatus(ctx, cs, runinfo, "completed", pipelineRunStatus(pr),
-		outputBuffer.String(), consoleURL, false)
+	err = createStatus(ctx, vcsintf, cs, webvcs.StatusOpts{
+		Status:     "completed",
+		Conclusion: pipelineRunStatus(pr),
+		Text:       outputBuffer.String(),
+		DetailsURL: consoleURL,
+	}, false)
 
 	return pr, err
 }
diff --git a/pkg/resolve/resolve.go b/pkg/resolve/resolve.go
index 547259b1..6346e155 100644
--- a/pkg/resolve/resolve.go
+++ b/pkg/resolve/resolve.go
@@ -6,10 +6,11 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/config"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/matcher"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	tektonv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+	"go.uber.org/zap"
 	k8scheme "k8s.io/client-go/kubernetes/scheme"
 )
 
@@ -20,7 +21,7 @@ type Types struct {
 	Tasks        []*tektonv1beta1.Task
 }
 
-func readTypes(cs *cli.Clients, data string) Types {
+func readTypes(log *zap.SugaredLogger, data string) Types {
 	types := Types{}
 	decoder := k8scheme.Codecs.UniversalDeserializer()
 
@@ -31,7 +32,7 @@ func readTypes(cs *cli.Clients, data string) Types {
 
 		obj, _, err := decoder.Decode([]byte(doc), nil, nil)
 		if err != nil {
-			cs.Log.Infof("Skipping document not looking like a kubernetes resources: %v", err)
+			log.Infof("Skipping document not looking like a kubernetes resources: %v", err)
 			continue
 		}
 		switch o := obj.(type) {
@@ -42,7 +43,7 @@ func readTypes(cs *cli.Clients, data string) Types {
 		case *tektonv1beta1.Task:
 			types.Tasks = append(types.Tasks, o)
 		default:
-			cs.Log.Info("Skipping document not looking like a tekton resource we can Resolve.")
+			log.Info("Skipping document not looking like a tekton resource we can Resolve.")
 		}
 	}
 
@@ -103,14 +104,14 @@ type Opts struct {
 // Pipeline/PipelineRuns/Tasks and resolve them inline as a single PipelineRun
 // generateName can be set as True to set the name as a generateName + "-" for
 // unique pipelinerun
-func Resolve(ctx context.Context, cs *cli.Clients, runinfo *webvcs.RunInfo, data string, ropt *Opts) (
+func Resolve(ctx context.Context, cs *params.Run, vcsintf webvcs.Interface, data string, ropt *Opts) (
 	[]*tektonv1beta1.PipelineRun, error) {
 	s := k8scheme.Scheme
 	if err := tektonv1beta1.AddToScheme(s); err != nil {
 		return []*tektonv1beta1.PipelineRun{}, err
 	}
 
-	types := readTypes(cs, data)
+	types := readTypes(cs.Clients.Log, data)
 	if len(types.PipelineRuns) == 0 {
 		return []*tektonv1beta1.PipelineRun{}, errors.New("we need at least one pipelinerun to start with")
 	}
@@ -118,11 +119,10 @@ func Resolve(ctx context.Context, cs *cli.Clients, runinfo *webvcs.RunInfo, data
 	// First resolve Annotations Tasks
 	for _, pipelinerun := range types.PipelineRuns {
 		if ropt.RemoteTasks && pipelinerun.GetObjectMeta().GetAnnotations() != nil {
-			rt := config.RemoteTasks{
-				Clients: cs,
-				Runinfo: runinfo,
+			rt := matcher.RemoteTasks{
+				Run: cs,
 			}
-			remoteTasks, err := rt.GetTaskFromAnnotations(ctx, pipelinerun.GetObjectMeta().GetAnnotations())
+			remoteTasks, err := rt.GetTaskFromAnnotations(ctx, vcsintf, pipelinerun.GetObjectMeta().GetAnnotations())
 			if err != nil {
 				return []*tektonv1beta1.PipelineRun{}, err
 			}
diff --git a/pkg/webvcs/github.go b/pkg/webvcs/github.go
deleted file mode 100644
index ecaf51f0..00000000
--- a/pkg/webvcs/github.go
+++ /dev/null
@@ -1,465 +0,0 @@
-package webvcs
-
-import (
-	"context"
-	"encoding/base64"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"net/http"
-	"path"
-	"regexp"
-	"strconv"
-	"strings"
-	"time"
-
-	"github.com/google/go-github/v35/github"
-	"go.uber.org/zap"
-	"golang.org/x/oauth2"
-)
-
-type GithubVCS struct {
-	Client        *github.Client
-	Token, APIURL string
-}
-
-// RunInfo Information about current run
-type RunInfo struct {
-	BaseBranch         string // branch against where we are making the PR
-	CheckRunID         *int64
-	DefaultBranch      string
-	Event              interface{}
-	EventType          string
-	HeadBranch         string // branch from where our SHA get tested
-	Owner              string
-	Repository         string
-	SHA                string
-	SHAURL             string
-	Sender             string
-	TriggerTarget      string
-	URL                string
-	LogURL             string
-	SHATitle           string
-	ApplicationName    string // the Application Name for example "Pipelines as Code"
-	SecretAutoCreation bool   // secret auto creation in target namespace
-}
-
-// Check check if the runinfo is properly set
-func (r RunInfo) Check() error {
-	if r.SHA != "" && r.BaseBranch != "" &&
-		r.Repository != "" && r.DefaultBranch != "" &&
-		r.HeadBranch != "" && r.Owner != "" && r.URL != "" &&
-		r.Sender != "" && r.EventType != "" && r.TriggerTarget != "" {
-		return nil
-	}
-	return fmt.Errorf("missing values in runInfo")
-}
-
-// DeepCopyInto deep copy runinfo in another instance
-func (r *RunInfo) DeepCopyInto(out *RunInfo) {
-	*out = *r
-}
-
-// NewGithubVCS Create a new GitHub VCS object for token
-func NewGithubVCS(token string, apiURL string) GithubVCS {
-	ts := oauth2.StaticTokenSource(
-		&oauth2.Token{AccessToken: token},
-	)
-	tc := oauth2.NewClient(context.Background(), ts)
-
-	var client *github.Client
-	if apiURL != "" {
-		if !strings.HasPrefix(apiURL, "https") {
-			apiURL = "https://" + apiURL
-		}
-		client, _ = github.NewEnterpriseClient(apiURL, apiURL, tc)
-	} else {
-		client = github.NewClient(tc)
-	}
-	return GithubVCS{
-		Client: client,
-		Token:  token,
-		APIURL: apiURL,
-	}
-}
-
-// payloadFix since we are getting a bunch of \r\n or \n and others from triggers/github, so let just
-// workaround it. Originally from https://stackoverflow.com/a/52600147
-func payloadFix(payload string) string {
-	replacement := " "
-	replacer := strings.NewReplacer(
-		"\r\n", replacement,
-		"\r", replacement,
-		"\n", replacement,
-		"\v", replacement,
-		"\f", replacement,
-		"\u0085", replacement,
-		"\u2028", replacement,
-		"\u2029", replacement,
-	)
-	return replacer.Replace(payload)
-}
-
-func (v GithubVCS) handleReRequestEvent(ctx context.Context, log *zap.SugaredLogger, event *github.CheckRunEvent) (RunInfo, error) {
-	runinfo := RunInfo{
-		Owner:         event.GetRepo().GetOwner().GetLogin(),
-		Repository:    event.GetRepo().GetName(),
-		URL:           event.GetRepo().GetHTMLURL(),
-		DefaultBranch: event.GetRepo().GetDefaultBranch(),
-		SHA:           event.GetCheckRun().GetCheckSuite().GetHeadSHA(),
-		HeadBranch:    event.GetCheckRun().GetCheckSuite().GetHeadBranch(),
-	}
-	// If we don't have a pull_request in this it probably mean a push
-	if len(event.GetCheckRun().GetCheckSuite().PullRequests) == 0 {
-		runinfo.BaseBranch = runinfo.HeadBranch
-		runinfo.EventType = "push"
-		// we allow the rerequest user here, not the push user, i guess it's
-		// fine because you can't do a rereq without being a github owner?
-		runinfo.Sender = event.GetSender().GetLogin()
-		return runinfo, nil
-	}
-	prNumber := event.GetCheckRun().GetCheckSuite().PullRequests[0].GetNumber()
-	log.Infof("Recheck of PR %s/%s#%d has been requested", runinfo.Owner, runinfo.Repository, prNumber)
-	return v.getPullRequest(ctx, runinfo, prNumber)
-}
-
-func convertPullRequestURLtoNumber(pullRequest string) (int, error) {
-	prNumber, err := strconv.Atoi(path.Base(pullRequest))
-	if err != nil {
-		return -1, err
-	}
-	return prNumber, nil
-}
-
-func (v GithubVCS) handleIssueCommentEvent(ctx context.Context, log *zap.SugaredLogger, event *github.IssueCommentEvent) (RunInfo, error) {
-	runinfo := RunInfo{
-		Owner:      event.GetRepo().GetOwner().GetLogin(),
-		Repository: event.GetRepo().GetName(),
-	}
-
-	if !event.GetIssue().IsPullRequest() {
-		return RunInfo{}, fmt.Errorf("issue comment is not coming from a pull_request")
-	}
-
-	// We are getting the full URL so we have to get the last part to get the PR number,
-	// we don't have to care about URL query string/hash and other stuff because
-	// that comes up from the API.
-	prNumber, err := convertPullRequestURLtoNumber(event.GetIssue().GetPullRequestLinks().GetHTMLURL())
-	if err != nil {
-		return RunInfo{}, err
-	}
-
-	log.Infof("PR recheck from issue commment on %s/%s#%d has been requested", runinfo.Owner, runinfo.Repository, prNumber)
-	return v.getPullRequest(ctx, runinfo, prNumber)
-}
-
-// getPullRequest get a pull request details
-func (v GithubVCS) getPullRequest(ctx context.Context, runinfo RunInfo, prNumber int) (RunInfo, error) {
-	pr, _, err := v.Client.PullRequests.Get(ctx, runinfo.Owner, runinfo.Repository, prNumber)
-	if err != nil {
-		return runinfo, err
-	}
-	// Make sure to use the Base for Default BaseBranch or there would be a potential hijack
-	runinfo.DefaultBranch = pr.GetBase().GetRepo().GetDefaultBranch()
-	runinfo.URL = pr.GetBase().GetRepo().GetHTMLURL()
-	runinfo.SHA = pr.GetHead().GetSHA()
-	runinfo.SHAURL = fmt.Sprintf("%s/commit/%s", pr.GetHTMLURL(), pr.GetHead().GetSHA())
-	// TODO: Maybe if we wanted to allow rerequest from non approved user we
-	// would use the CheckRun Sender instead of the rerequest sender, could it
-	// be a room for abuse? 🤔
-	runinfo.Sender = pr.GetUser().GetLogin()
-	runinfo.HeadBranch = pr.GetHead().GetRef()
-	runinfo.BaseBranch = pr.GetBase().GetRef()
-	runinfo.EventType = "pull_request"
-	return runinfo, nil
-}
-
-// populateCommitInfo get info on a commit in runinfo
-func (v GithubVCS) populateCommitInfo(ctx context.Context, runinfo *RunInfo) error {
-	commit, _, err := v.Client.Git.GetCommit(ctx, runinfo.Owner, runinfo.Repository, runinfo.SHA)
-	if err != nil {
-		return err
-	}
-
-	runinfo.SHAURL = commit.GetHTMLURL()
-	runinfo.SHATitle = strings.Split(commit.GetMessage(), "\n\n")[0]
-
-	return nil
-}
-
-// ParsePayload parse payload event
-// TODO: this piece of code is just plain silly
-func (v GithubVCS) ParsePayload(ctx context.Context, log *zap.SugaredLogger, optRunInfo RunInfo, payload string) (*RunInfo, error) {
-	var runinfo RunInfo
-	payload = payloadFix(payload)
-	event, err := github.ParseWebHook(optRunInfo.EventType, []byte(payloadFix(payload)))
-	if err != nil {
-		return &runinfo, err
-	}
-	err = json.Unmarshal([]byte(payload), &event)
-	if err != nil {
-		return &runinfo, err
-	}
-
-	switch event := event.(type) {
-	case *github.CheckRunEvent:
-		if optRunInfo.TriggerTarget == "issue-recheck" {
-			runinfo, err = v.handleReRequestEvent(ctx, log, event)
-			if err != nil {
-				return &runinfo, err
-			}
-		}
-	case *github.IssueCommentEvent:
-		runinfo, err = v.handleIssueCommentEvent(ctx, log, event)
-		if err != nil {
-			return &runinfo, err
-		}
-	case *github.PushEvent:
-		runinfo = RunInfo{
-			Owner:         event.GetRepo().GetOwner().GetLogin(),
-			Repository:    event.GetRepo().GetName(),
-			DefaultBranch: event.GetRepo().GetDefaultBranch(),
-			URL:           event.GetRepo().GetHTMLURL(),
-			SHA:           event.GetHeadCommit().GetID(),
-			SHAURL:        event.GetHeadCommit().GetURL(),
-			SHATitle:      event.GetHeadCommit().GetMessage(),
-			Sender:        event.GetSender().GetLogin(),
-			BaseBranch:    event.GetRef(),
-			EventType:     optRunInfo.TriggerTarget,
-		}
-
-		runinfo.HeadBranch = runinfo.BaseBranch // in push events Head Branch is the same as Basebranch
-	case *github.PullRequestEvent:
-		runinfo = RunInfo{
-			Owner:         event.GetRepo().Owner.GetLogin(),
-			Repository:    event.GetRepo().GetName(),
-			DefaultBranch: event.GetRepo().GetDefaultBranch(),
-			SHA:           event.GetPullRequest().Head.GetSHA(),
-			URL:           event.GetRepo().GetHTMLURL(),
-			BaseBranch:    event.GetPullRequest().Base.GetRef(),
-			HeadBranch:    event.GetPullRequest().Head.GetRef(),
-			Sender:        event.GetPullRequest().GetUser().GetLogin(),
-			EventType:     optRunInfo.EventType,
-		}
-	default:
-		return &runinfo, errors.New("this event is not supported")
-	}
-
-	err = v.populateCommitInfo(ctx, &runinfo)
-	if err != nil {
-		return nil, err
-	}
-
-	runinfo.Event = event
-	runinfo.TriggerTarget = optRunInfo.TriggerTarget
-	runinfo.SecretAutoCreation = optRunInfo.SecretAutoCreation
-	return &runinfo, nil
-}
-
-// CheckSenderOrgMembership Get sender user's organization. We can
-// only get the one that the user sets as public 🤷
-func (v GithubVCS) CheckSenderOrgMembership(ctx context.Context, runinfo *RunInfo) (bool, error) {
-	users, resp, err := v.Client.Organizations.ListMembers(ctx, runinfo.Owner,
-		&github.ListMembersOptions{
-			PublicOnly: true, // We can't list private member in a org
-		})
-	// If we are 404 it means we are checking a repo owner and not a org so let's bail out with grace
-	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
-		return false, nil
-	}
-
-	if err != nil {
-		return false, err
-	}
-	for _, v := range users {
-		if v.GetLogin() == runinfo.Sender {
-			return true, nil
-		}
-	}
-
-	return false, nil
-}
-
-// GetStringPullRequestComment return the comment if we find a regexp in one of
-// the comments text of a pull request
-func (v GithubVCS) GetStringPullRequestComment(ctx context.Context, runinfo *RunInfo, reg string) ([]*github.IssueComment, error) {
-	var ret []*github.IssueComment
-	prNumber, err := convertPullRequestURLtoNumber(runinfo.URL)
-	if err != nil {
-		return nil, err
-	}
-	comments, _, err := v.Client.Issues.ListComments(ctx, runinfo.Owner, runinfo.Repository,
-		prNumber, &github.IssueListCommentsOptions{})
-	if err != nil {
-		return nil, err
-	}
-
-	re := regexp.MustCompile(reg)
-	for _, v := range comments {
-		if string(re.Find([]byte(v.GetBody()))) != "" {
-			ret = append(ret, v)
-		}
-	}
-	return ret, nil
-}
-
-// GetTektonDir Get tekton directory from a repository
-func (v GithubVCS) GetTektonDir(ctx context.Context, path string, runinfo *RunInfo) ([]*github.RepositoryContent, error) {
-	fp, objects, resp, err := v.Client.Repositories.GetContents(ctx, runinfo.Owner,
-		runinfo.Repository, path, &github.RepositoryContentGetOptions{Ref: runinfo.SHA})
-
-	if fp != nil {
-		return nil, fmt.Errorf("the object %s is a file instead of a directory", path)
-	}
-	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
-		return nil, nil
-	}
-
-	if err != nil {
-		return nil, err
-	}
-
-	return objects, nil
-}
-
-// GetFileInsideRepo Get a file via Github API using the runinfo information, we
-// branch is true, the user the branch as ref isntead of the SHA
-func (v GithubVCS) GetFileInsideRepo(ctx context.Context, path string, branch bool, runinfo *RunInfo) (string, error) {
-	ref := runinfo.SHA
-	if branch {
-		ref = runinfo.BaseBranch
-	}
-
-	fp, objects, resp, err := v.Client.Repositories.GetContents(ctx, runinfo.Owner,
-		runinfo.Repository, path, &github.RepositoryContentGetOptions{Ref: ref})
-	if err != nil {
-		return "", err
-	}
-	if objects != nil {
-		return "", fmt.Errorf("referenced file inside the Github Repository %s is a directory", path)
-	}
-	if resp.Response.StatusCode == http.StatusNotFound {
-		return "", fmt.Errorf("cannot find %s in this repository", path)
-	}
-
-	getobj, err := v.GetObject(ctx, fp.GetSHA(), runinfo)
-	if err != nil {
-		return "", err
-	}
-
-	return string(getobj), nil
-}
-
-// GetFileFromDefaultBranch will get a file directly from the Default BaseBranch as
-// configured in runinfo which is directly set in webhook by Github
-func (v GithubVCS) GetFileFromDefaultBranch(ctx context.Context, path string, runinfo *RunInfo) (string, error) {
-	runInfoOnMain := &RunInfo{}
-	runinfo.DeepCopyInto(runInfoOnMain)
-	runInfoOnMain.BaseBranch = runInfoOnMain.DefaultBranch
-
-	tektonyaml, err := v.GetFileInsideRepo(ctx, path, true, runInfoOnMain)
-	if err != nil {
-		return "", fmt.Errorf("cannot find %s inside the %s branch: %w", path, runInfoOnMain.BaseBranch, err)
-	}
-	return tektonyaml, err
-}
-
-// ConcatAllYamlFiles concat all yaml files from a directory as one big multi document yaml string
-// TODO: trash the tekton.yaml condition when we don't need it anymore
-func (v GithubVCS) ConcatAllYamlFiles(ctx context.Context, objects []*github.RepositoryContent, runinfo *RunInfo) (string, error) {
-	var allTemplates string
-
-	for _, value := range objects {
-		if strings.HasSuffix(value.GetName(), ".yaml") ||
-			strings.HasSuffix(value.GetName(), ".yml") {
-			data, err := v.GetObject(ctx, value.GetSHA(), runinfo)
-			if err != nil {
-				return "", err
-			}
-			if allTemplates != "" && !strings.HasPrefix(string(data), "---") {
-				allTemplates += "---"
-			}
-			allTemplates += "\n" + string(data) + "\n"
-		}
-	}
-	return allTemplates, nil
-}
-
-// GetObject Get an object from a repository
-func (v GithubVCS) GetObject(ctx context.Context, sha string, runinfo *RunInfo) ([]byte, error) {
-	blob, _, err := v.Client.Git.GetBlob(ctx, runinfo.Owner, runinfo.Repository, sha)
-	if err != nil {
-		return nil, err
-	}
-
-	decoded, err := base64.StdEncoding.DecodeString(blob.GetContent())
-	if err != nil {
-		return nil, err
-	}
-	return decoded, err
-}
-
-func (v GithubVCS) CreateCheckRun(ctx context.Context, status string, runinfo *RunInfo) (*github.CheckRun, error) {
-	now := github.Timestamp{Time: time.Now()}
-	checkrunoption := github.CreateCheckRunOptions{
-		Name:       runinfo.ApplicationName,
-		HeadSHA:    runinfo.SHA,
-		Status:     &status,
-		DetailsURL: &runinfo.LogURL,
-		StartedAt:  &now,
-	}
-
-	checkRun, _, err := v.Client.Checks.CreateCheckRun(ctx, runinfo.Owner, runinfo.Repository, checkrunoption)
-	return checkRun, err
-}
-
-func (v GithubVCS) CreateStatus(ctx context.Context, runinfo *RunInfo, status, conclusion, text, detailsURL string) (*github.CheckRun, error) {
-	now := github.Timestamp{Time: time.Now()}
-
-	var summary, title string
-
-	switch conclusion {
-	case "success":
-		title = "✅ Success"
-		summary = fmt.Sprintf("%s has successfully validated your commit.", runinfo.ApplicationName)
-	case "failure":
-		title = "❌ Failed"
-		summary = fmt.Sprintf("%s has <b>failed</b>.", runinfo.ApplicationName)
-	case "skipped":
-		title = "➖ Skipped"
-		summary = fmt.Sprintf("%s is skipping this commit.", runinfo.ApplicationName)
-	case "neutral":
-		title = "❓ Unknown"
-		summary = fmt.Sprintf("%s doesn't know what happened with this commit.", runinfo.ApplicationName)
-	}
-
-	if status == "in_progress" {
-		title = "CI has Started"
-		summary = fmt.Sprintf("%s is running.", runinfo.ApplicationName)
-	}
-
-	checkRunOutput := &github.CheckRunOutput{
-		Title:   &title,
-		Summary: &summary,
-		Text:    &text,
-	}
-
-	opts := github.UpdateCheckRunOptions{
-		Name:   runinfo.ApplicationName,
-		Status: &status,
-		Output: checkRunOutput,
-	}
-
-	if detailsURL != "" {
-		opts.DetailsURL = &detailsURL
-	}
-
-	// Only set completed-at if conclusion is set (which means finished)
-	if conclusion != "" {
-		opts.CompletedAt = &now
-		opts.Conclusion = &conclusion
-	}
-
-	checkRun, _, err := v.Client.Checks.UpdateCheckRun(ctx, runinfo.Owner, runinfo.Repository, *runinfo.CheckRunID, opts)
-	return checkRun, err
-}
diff --git a/pkg/webvcs/github/acl.go b/pkg/webvcs/github/acl.go
new file mode 100644
index 00000000..7812fb75
--- /dev/null
+++ b/pkg/webvcs/github/acl.go
@@ -0,0 +1,174 @@
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"regexp"
+	"strings"
+
+	"github.com/google/go-github/v35/github"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"sigs.k8s.io/yaml"
+)
+
+var okToTestCommentRegexp = `(^|\n)/ok-to-test(\r\n|$)`
+
+func (v VCS) IsAllowed(ctx context.Context, event *info.Event) (bool, error) {
+	// Do most of the checks first, if user is a owner or in a organisation
+	allowed, err := v.aclCheckAll(ctx, event)
+	if err != nil {
+		return false, err
+	}
+	if allowed {
+		return true, nil
+	}
+
+	// Finally try to parse all comments
+	return v.aclAllowedOkToTestFromAnOwner(ctx, event)
+}
+
+// allowedOkToTestFromAnOwner Goes on evry comments in a pull-request and sess
+// if there is a /ok-to-test in there running an aclCheck again on the commment
+// Sender if she is an OWNER and then allow it to run CI.
+// TODO: pull out the github logic from there in an agnostic way.
+func (v VCS) aclAllowedOkToTestFromAnOwner(ctx context.Context, event *info.Event) (bool, error) {
+	revent := event
+	revent.EventType = ""
+	revent.TriggerTarget = ""
+	if revent.Event == nil {
+		return false, nil
+	}
+
+	switch event := revent.Event.(type) {
+	case *github.IssueCommentEvent:
+		revent.URL = event.Issue.GetPullRequestLinks().GetHTMLURL()
+	case *github.PullRequestEvent:
+		revent.URL = event.GetPullRequest().GetHTMLURL()
+	default:
+		return false, nil
+	}
+
+	comments, err := v.GetStringPullRequestComment(ctx, revent, okToTestCommentRegexp)
+	if err != nil {
+		return false, err
+	}
+
+	for _, comment := range comments {
+		revent.Sender = comment.User.GetLogin()
+		allowed, err := v.aclCheckAll(ctx, revent)
+		if err != nil {
+			return false, err
+		}
+		if allowed {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+// ownersConfig prow owner, only supporting approvers or reviewers in yaml
+type ownersConfig struct {
+	Approvers []string `json:"approvers,omitempty"`
+	Reviewers []string `json:"reviewers,omitempty"`
+}
+
+// aclCheck check if we are allowed to run the pipeline on that PR
+func (v VCS) aclCheckAll(ctx context.Context, rev *info.Event) (bool, error) {
+	if rev.Owner == rev.Sender {
+		return true, nil
+	}
+
+	// If the user who has submitted the pr is a owner on the repo then allows
+	// the CI to be run.
+	isUserMemberRepo, err := v.checkSenderOrgMembership(ctx, rev)
+	if err != nil {
+		return false, err
+	}
+
+	if isUserMemberRepo {
+		return true, nil
+	}
+
+	// If we have a prow OWNERS file in the defaultBranch (ie: master) then
+	// parse it in approvers and reviewers field and check if sender is in there.
+	ownerFile, err := v.getFileFromDefaultBranch(ctx, "OWNERS", rev)
+
+	// Don't error out if the OWNERS file cannot be found
+	if err != nil && !strings.Contains(err.Error(), "cannot find") {
+		return false, err
+	} else if ownerFile != "" {
+		var ownerConfig ownersConfig
+		err := yaml.Unmarshal([]byte(ownerFile), &ownerConfig)
+		if err != nil {
+			return false, err
+		}
+		for _, owner := range append(ownerConfig.Approvers, ownerConfig.Reviewers...) {
+			if owner == rev.Sender {
+				return true, nil
+			}
+		}
+	}
+
+	return false, nil
+}
+
+// checkSenderOrgMembership Get sender user's organization. We can
+// only get the one that the user sets as public 🤷
+func (v VCS) checkSenderOrgMembership(ctx context.Context, runevent *info.Event) (bool, error) {
+	users, resp, err := v.Client.Organizations.ListMembers(ctx, runevent.Owner,
+		&github.ListMembersOptions{
+			PublicOnly: true, // We can't list private member in a org
+		})
+	// If we are 404 it means we are checking a repo owner and not a org so let's bail out with grace
+	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
+		return false, nil
+	}
+
+	if err != nil {
+		return false, err
+	}
+	for _, v := range users {
+		if v.GetLogin() == runevent.Sender {
+			return true, nil
+		}
+	}
+
+	return false, nil
+}
+
+// getFileFromDefaultBranch will get a file directly from the Default BaseBranch as
+// configured in runinfo which is directly set in webhook by Github
+func (v VCS) getFileFromDefaultBranch(ctx context.Context, path string, runevent *info.Event) (string, error) {
+	runEventOnMain := runevent
+	runEventOnMain.BaseBranch = runEventOnMain.DefaultBranch
+
+	tektonyaml, err := v.GetFileInsideRepo(ctx, runEventOnMain, path, true)
+	if err != nil {
+		return "", fmt.Errorf("cannot find %s inside the %s branch: %w", path, runEventOnMain.BaseBranch, err)
+	}
+	return tektonyaml, err
+}
+
+// GetStringPullRequestComment return the comment if we find a regexp in one of
+// the comments text of a pull request
+func (v VCS) GetStringPullRequestComment(ctx context.Context, runevent *info.Event, reg string) ([]*github.IssueComment, error) {
+	var ret []*github.IssueComment
+	prNumber, err := convertPullRequestURLtoNumber(runevent.URL)
+	if err != nil {
+		return nil, err
+	}
+	comments, _, err := v.Client.Issues.ListComments(ctx, runevent.Owner, runevent.Repository,
+		prNumber, &github.IssueListCommentsOptions{})
+	if err != nil {
+		return nil, err
+	}
+
+	re := regexp.MustCompile(reg)
+	for _, v := range comments {
+		if string(re.Find([]byte(v.GetBody()))) != "" {
+			ret = append(ret, v)
+		}
+	}
+	return ret, nil
+}
diff --git a/pkg/webvcs/github/events.go b/pkg/webvcs/github/events.go
new file mode 100644
index 00000000..79a5f4cc
--- /dev/null
+++ b/pkg/webvcs/github/events.go
@@ -0,0 +1,157 @@
+package github
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"path"
+	"strconv"
+	"strings"
+
+	"github.com/google/go-github/v35/github"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"go.uber.org/zap"
+)
+
+// payloadFix since we are getting a bunch of \r\n or \n and others from triggers/github, so let just
+// workaround it. Originally from https://stackoverflow.com/a/52600147
+func (v VCS) payloadFix(payload string) []byte {
+	replacement := " "
+	replacer := strings.NewReplacer(
+		"\r\n", replacement,
+		"\r", replacement,
+		"\n", replacement,
+		"\v", replacement,
+		"\f", replacement,
+		"\u0085", replacement,
+		"\u2028", replacement,
+		"\u2029", replacement,
+	)
+	return []byte(replacer.Replace(payload))
+}
+
+// ParsePayload parse payload event
+// TODO: this piece of code is just plain silly
+func (v VCS) ParsePayload(ctx context.Context, log *zap.SugaredLogger, runevent *info.Event, payload string) (*info.Event, error) {
+	var processedevent *info.Event
+	payloadTreated := v.payloadFix(payload)
+	event, err := github.ParseWebHook(runevent.EventType, payloadTreated)
+	if err != nil {
+		return &info.Event{}, err
+	}
+
+	err = json.Unmarshal(payloadTreated, &event)
+	if err != nil {
+		return &info.Event{}, err
+	}
+
+	switch event := event.(type) {
+	case *github.CheckRunEvent:
+		if runevent.TriggerTarget == "issue-recheck" {
+			processedevent, err = v.handleReRequestEvent(ctx, log, event)
+			if err != nil {
+				return &info.Event{}, err
+			}
+		}
+	case *github.IssueCommentEvent:
+		processedevent, err = v.handleIssueCommentEvent(ctx, log, event)
+		if err != nil {
+			return &info.Event{}, err
+		}
+	case *github.PushEvent:
+		processedevent = &info.Event{
+			Owner:         event.GetRepo().GetOwner().GetLogin(),
+			Repository:    event.GetRepo().GetName(),
+			DefaultBranch: event.GetRepo().GetDefaultBranch(),
+			URL:           event.GetRepo().GetHTMLURL(),
+			SHA:           event.GetHeadCommit().GetID(),
+			SHAURL:        event.GetHeadCommit().GetURL(),
+			SHATitle:      event.GetHeadCommit().GetMessage(),
+			Sender:        event.GetSender().GetLogin(),
+			BaseBranch:    event.GetRef(),
+			EventType:     runevent.TriggerTarget,
+		}
+
+		processedevent.HeadBranch = processedevent.BaseBranch // in push events Head Branch is the same as Basebranch
+	case *github.PullRequestEvent:
+		processedevent = &info.Event{
+			Owner:         event.GetRepo().Owner.GetLogin(),
+			Repository:    event.GetRepo().GetName(),
+			DefaultBranch: event.GetRepo().GetDefaultBranch(),
+			SHA:           event.GetPullRequest().Head.GetSHA(),
+			URL:           event.GetRepo().GetHTMLURL(),
+			BaseBranch:    event.GetPullRequest().Base.GetRef(),
+			HeadBranch:    event.GetPullRequest().Head.GetRef(),
+			Sender:        event.GetPullRequest().GetUser().GetLogin(),
+			EventType:     runevent.EventType,
+		}
+
+	default:
+		return &info.Event{}, errors.New("this event is not supported")
+	}
+
+	err = v.populateCommitInfo(ctx, processedevent)
+	if err != nil {
+		return &info.Event{}, err
+	}
+
+	processedevent.Event = event
+	processedevent.TriggerTarget = runevent.TriggerTarget
+
+	return processedevent, nil
+}
+
+func (v VCS) handleReRequestEvent(ctx context.Context, log *zap.SugaredLogger, event *github.CheckRunEvent) (*info.Event, error) {
+	runevent := &info.Event{
+		Owner:         event.GetRepo().GetOwner().GetLogin(),
+		Repository:    event.GetRepo().GetName(),
+		URL:           event.GetRepo().GetHTMLURL(),
+		DefaultBranch: event.GetRepo().GetDefaultBranch(),
+		SHA:           event.GetCheckRun().GetCheckSuite().GetHeadSHA(),
+		HeadBranch:    event.GetCheckRun().GetCheckSuite().GetHeadBranch(),
+	}
+
+	// If we don't have a pull_request in this it probably mean a push
+	if len(event.GetCheckRun().GetCheckSuite().PullRequests) == 0 {
+		runevent.BaseBranch = runevent.HeadBranch
+		runevent.EventType = "push"
+		// we allow the rerequest user here, not the push user, i guess it's
+		// fine because you can't do a rereq without being a github owner?
+		runevent.Sender = event.GetSender().GetLogin()
+		return runevent, nil
+	}
+	prNumber := event.GetCheckRun().GetCheckSuite().PullRequests[0].GetNumber()
+	log.Infof("Recheck of PR %s/%s#%d has been requested", runevent.Owner, runevent.Repository, prNumber)
+	return v.getPullRequest(ctx, runevent, prNumber)
+}
+
+func convertPullRequestURLtoNumber(pullRequest string) (int, error) {
+	prNumber, err := strconv.Atoi(path.Base(pullRequest))
+	if err != nil {
+		return -1, err
+	}
+	return prNumber, nil
+}
+
+func (v VCS) handleIssueCommentEvent(ctx context.Context, log *zap.SugaredLogger, event *github.IssueCommentEvent) (*info.Event, error) {
+	runevent := &info.Event{
+		Owner:      event.GetRepo().GetOwner().GetLogin(),
+		Repository: event.GetRepo().GetName(),
+	}
+
+	if !event.GetIssue().IsPullRequest() {
+		return &info.Event{}, fmt.Errorf("issue comment is not coming from a pull_request")
+	}
+
+	// We are getting the full URL so we have to get the last part to get the PR number,
+	// we don't have to care about URL query string/hash and other stuff because
+	// that comes up from the API.
+	prNumber, err := convertPullRequestURLtoNumber(event.GetIssue().GetPullRequestLinks().GetHTMLURL())
+	if err != nil {
+		return &info.Event{}, err
+	}
+
+	log.Infof("PR recheck from issue commment on %s/%s#%d has been requested", runevent.Owner, runevent.Repository, prNumber)
+	return v.getPullRequest(ctx, runevent, prNumber)
+}
diff --git a/pkg/webvcs/github/github.go b/pkg/webvcs/github/github.go
new file mode 100644
index 00000000..b92efc71
--- /dev/null
+++ b/pkg/webvcs/github/github.go
@@ -0,0 +1,238 @@
+package github
+
+import (
+	"context"
+	"encoding/base64"
+	"fmt"
+	"net/http"
+	"strings"
+	"time"
+
+	"github.com/google/go-github/v35/github"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"golang.org/x/oauth2"
+)
+
+type VCS struct {
+	Client        *github.Client
+	Token, APIURL string
+}
+
+// NewGithubVCS Create a new GitHub VCS object for token
+func NewGithubVCS(ctx context.Context, info info.PacOpts) VCS {
+	ts := oauth2.StaticTokenSource(
+		&oauth2.Token{AccessToken: info.VCSToken},
+	)
+	tc := oauth2.NewClient(ctx, ts)
+
+	var client *github.Client
+	apiURL := info.VCSAPIURL
+	if apiURL != "" {
+		if !strings.HasPrefix(apiURL, "https") {
+			apiURL = "https://" + apiURL
+		}
+		client, _ = github.NewEnterpriseClient(apiURL, apiURL, tc)
+	} else {
+		client = github.NewClient(tc)
+	}
+
+	return VCS{
+		Client: client,
+		Token:  info.VCSToken,
+		APIURL: apiURL,
+	}
+}
+
+// concatAllYamlFiles concat all yaml files from a directory as one big multi document yaml string
+func (v VCS) concatAllYamlFiles(ctx context.Context, objects []*github.RepositoryContent, runevent *info.Event) (string, error) {
+	var allTemplates string
+
+	for _, value := range objects {
+		if strings.HasSuffix(value.GetName(), ".yaml") ||
+			strings.HasSuffix(value.GetName(), ".yml") {
+			data, err := v.getObject(ctx, value.GetSHA(), runevent)
+			if err != nil {
+				return "", err
+			}
+			if allTemplates != "" && !strings.HasPrefix(string(data), "---") {
+				allTemplates += "---"
+			}
+			allTemplates += "\n" + string(data) + "\n"
+		}
+	}
+	return allTemplates, nil
+}
+
+// GetTektonDir Get all yaml files in tekton directory return as a single concated file
+func (v VCS) GetTektonDir(ctx context.Context, runevent *info.Event, path string) (string, error) {
+	fp, objects, resp, err := v.Client.Repositories.GetContents(ctx, runevent.Owner,
+		runevent.Repository, path, &github.RepositoryContentGetOptions{Ref: runevent.SHA})
+
+	if fp != nil {
+		return "", fmt.Errorf("the object %s is a file instead of a directory", path)
+	}
+	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
+		return "", nil
+	}
+
+	if err != nil {
+		return "", err
+	}
+
+	return v.concatAllYamlFiles(ctx, objects, runevent)
+}
+
+// getPullRequest get a pull request details
+func (v VCS) getPullRequest(ctx context.Context, runevent *info.Event, prNumber int) (*info.Event, error) {
+	pr, _, err := v.Client.PullRequests.Get(ctx, runevent.Owner, runevent.Repository, prNumber)
+	if err != nil {
+		return runevent, err
+	}
+	// Make sure to use the Base for Default BaseBranch or there would be a potential hijack
+	runevent.DefaultBranch = pr.GetBase().GetRepo().GetDefaultBranch()
+	runevent.URL = pr.GetBase().GetRepo().GetHTMLURL()
+	runevent.SHA = pr.GetHead().GetSHA()
+	runevent.SHAURL = fmt.Sprintf("%s/commit/%s", pr.GetHTMLURL(), pr.GetHead().GetSHA())
+	// TODO: Maybe if we wanted to allow rerequest from non approved user we
+	// would use the CheckRun Sender instead of the rerequest sender, could it
+	// be a room for abuse? 🤔
+	runevent.Sender = pr.GetUser().GetLogin()
+	runevent.HeadBranch = pr.GetHead().GetRef()
+	runevent.BaseBranch = pr.GetBase().GetRef()
+	runevent.EventType = "pull_request"
+	return runevent, nil
+}
+
+// populateCommitInfo get info on a commit in runevent
+func (v VCS) populateCommitInfo(ctx context.Context, runevent *info.Event) error {
+	commit, _, err := v.Client.Git.GetCommit(ctx, runevent.Owner, runevent.Repository, runevent.SHA)
+	if err != nil {
+		return err
+	}
+
+	runevent.SHAURL = commit.GetHTMLURL()
+	runevent.SHATitle = strings.Split(commit.GetMessage(), "\n\n")[0]
+
+	return nil
+}
+
+// GetFileInsideRepo Get a file via Github API using the runinfo information, we
+// branch is true, the user the branch as ref isntead of the SHA
+// TODO: merge GetFileInsideRepo amd GetTektonDir
+func (v VCS) GetFileInsideRepo(ctx context.Context, runevent *info.Event, path string, branch bool) (string, error) {
+	ref := runevent.SHA
+	if branch {
+		ref = runevent.BaseBranch
+	}
+
+	fp, objects, resp, err := v.Client.Repositories.GetContents(ctx, runevent.Owner,
+		runevent.Repository, path, &github.RepositoryContentGetOptions{Ref: ref})
+	if err != nil {
+		return "", err
+	}
+	if objects != nil {
+		return "", fmt.Errorf("referenced file inside the Github Repository %s is a directory", path)
+	}
+	if resp.Response.StatusCode == http.StatusNotFound {
+		return "", fmt.Errorf("cannot find %s in this repository", path)
+	}
+
+	getobj, err := v.getObject(ctx, fp.GetSHA(), runevent)
+	if err != nil {
+		return "", err
+	}
+
+	return string(getobj), nil
+}
+
+// getObject Get an object from a repository
+func (v VCS) getObject(ctx context.Context, sha string, runevent *info.Event) ([]byte, error) {
+	blob, _, err := v.Client.Git.GetBlob(ctx, runevent.Owner, runevent.Repository, sha)
+	if err != nil {
+		return nil, err
+	}
+
+	decoded, err := base64.StdEncoding.DecodeString(blob.GetContent())
+	if err != nil {
+		return nil, err
+	}
+	return decoded, err
+}
+
+func (v VCS) createCheckRun(ctx context.Context, status string, runevent *info.Event, pacopts info.PacOpts) (*github.CheckRun, error) {
+	now := github.Timestamp{Time: time.Now()}
+	checkrunoption := github.CreateCheckRunOptions{
+		Name:       pacopts.ApplicationName,
+		HeadSHA:    runevent.SHA,
+		Status:     github.String(status),
+		DetailsURL: github.String(pacopts.LogURL),
+		StartedAt:  &now,
+	}
+
+	checkRun, _, err := v.Client.Checks.CreateCheckRun(ctx, runevent.Owner, runevent.Repository, checkrunoption)
+	return checkRun, err
+}
+
+func (v VCS) CreateStatus(ctx context.Context, runevent *info.Event, pacopts info.PacOpts, status webvcs.StatusOpts) error {
+	checkrunid := runevent.CheckRunID
+
+	// TODO: get console info ASAP,
+	// Create initial checkrun if not exist
+	if checkrunid == nil {
+		createCheckRun, err := v.createCheckRun(ctx, "in_progress", runevent, pacopts)
+		if err != nil {
+			return err
+		}
+		checkrunid = createCheckRun.ID
+	}
+
+	now := github.Timestamp{Time: time.Now()}
+
+	var summary, title string
+
+	switch status.Conclusion {
+	case "success":
+		title = "✅ Success"
+		summary = fmt.Sprintf("%s has successfully validated your commit.", pacopts.ApplicationName)
+	case "failure":
+		title = "❌ Failed"
+		summary = fmt.Sprintf("%s has <b>failed</b>.", pacopts.ApplicationName)
+	case "skipped":
+		title = "➖ Skipped"
+		summary = fmt.Sprintf("%s is skipping this commit.", pacopts.ApplicationName)
+	case "neutral":
+		title = "❓ Unknown"
+		summary = fmt.Sprintf("%s doesn't know what happened with this commit.", pacopts.ApplicationName)
+	}
+
+	if status.Status == "in_progress" {
+		title = "CI has Started"
+		summary = fmt.Sprintf("%s is running.", pacopts.ApplicationName)
+	}
+
+	checkRunOutput := &github.CheckRunOutput{
+		Title:   &title,
+		Summary: &summary,
+		Text:    &status.Text,
+	}
+
+	opts := github.UpdateCheckRunOptions{
+		Name:   pacopts.ApplicationName,
+		Status: &status.Status,
+		Output: checkRunOutput,
+	}
+
+	if status.DetailsURL != "" {
+		opts.DetailsURL = &status.DetailsURL
+	}
+
+	// Only set completed-at if conclusion is set (which means finished)
+	if status.Conclusion != "" {
+		opts.CompletedAt = &now
+		opts.Conclusion = &status.Conclusion
+	}
+
+	_, _, err := v.Client.Checks.UpdateCheckRun(ctx, runevent.Owner, runevent.Repository, *checkrunid, opts)
+	return err
+}
diff --git a/pkg/webvcs/interface.go b/pkg/webvcs/interface.go
new file mode 100644
index 00000000..fe13daaa
--- /dev/null
+++ b/pkg/webvcs/interface.go
@@ -0,0 +1,23 @@
+package webvcs
+
+import (
+	"context"
+
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"go.uber.org/zap"
+)
+
+type StatusOpts struct {
+	Status     string
+	Conclusion string
+	Text       string
+	DetailsURL string
+}
+
+type Interface interface {
+	ParsePayload(context.Context, *zap.SugaredLogger, *info.Event, string) (*info.Event, error)
+	IsAllowed(context.Context, *info.Event) (bool, error)
+	CreateStatus(context.Context, *info.Event, info.PacOpts, StatusOpts) error
+	GetTektonDir(context.Context, *info.Event, string) (string, error)            // ctx, event, path
+	GetFileInsideRepo(context.Context, *info.Event, string, bool) (string, error) // ctx, event, path, branch
+}


Test patch:
diff --git a/cmd/pipelines-as-code/main_test.go b/cmd/pipelines-as-code/main_test.go
deleted file mode 100644
index d2cf7a0a..00000000
--- a/cmd/pipelines-as-code/main_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package main
-
-import (
-	"testing"
-
-	"gotest.tools/v3/assert"
-)
-
-func TestRouteBinary(t *testing.T) {
-	tests := []struct {
-		name  string
-		short string
-	}{
-		{
-			name:  "pipelines-as-code",
-			short: "Pipelines as code Run",
-		},
-		{
-			name:  "main",
-			short: "Pipelines as code Run",
-		},
-		{
-			name:  "tkn-pac",
-			short: "Pipelines as Code CLI",
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			assert.Equal(t, RouteBinary(tt.name).Short, tt.short)
-		})
-	}
-}
diff --git a/config/404-trigger-retest-comment.yaml b/config/404-trigger-retest-comment.yaml
index e5a9c988..a4ed6357 100644
--- a/config/404-trigger-retest-comment.yaml
+++ b/config/404-trigger-retest-comment.yaml
@@ -142,16 +142,22 @@ spec:
                     imagePullPolicy: Always
                     image: "ko://github.com/openshift-pipelines/pipelines-as-code/cmd/pipelines-as-code"
                     env:
-                    - name: PAC_APPLICATION_NAME
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: application-name
-                    - name: PAC_SECRET_AUTO_CREATE
-                      valueFrom:
-                        configMapKeyRef:
-                          name: pipelines-as-code
-                          key: secret-auto-create
+                      - name: PAC_APPLICATION_NAME
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: application-name
+                      - name: PAC_SECRET_AUTO_CREATE
+                        valueFrom:
+                          configMapKeyRef:
+                            name: pipelines-as-code
+                            key: secret-auto-create
+                      - name: PAC_WEBVCS_URL
+                        value: $(params.ghe_host)
+                      - name: PAC_WEBVCS_TOKEN
+                        value: $(params.token)
+                      - name: PAC_WEBVCS_TYPE
+                        value: "github"
                     script: |
                       cat << EOF|tee /tmp/payload.json
                       {
@@ -172,9 +178,10 @@ spec:
                         }
                       }
                       EOF
-                      pipelines-as-code --trigger-target=$(params.trigger_target) \
-                        --api-url="$(params.ghe_host)" \
-                        --payload-file=/tmp/payload.json --token="$(params.token)" --webhook-type="$(params.event_type)"
+                      env|grep '^PAC'|sed 's/TOKEN=.*/TOKEN=HIDDENTOKEN/'
+                      cat /tmp/payload.json
+                      pipelines-as-code --trigger-target=$(params.trigger_target) --webhook-type="$(params.event_type)" \
+                      --payload-file=/tmp/payload.json
               params:
                 - name: action
                   value: "$(params.action)"
diff --git a/pkg/cmd/pipelineascode/pipelineascode_test.go b/pkg/cmd/pipelineascode/pipelineascode_test.go
index 3a1f24ac..e685e5f9 100644
--- a/pkg/cmd/pipelineascode/pipelineascode_test.go
+++ b/pkg/cmd/pipelineascode/pipelineascode_test.go
@@ -1,244 +1,154 @@
 package pipelineascode
 
 import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"net/http"
 	"testing"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	pacpkg "github.com/openshift-pipelines/pipelines-as-code/pkg/pipelineascode"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
-	ghtesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/github"
 	kitesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/kubernetestint"
-	tparams "github.com/openshift-pipelines/pipelines-as-code/pkg/test/params"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	testwebvcs "github.com/openshift-pipelines/pipelines-as-code/pkg/test/webvcs"
 	"go.uber.org/zap"
 	zapobserver "go.uber.org/zap/zaptest/observer"
 	"gotest.tools/v3/assert"
-	"gotest.tools/v3/fs"
 	rtesting "knative.dev/pkg/reconciler/testing"
 )
 
-func TestCommandTokenSetProperly(t *testing.T) {
-	params := tparams.FakeParams{}
-	cmd := Command(params)
-	e := bytes.NewBufferString("")
-	o := bytes.NewBufferString("")
-	cmd.SetErr(e)
-	cmd.SetOut(o)
-	cmd.SetArgs([]string{"--trigger-target", "push"})
-	err := cmd.Execute()
-	assert.ErrorContains(t, err, "token option is not set properly")
-}
-
-func TestRunWrapPR(t *testing.T) {
+func TestRunByVCS(t *testing.T) {
 	ctx, _ := rtesting.SetupFakeContext(t)
-	fakeghclient, mux, _, teardown := ghtesthelper.SetupGH()
-	stdata, _ := testclient.SeedTestData(t, ctx, testclient.Data{})
+
 	observer, _ := zapobserver.New(zap.InfoLevel)
 	fakelogger := zap.New(observer).Sugar()
-	checkid := 1234
-	defer teardown()
-
-	mux.HandleFunc("/repos/chmouel/scratchmyback/check-runs", func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintf(w, `{"id": %d}`, checkid)
-	})
-	mux.HandleFunc("/repos/chmouel/scratchmyback/commits/ref", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc("/repos/chmouel/scratchmyback/git/commits/ref", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc(fmt.Sprintf("/repos/chmouel/scratchmyback/check-runs/%d", checkid), func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintf(w, `{"id": %d}`, checkid)
-	})
-	cs := &cli.Clients{
-		GithubClient: webvcs.GithubVCS{
-			Client: fakeghclient,
-		},
-		Log:            fakelogger,
-		PipelineAsCode: stdata.PipelineAsCode,
-	}
-	k8int := &kitesthelper.KinterfaceTest{
-		ConsoleURL: "https://console.url",
-	}
-
-	options := &pacpkg.Options{
-		RunInfo: webvcs.RunInfo{
-			EventType:     "pull_request",
-			TriggerTarget: "pull_request",
-		},
-	}
-	err := runWrap(ctx, options, cs, k8int)
-	assert.ErrorContains(t, err, "no payload")
-
-	options.PayloadFile = "testdata/pull_request.json"
-	err = runWrap(ctx, options, cs, k8int)
-	assert.NilError(t, err)
-}
-
-func TestGetInfo(t *testing.T) {
-	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-
-	defer teardown()
-	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprint(w, ``)
-	})
-	ctx, _ := rtesting.SetupFakeContext(t)
-	cs := &cli.Clients{
-		GithubClient: webvcs.GithubVCS{
-			Client: fakeclient,
-		},
-	}
-
-	b, err := ioutil.ReadFile("testdata/pull_request.json")
-	assert.NilError(t, err)
-	goodPayload := string(b)
-	missingValuesPayload := `
-	{
-  "pull_request": {
-	"head": {
-	  "sha": "sha"
-	}
-  },
-  "repository": {
-	"default_branch": "main",
-	"html_url": "https://github.com/openshift/tektoncd-pipeline",
-	"name": "tektoncd-pipeline",
-	"owner": {
-	  "login": "openshift"
-	}
-  }
-}
-	`
+	stdata, _ := testclient.SeedTestData(t, ctx, testclient.Data{})
 
-	testCases := []struct {
-		desc           string
-		runinfo        webvcs.RunInfo
-		payload        string
-		errmsg         string
-		branchShouldBe string
+	tests := []struct {
+		name                 string
+		wantErr              bool
+		event                *info.Event
+		payloadFile          string
+		consoleURLErroring   bool
+		createStatusErroring bool
+		twebvcs              testwebvcs.TestWebVCSImp
 	}{
 		{
-			desc:    "Error on bad payload",
-			runinfo: webvcs.RunInfo{EventType: "pull_request", TriggerTarget: "pull_request"},
-			payload: "foo bar",
-			errmsg:  "invalid character",
+			name:        "error on payload not here",
+			payloadFile: "/no/men/no/football",
+			wantErr:     true,
 		},
 		{
-			desc:    "No payload no runcheck",
-			runinfo: webvcs.RunInfo{},
-			payload: "",
-			errmsg:  "unknown X-Github-Event in message:",
+			name:        "no payload passed",
+			payloadFile: "",
+			wantErr:     true,
 		},
 		{
-			desc: "Bad runinfo with missing infos",
-			runinfo: webvcs.RunInfo{
-				Owner:     "foo",
-				EventType: "pull_request",
+			name: "run pull_request user not allowed",
+			event: &info.Event{
+				EventType:     "pull_request",
+				TriggerTarget: "pull_request",
+				BaseBranch:    "testbranch",
+				DefaultBranch: "main",
+				HeadBranch:    "main",
+				Owner:         "owner",
+				Repository:    "repo",
+				SHA:           "sha",
+				Sender:        "sender",
 			},
-			payload: "",
-			errmsg:  "unexpected end of JSON input",
+			twebvcs:     testwebvcs.TestWebVCSImp{AllowIT: false},
+			payloadFile: "testdata/pull_request.json",
 		},
 		{
-			desc:    "Missing values payload",
-			runinfo: webvcs.RunInfo{EventType: "pull_request", TriggerTarget: "pull_request"},
-			payload: missingValuesPayload,
-			errmsg:  "missing some values",
+			name: "no console URL set, just a warning",
+			event: &info.Event{
+				EventType:     "pull_request",
+				TriggerTarget: "pull_request",
+				BaseBranch:    "testbranch",
+				DefaultBranch: "main",
+				HeadBranch:    "main",
+				Owner:         "owner",
+				Repository:    "repo",
+				SHA:           "sha",
+				Sender:        "sender",
+			},
+			twebvcs:            testwebvcs.TestWebVCSImp{AllowIT: false},
+			payloadFile:        "testdata/pull_request.json",
+			consoleURLErroring: true,
 		},
 		{
-			desc:           "Good payload",
-			runinfo:        webvcs.RunInfo{EventType: "pull_request", TriggerTarget: "pull_request"},
-			payload:        goodPayload,
-			errmsg:         "",
-			branchShouldBe: "goodInfoBranch",
+			name: "create status error",
+			event: &info.Event{
+				EventType:     "pull_request",
+				TriggerTarget: "pull_request",
+				BaseBranch:    "testbranch",
+				DefaultBranch: "main",
+				HeadBranch:    "main",
+				Owner:         "owner",
+				Repository:    "repo",
+				SHA:           "sha",
+				Sender:        "sender",
+			},
+			twebvcs:     testwebvcs.TestWebVCSImp{AllowIT: false, CreateStatusErorring: true},
+			payloadFile: "testdata/pull_request.json",
+			wantErr:     true,
 		},
 	}
-	for _, tC := range testCases {
-		t.Run(tC.desc, func(t *testing.T) {
-			file := fs.NewFile(t, "test-payload", fs.WithContent(tC.payload))
-			defer file.Remove()
-
-			opts := &pacpkg.Options{
-				PayloadFile: file.Path(),
-				RunInfo:     tC.runinfo,
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			cs := &params.Run{
+				Clients: clients.Clients{
+					Log:            fakelogger,
+					PipelineAsCode: stdata.PipelineAsCode,
+				},
+				Info: info.Info{
+					Pac: info.PacOpts{
+						VCSType:     "github",
+						PayloadFile: test.payloadFile,
+					},
+				},
+			}
+			test.twebvcs.Event = test.event
+			kinteract := &kitesthelper.KinterfaceTest{
+				ConsoleURL:         "http://console",
+				ConsoleURLErorring: test.consoleURLErroring,
 			}
-			runinfo, err := parsePayload(ctx, cs, opts)
-			if tC.errmsg != "" {
-				assert.ErrorContains(t, err, tC.errmsg)
+			err := runWrap(ctx, cs, test.twebvcs, kinteract)
+			if test.wantErr {
+				assert.Assert(t, err != nil, "We want an error here")
 			} else {
 				assert.NilError(t, err)
-				assert.Equal(t, runinfo.BaseBranch, tC.branchShouldBe)
 			}
 		})
 	}
 }
 
-func TestRunWrap(t *testing.T) {
-	ctx, _ := rtesting.SetupFakeContext(t)
-	fakeghclient, mux, _, teardown := ghtesthelper.SetupGH()
-	stdata, _ := testclient.SeedTestData(t, ctx, testclient.Data{})
-	observer, _ := zapobserver.New(zap.InfoLevel)
-	fakelogger := zap.New(observer).Sugar()
-	checkid := 1234
-	mux.HandleFunc("/repos/chmouel/scratchmyback/check-runs", func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintf(w, `{"id": %d}`, checkid)
-	})
-	mux.HandleFunc(fmt.Sprintf("/repos/chmouel/scratchmyback/check-runs/%d", checkid), func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintf(w, `{"id": %d}`, checkid)
-	})
-	mux.HandleFunc("/repos/chmouel/scratchmyback/commits/ref", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc("/repos/chmouel/scratchmyback/git/commits/ref", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-
-	kinteract := &kitesthelper.KinterfaceTest{
-		ConsoleURL: "https://console.url",
-	}
-
-	defer teardown()
-	cs := &cli.Clients{
-		GithubClient: webvcs.GithubVCS{
-			Client: fakeghclient,
-		},
-		Log:            fakelogger,
-		PipelineAsCode: stdata.PipelineAsCode,
-	}
-
+func TestGetPayloadFromFile(t *testing.T) {
 	tests := []struct {
-		name      string
-		opts      *pacpkg.Options
-		substrErr string
+		name    string
+		vcstype string
+		opts    info.PacOpts
+		want    string
+		wantErr bool
 	}{
 		{
-			name: "good",
-			opts: &pacpkg.Options{
-				RunInfo:     webvcs.RunInfo{EventType: "pull_request", TriggerTarget: "pull_request"},
-				PayloadFile: "testdata/pull_request.json",
-			},
+			name:    "Test Github",
+			vcstype: "github",
 		},
 		{
-			name:      "bad",
-			opts:      &pacpkg.Options{},
-			substrErr: "no payload",
-		},
-		{
-			name:      "file 404",
-			opts:      &pacpkg.Options{PayloadFile: "/nowhere"},
-			substrErr: "no such file or directory",
+			name:    "Not recognized",
+			vcstype: "notrecognized",
+			wantErr: true,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			err := runWrap(ctx, tt.opts, cs, kinteract)
-			if tt.substrErr != "" {
-				assert.ErrorContains(t, err, tt.substrErr)
-			} else {
-				assert.NilError(t, err)
+			opts := info.PacOpts{
+				VCSType: tt.vcstype,
+			}
+			ctx, _ := rtesting.SetupFakeContext(t)
+			_, err := getVCS(ctx, opts)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("getPayloadFromFile() error = %v, wantErr %v", err, tt.wantErr)
+				return
 			}
 		})
 	}
diff --git a/pkg/cmd/repository/create_test.go b/pkg/cmd/repository/create_test.go
index 2eac09fa..370e5557 100644
--- a/pkg/cmd/repository/create_test.go
+++ b/pkg/cmd/repository/create_test.go
@@ -4,15 +4,16 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/git"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/fs"
 	rtesting "knative.dev/pkg/reconciler/testing"
 )
 
-func Test_create(t *testing.T) {
+func TestCreate(t *testing.T) {
 	tests := []struct {
 		name            string
 		wantErr         bool
@@ -36,13 +37,15 @@ func Test_create(t *testing.T) {
 			ctx, _ := rtesting.SetupFakeContext(t)
 			tdata := testclient.Data{}
 			stdata, _ := testclient.SeedTestData(t, ctx, tdata)
-			cs := &cli.Clients{
-				PipelineAsCode: stdata.PipelineAsCode,
+			cs := &params.Run{
+				Clients: clients.Clients{
+					PipelineAsCode: stdata.PipelineAsCode,
+				},
 			}
 			io, out := newIOStream()
 			opts := CreateOptions{
 				AssumeYes: true,
-				Clients:   cs,
+				Run:       cs,
 				IOStreams: io,
 				CurrentNS: tt.targetNamespace,
 			}
diff --git a/pkg/cmd/repository/describe_test.go b/pkg/cmd/repository/describe_test.go
index df4d96e1..0c292f3a 100644
--- a/pkg/cmd/repository/describe_test.go
+++ b/pkg/cmd/repository/describe_test.go
@@ -11,9 +11,10 @@ import (
 	"github.com/google/go-github/v35/github"
 	"github.com/jonboulle/clockwork"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli/ui"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/ui"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
 	"gotest.tools/v3/golden"
 	corev1 "k8s.io/api/core/v1"
@@ -40,7 +41,7 @@ func TestDescribe(t *testing.T) {
 		currentNamespace string
 		repoName         string
 		statuses         []v1alpha1.RepositoryRunStatus
-		opts             *flags.CliOpts
+		opts             *params.PacCliOpts
 	}
 	tests := []struct {
 		name    string
@@ -52,7 +53,7 @@ func TestDescribe(t *testing.T) {
 			args: args{
 				repoName:         "test-run",
 				currentNamespace: "namespace",
-				opts:             &flags.CliOpts{},
+				opts:             &params.PacCliOpts{},
 				statuses: []v1alpha1.RepositoryRunStatus{
 					{
 						Status: v1beta1.Status{
@@ -78,7 +79,7 @@ func TestDescribe(t *testing.T) {
 			args: args{
 				repoName:         "test-run",
 				currentNamespace: "namespace",
-				opts: &flags.CliOpts{
+				opts: &params.PacCliOpts{
 					Namespace: "optnamespace",
 				},
 				statuses: []v1alpha1.RepositoryRunStatus{
@@ -104,7 +105,7 @@ func TestDescribe(t *testing.T) {
 		{
 			name: "Describe a Pipeline with a Multiple Run",
 			args: args{
-				opts:             &flags.CliOpts{},
+				opts:             &params.PacCliOpts{},
 				repoName:         "test-run",
 				currentNamespace: "namespace",
 				statuses: []v1alpha1.RepositoryRunStatus{
@@ -177,12 +178,16 @@ func TestDescribe(t *testing.T) {
 			}
 			ctx, _ := rtesting.SetupFakeContext(t)
 			stdata, _ := testclient.SeedTestData(t, ctx, tdata)
-			cs := &cli.Clients{
-				PipelineAsCode: stdata.PipelineAsCode,
+			cs := &params.Run{
+				Clients: clients.Clients{
+					PipelineAsCode: stdata.PipelineAsCode,
+				},
+				Info: info.Info{Kube: info.KubeOpts{Namespace: tt.args.currentNamespace}},
 			}
 
 			io, out := newIOStream()
-			if err := describe(ctx, cs, cw, tt.args.opts, io, tt.args.currentNamespace,
+			if err := describe(
+				ctx, cs, cw, tt.args.opts, io,
 				tt.args.repoName); (err != nil) != tt.wantErr {
 				t.Errorf("describe() error = %v, wantErr %v", err, tt.wantErr)
 			} else {
diff --git a/pkg/cmd/repository/list_test.go b/pkg/cmd/repository/list_test.go
index ceb0d0ee..87d79f3c 100644
--- a/pkg/cmd/repository/list_test.go
+++ b/pkg/cmd/repository/list_test.go
@@ -9,8 +9,9 @@ import (
 	"github.com/google/go-github/v35/github"
 	"github.com/jonboulle/clockwork"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/flags"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
 	"gotest.tools/v3/golden"
 	corev1 "k8s.io/api/core/v1"
@@ -93,7 +94,7 @@ func TestList(t *testing.T) {
 		namespaces       []*corev1.Namespace
 		repositories     []*v1alpha1.Repository
 		currentNamespace string
-		opts             *flags.CliOpts
+		opts             *params.PacCliOpts
 		selectors        string
 		noheaders        bool
 	}
@@ -105,7 +106,7 @@ func TestList(t *testing.T) {
 		{
 			name: "Test list repositories",
 			args: args{
-				opts:             &flags.CliOpts{},
+				opts:             &params.PacCliOpts{},
 				currentNamespace: namespace1.GetName(),
 				namespaces: []*corev1.Namespace{
 					namespace1,
@@ -116,7 +117,7 @@ func TestList(t *testing.T) {
 		{
 			name: "Test list repositories all namespaces",
 			args: args{
-				opts:             &flags.CliOpts{AllNameSpaces: true},
+				opts:             &params.PacCliOpts{AllNameSpaces: true},
 				currentNamespace: "namespace",
 				namespaces:       []*corev1.Namespace{namespace1, namespace2},
 				repositories:     []*v1alpha1.Repository{repoNamespace1, repoNamespace2},
@@ -125,7 +126,7 @@ func TestList(t *testing.T) {
 		{
 			name: "Test list repositories specific namespaces",
 			args: args{
-				opts:             &flags.CliOpts{},
+				opts:             &params.PacCliOpts{},
 				currentNamespace: namespace2.GetName(),
 				namespaces:       []*corev1.Namespace{namespace1, namespace2},
 				repositories:     []*v1alpha1.Repository{repoNamespace1, repoNamespace2},
@@ -140,13 +141,15 @@ func TestList(t *testing.T) {
 			}
 			ctx, _ := rtesting.SetupFakeContext(t)
 			stdata, _ := testclient.SeedTestData(t, ctx, tdata)
-			cs := &cli.Clients{
-				PipelineAsCode: stdata.PipelineAsCode,
+			cs := &params.Run{
+				Clients: clients.Clients{
+					PipelineAsCode: stdata.PipelineAsCode,
+				},
+				Info: info.Info{Kube: info.KubeOpts{Namespace: tt.args.currentNamespace}},
 			}
 			io, out := newIOStream()
 			if err := list(ctx, cs, tt.args.opts, io,
-				cw, tt.args.currentNamespace,
-				tt.args.selectors, tt.args.noheaders); (err != nil) != tt.wantErr {
+				cw, tt.args.selectors, tt.args.noheaders); (err != nil) != tt.wantErr {
 				t.Errorf("describe() error = %v, wantErr %v", err, tt.wantErr)
 			} else {
 				golden.Assert(t, out.String(), strings.ReplaceAll(fmt.Sprintf("%s.golden", t.Name()), "/", "-"))
diff --git a/pkg/cmd/repository/root_test.go b/pkg/cmd/repository/root_test.go
index 972cb3d4..600f561f 100644
--- a/pkg/cmd/repository/root_test.go
+++ b/pkg/cmd/repository/root_test.go
@@ -10,11 +10,11 @@ import (
 	"github.com/google/go-github/v35/github"
 	"github.com/jonboulle/clockwork"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli/ui"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/ui"
 	tcli "github.com/openshift-pipelines/pipelines-as-code/pkg/test/cli"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/test/params"
 	"github.com/spf13/cobra"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/golden"
@@ -26,7 +26,7 @@ import (
 )
 
 func TestRoot(t *testing.T) {
-	s, err := tcli.ExecuteCommand(Root(&cli.PacParams{}), "help")
+	s, err := tcli.ExecuteCommand(Root(&params.Run{}), "help")
 	assert.NilError(t, err)
 	assert.Assert(t, strings.Contains(s, "repository, repo, repsitories"))
 }
@@ -34,7 +34,7 @@ func TestRoot(t *testing.T) {
 func TestCommands(t *testing.T) {
 	tests := []struct {
 		name    string
-		command func(p cli.Params, ioStreams *ui.IOStreams) *cobra.Command
+		command func(c *params.Run, ioStreams *ui.IOStreams) *cobra.Command
 		want    *cobra.Command
 	}{
 		{
@@ -97,14 +97,15 @@ func TestCommands(t *testing.T) {
 			}
 			ctx, _ := rtesting.SetupFakeContext(t)
 			stdata, _ := testclient.SeedTestData(t, ctx, tdata)
-			cs := &cli.Clients{
-				PipelineAsCode: stdata.PipelineAsCode,
+			cs := &params.Run{
+				Clients: clients.Clients{
+					ClientInitialized: true,
+					PipelineAsCode:    stdata.PipelineAsCode,
+				},
 			}
 			buf := new(bytes.Buffer)
 			ioStream := &ui.IOStreams{Out: buf, ErrOut: buf}
-			cmd := tt.command(params.FakeParams{
-				Fakeclients: cs,
-			}, ioStream)
+			cmd := tt.command(cs, ioStream)
 			cmd.SetOut(buf)
 			_, err := tcli.ExecuteCommand(cmd, "--no-color", "-n", nsName, repoName)
 			assert.NilError(t, err)
@@ -164,13 +165,13 @@ func TESSS(t *testing.T) {
 	}
 	ctx, _ := rtesting.SetupFakeContext(t)
 	stdata, _ := testclient.SeedTestData(t, ctx, tdata)
-	cs := &cli.Clients{
-		PipelineAsCode: stdata.PipelineAsCode,
+	cs := &params.Run{
+		Clients: clients.Clients{
+			PipelineAsCode: stdata.PipelineAsCode,
+		},
 	}
 	buf := new(bytes.Buffer)
-	cmd := ListCommand(params.FakeParams{
-		Fakeclients: cs,
-	}, &ui.IOStreams{Out: buf, ErrOut: buf})
+	cmd := ListCommand(cs, &ui.IOStreams{Out: buf, ErrOut: buf})
 	cmd.SetOut(buf)
 	_, err := tcli.ExecuteCommand(cmd, "-n", nsName, repoName)
 	assert.NilError(t, err)
diff --git a/pkg/cmd/resolve/resolve_test.go b/pkg/cmd/resolve/resolve_test.go
index fd7d8434..806fe168 100644
--- a/pkg/cmd/resolve/resolve_test.go
+++ b/pkg/cmd/resolve/resolve_test.go
@@ -6,8 +6,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	tparams "github.com/openshift-pipelines/pipelines-as-code/pkg/test/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
 	"go.uber.org/zap"
 	zapobserver "go.uber.org/zap/zaptest/observer"
 	"gotest.tools/v3/assert"
@@ -40,8 +40,8 @@ func TestSplitArgsInMap(t *testing.T) {
 }
 
 func TestCommandFilenameSetProperly(t *testing.T) {
-	params := tparams.FakeParams{}
-	cmd := Command(params)
+	cs := &params.Run{Clients: clients.Clients{ClientInitialized: true}}
+	cmd := Command(cs)
 	e := bytes.NewBufferString("")
 	o := bytes.NewBufferString("")
 	cmd.SetErr(e)
@@ -54,7 +54,7 @@ func TestCommandFilenameSetProperly(t *testing.T) {
 func TestResolveFilenames(t *testing.T) {
 	observer, _ := zapobserver.New(zap.InfoLevel)
 	fakelogger := zap.New(observer).Sugar()
-	cs := &cli.Clients{Log: fakelogger}
+	cs := &params.Run{Clients: clients.Clients{Log: fakelogger}}
 
 	tmplSimpleWithPrefix := fmt.Sprintf("---\n%s", tmplSimpleNoPrefix)
 
diff --git a/pkg/hub/get_test.go b/pkg/hub/get_test.go
index 61bb8acc..ed40d554 100644
--- a/pkg/hub/get_test.go
+++ b/pkg/hub/get_test.go
@@ -4,7 +4,8 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
 	httptesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/http"
 	rtesting "knative.dev/pkg/reconciler/testing"
 )
@@ -54,8 +55,10 @@ func TestGetTask(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			httpTestClient := httptesthelper.MakeHTTPTestClient(t, tt.config)
 			ctx, _ := rtesting.SetupFakeContext(t)
-			cs := &cli.Clients{
-				HTTPClient: *httpTestClient,
+			cs := &params.Run{
+				Clients: clients.Clients{
+					HTTP: *httpTestClient,
+				},
 			}
 			got, err := GetTask(ctx, cs, tt.task)
 			if (err != nil) != tt.wantErr {
diff --git a/pkg/kubeinteraction/secrets_test.go b/pkg/kubeinteraction/secrets_test.go
index 89927808..1699084c 100644
--- a/pkg/kubeinteraction/secrets_test.go
+++ b/pkg/kubeinteraction/secrets_test.go
@@ -3,9 +3,10 @@ package kubeinteraction
 import (
 	"testing"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	"go.uber.org/zap"
 	zapobserver "go.uber.org/zap/zaptest/observer"
 	"gotest.tools/v3/assert"
@@ -17,7 +18,6 @@ import (
 func TestCreateBasicAuthSecret(t *testing.T) {
 	nsNotThere := "not_there"
 	nsthere := "there"
-	token := "verysecrete"
 
 	ctx, _ := rtesting.SetupFakeContext(t)
 	tdata := testclient.Data{
@@ -55,13 +55,14 @@ func TestCreateBasicAuthSecret(t *testing.T) {
 	observer, _ := zapobserver.New(zap.InfoLevel)
 	fakelogger := zap.New(observer).Sugar()
 	kint := Interaction{
-		Clients: &cli.Clients{
-			Kube:         stdata.Kube,
-			GithubClient: webvcs.GithubVCS{Token: token},
-			Log:          fakelogger,
+		Run: &params.Run{
+			Clients: clients.Clients{
+				Kube: stdata.Kube,
+				Log:  fakelogger,
+			},
 		},
 	}
-	runinfo := webvcs.RunInfo{
+	runevent := info.Event{
 		Owner:      "owner",
 		Repository: "repo",
 		URL:        "https://forge/owner/repo",
@@ -82,9 +83,9 @@ func TestCreateBasicAuthSecret(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			err := kint.CreateBasicAuthSecret(ctx, runinfo, tt.targetNS)
+			err := kint.CreateBasicAuthSecret(ctx, &runevent, info.PacOpts{VCSToken: "verysecrete"}, tt.targetNS)
 			assert.NilError(t, err)
-			slist, err := kint.Clients.Kube.CoreV1().Secrets(tt.targetNS).List(ctx, metav1.ListOptions{})
+			slist, err := kint.Run.Clients.Kube.CoreV1().Secrets(tt.targetNS).List(ctx, metav1.ListOptions{})
 			assert.NilError(t, err)
 			assert.Assert(t, len(slist.Items) > 0, "Secret has not been created")
 			assert.Equal(t, slist.Items[0].Name, "pac-git-basic-auth-owner-repo")
diff --git a/pkg/config/annotation_matcher_test.go b/pkg/matcher/annotation_matcher_test.go
similarity index 80%
rename from pkg/config/annotation_matcher_test.go
rename to pkg/matcher/annotation_matcher_test.go
index cf6e3495..f3d2c1e8 100644
--- a/pkg/config/annotation_matcher_test.go
+++ b/pkg/matcher/annotation_matcher_test.go
@@ -1,4 +1,4 @@
-package config
+package matcher
 
 import (
 	"fmt"
@@ -8,10 +8,11 @@ import (
 
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
 	testnewrepo "github.com/openshift-pipelines/pipelines-as-code/pkg/test/repository"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	tektonv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	"go.uber.org/zap"
 	zapobserver "go.uber.org/zap/zaptest/observer"
@@ -35,9 +36,9 @@ func TestMatchPipelinerunAnnotationAndRepositories(t *testing.T) {
 	}
 
 	type args struct {
-		pruns   []*tektonv1beta1.PipelineRun
-		runinfo *webvcs.RunInfo
-		data    testclient.Data
+		pruns    []*tektonv1beta1.PipelineRun
+		runevent info.Event
+		data     testclient.Data
 	}
 	tests := []struct {
 		name, wantPRName, wantRepoName, wantLog string
@@ -48,8 +49,8 @@ func TestMatchPipelinerunAnnotationAndRepositories(t *testing.T) {
 			name:       "match a repository with target NS",
 			wantPRName: pipelineTargetNSName,
 			args: args{
-				pruns:   []*tektonv1beta1.PipelineRun{pipelineTargetNS},
-				runinfo: &webvcs.RunInfo{URL: targetURL, EventType: "pull_request", BaseBranch: mainBranch},
+				pruns:    []*tektonv1beta1.PipelineRun{pipelineTargetNS},
+				runevent: info.Event{URL: targetURL, EventType: "pull_request", BaseBranch: mainBranch},
 				data: testclient.Data{
 					Repositories: []*v1alpha1.Repository{
 						testnewrepo.NewRepo("test-good", targetURL, mainBranch, targetNamespace, targetNamespace, "pull_request"),
@@ -62,8 +63,8 @@ func TestMatchPipelinerunAnnotationAndRepositories(t *testing.T) {
 			wantPRName:   pipelineTargetNSName,
 			wantRepoName: "test-good",
 			args: args{
-				pruns:   []*tektonv1beta1.PipelineRun{pipelineTargetNS},
-				runinfo: &webvcs.RunInfo{URL: targetURL, EventType: "pull_request", BaseBranch: mainBranch},
+				pruns:    []*tektonv1beta1.PipelineRun{pipelineTargetNS},
+				runevent: info.Event{URL: targetURL, EventType: "pull_request", BaseBranch: mainBranch},
 				data: testclient.Data{
 					Repositories: []*v1alpha1.Repository{
 						testnewrepo.NewRepo("test-other", targetURL, mainBranch, targetNamespace, targetNamespace, "pull_request"),
@@ -77,8 +78,8 @@ func TestMatchPipelinerunAnnotationAndRepositories(t *testing.T) {
 			wantErr: true,
 			wantLog: "could not find Repository CRD",
 			args: args{
-				pruns:   []*tektonv1beta1.PipelineRun{pipelineTargetNS},
-				runinfo: &webvcs.RunInfo{URL: targetURL, EventType: "pull_request", BaseBranch: mainBranch},
+				pruns:    []*tektonv1beta1.PipelineRun{pipelineTargetNS},
+				runevent: info.Event{URL: targetURL, EventType: "pull_request", BaseBranch: mainBranch},
 				data: testclient.Data{
 					Repositories: []*v1alpha1.Repository{
 						testnewrepo.NewRepo("test-good", targetURL, mainBranch, "otherNS", "otherNS", "pull_request"),
@@ -94,10 +95,15 @@ func TestMatchPipelinerunAnnotationAndRepositories(t *testing.T) {
 			cs, _ := testclient.SeedTestData(t, ctx, tt.args.data)
 			observer, log := zapobserver.New(zap.InfoLevel)
 			logger := zap.New(observer).Sugar()
-			client := &cli.Clients{PipelineAsCode: cs.PipelineAsCode, Log: logger}
+			client := &params.Run{
+				Clients: clients.Clients{PipelineAsCode: cs.PipelineAsCode, Log: logger},
+				Info: info.Info{
+					Event: &tt.args.runevent,
+				},
+			}
 			got, repo, _, err := MatchPipelinerunByAnnotation(ctx,
 				tt.args.pruns,
-				client, tt.args.runinfo)
+				client)
 
 			if tt.wantErr && err == nil {
 				t.Error("We should have get an error")
@@ -145,13 +151,10 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 
 	observer, log := zapobserver.New(zap.InfoLevel)
 	logger := zap.New(observer).Sugar()
-	cs := &cli.Clients{
-		Log: logger,
-	}
 
 	type args struct {
-		pruns   []*tektonv1beta1.PipelineRun
-		runinfo *webvcs.RunInfo
+		pruns    []*tektonv1beta1.PipelineRun
+		runevent info.Event
 	}
 	tests := []struct {
 		name       string
@@ -163,8 +166,8 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "good-match-with-only-one",
 			args: args{
-				pruns:   []*tektonv1beta1.PipelineRun{pipelineGood},
-				runinfo: &webvcs.RunInfo{EventType: "pull_request", BaseBranch: "main"},
+				pruns:    []*tektonv1beta1.PipelineRun{pipelineGood},
+				runevent: info.Event{EventType: "pull_request", BaseBranch: "main"},
 			},
 			wantErr:    false,
 			wantPrName: "pipeline-good",
@@ -172,8 +175,8 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "first-one-match-with-two-good-ones",
 			args: args{
-				pruns:   []*tektonv1beta1.PipelineRun{pipelineGood, pipelineOther},
-				runinfo: &webvcs.RunInfo{EventType: "pull_request", BaseBranch: "main"},
+				pruns:    []*tektonv1beta1.PipelineRun{pipelineGood, pipelineOther},
+				runevent: info.Event{EventType: "pull_request", BaseBranch: "main"},
 			},
 			wantErr:    false,
 			wantPrName: "pipeline-good",
@@ -181,16 +184,16 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "no-match-on-event",
 			args: args{
-				pruns:   []*tektonv1beta1.PipelineRun{pipelineGood, pipelineOther},
-				runinfo: &webvcs.RunInfo{EventType: "push", BaseBranch: "main"},
+				pruns:    []*tektonv1beta1.PipelineRun{pipelineGood, pipelineOther},
+				runevent: info.Event{EventType: "push", BaseBranch: "main"},
 			},
 			wantErr: true,
 		},
 		{
 			name: "no-match-on-target-branch",
 			args: args{
-				pruns:   []*tektonv1beta1.PipelineRun{pipelineGood, pipelineOther},
-				runinfo: &webvcs.RunInfo{EventType: "pull_request", BaseBranch: "other"},
+				pruns:    []*tektonv1beta1.PipelineRun{pipelineGood, pipelineOther},
+				runevent: info.Event{EventType: "pull_request", BaseBranch: "other"},
 			},
 			wantErr: true,
 		},
@@ -204,7 +207,7 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 						},
 					},
 				},
-				runinfo: &webvcs.RunInfo{EventType: "push", BaseBranch: "main"},
+				runevent: info.Event{EventType: "push", BaseBranch: "main"},
 			},
 			wantErr: true,
 			wantLog: "cannot match between event and pipelineRuns",
@@ -212,7 +215,7 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "bad-event-annotation",
 			args: args{
-				runinfo: &webvcs.RunInfo{EventType: "pull_request", BaseBranch: "main"},
+				runevent: info.Event{EventType: "pull_request", BaseBranch: "main"},
 				pruns: []*tektonv1beta1.PipelineRun{
 					{
 						ObjectMeta: metav1.ObjectMeta{
@@ -230,7 +233,7 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "bad-target-branch-annotation",
 			args: args{
-				runinfo: &webvcs.RunInfo{EventType: "pull_request", BaseBranch: "main"},
+				runevent: info.Event{EventType: "pull_request", BaseBranch: "main"},
 				pruns: []*tektonv1beta1.PipelineRun{
 					{
 						ObjectMeta: metav1.ObjectMeta{
@@ -248,7 +251,7 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "empty-annotation",
 			args: args{
-				runinfo: &webvcs.RunInfo{EventType: "pull_request", BaseBranch: "main"},
+				runevent: info.Event{EventType: "pull_request", BaseBranch: "main"},
 				pruns: []*tektonv1beta1.PipelineRun{
 					{
 						ObjectMeta: metav1.ObjectMeta{
@@ -266,7 +269,7 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "match-branch-matching",
 			args: args{
-				runinfo: &webvcs.RunInfo{EventType: "push", BaseBranch: "refs/heads/main"},
+				runevent: info.Event{EventType: "push", BaseBranch: "refs/heads/main"},
 				pruns: []*tektonv1beta1.PipelineRun{
 					{
 						ObjectMeta: metav1.ObjectMeta{
@@ -284,7 +287,7 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "base-does-not-compare",
 			args: args{
-				runinfo: &webvcs.RunInfo{EventType: "push", BaseBranch: "refs/heads/main/foobar"},
+				runevent: info.Event{EventType: "push", BaseBranch: "refs/heads/main/foobar"},
 				pruns: []*tektonv1beta1.PipelineRun{
 					{
 						ObjectMeta: metav1.ObjectMeta{
@@ -302,7 +305,7 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 		{
 			name: "branch-glob-matching",
 			args: args{
-				runinfo: &webvcs.RunInfo{EventType: "push", BaseBranch: "refs/heads/main"},
+				runevent: info.Event{EventType: "push", BaseBranch: "refs/heads/main"},
 				pruns: []*tektonv1beta1.PipelineRun{
 					{
 						ObjectMeta: metav1.ObjectMeta{
@@ -322,7 +325,15 @@ func TestMatchPipelinerunByAnnotation(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ctx, _ := rtesting.SetupFakeContext(t)
-			got, _, _, err := MatchPipelinerunByAnnotation(ctx, tt.args.pruns, cs, tt.args.runinfo)
+			cs := &params.Run{
+				Clients: clients.Clients{
+					Log: logger,
+				},
+				Info: info.Info{
+					Event: &tt.args.runevent,
+				},
+			}
+			got, _, _, err := MatchPipelinerunByAnnotation(ctx, tt.args.pruns, cs)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("MatchPipelinerunByAnnotation() error = %v, wantErr %v", err, tt.wantErr)
 				return
diff --git a/pkg/config/annotation_tasks_install_test.go b/pkg/matcher/annotation_tasks_install_test.go
similarity index 75%
rename from pkg/config/annotation_tasks_install_test.go
rename to pkg/matcher/annotation_tasks_install_test.go
index e3d2ec8f..cc6ba1d1 100644
--- a/pkg/config/annotation_tasks_install_test.go
+++ b/pkg/matcher/annotation_tasks_install_test.go
@@ -1,18 +1,16 @@
-package config
+package matcher
 
 import (
-	"encoding/base64"
-	"fmt"
 	"log"
-	"net/http"
 	"os"
 	"testing"
 
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	ghtesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/github"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	httptesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/http"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/test/webvcs"
 	tektonv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	"gotest.tools/v3/assert"
 	k8scheme "k8s.io/client-go/kubernetes/scheme"
@@ -41,36 +39,14 @@ spec:
       script: |
        echo hello`
 
-	fakeGHclient, mux, _, ghTeardown := ghtesthelper.SetupGH()
-	defer ghTeardown()
-
-	mux.HandleFunc("/repos/contents/be/healthy", func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprint(w, `{
-  "name": "healthy",
-  "path": "be/healthy",
-  "sha": "takepicture"}`)
-	})
-	mux.HandleFunc("/repos/git/blobs/takepicture", func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintf(w, `{
-  "name": "healthy",
-  "path": "be/healthy",
-  "sha": "takepicture",
-  "size": 68,
-  "content": "%s\n",
-  "encoding": "base64"}`,
-			base64.StdEncoding.EncodeToString([]byte(simpletask)))
-	})
-	mux.HandleFunc("/repos/contents/pas/la", func(w http.ResponseWriter, r *http.Request) {
-		w.WriteHeader(http.StatusNotFound)
-	})
-
 	tests := []struct {
-		name        string
-		runinfo     *webvcs.RunInfo
-		annotations map[string]string
-		wantErr     string
-		gotTaskName string
-		remoteURLS  map[string]map[string]string
+		name            string
+		runevent        info.Event
+		annotations     map[string]string
+		wantErr         string
+		gotTaskName     string
+		remoteURLS      map[string]map[string]string
+		filesInsideRepo map[string]string
 	}{
 		{
 			name: "test-annotations-error-remote-http-not-k8",
@@ -117,7 +93,9 @@ spec:
 				pipelinesascode.GroupName + "/task": "[be/healthy]",
 			},
 			gotTaskName: "task",
-			runinfo:     &webvcs.RunInfo{},
+			filesInsideRepo: map[string]string{
+				"be/healthy": simpletask,
+			},
 		},
 		{
 			name: "test-annotations-remote-http-skipping-notmatching",
@@ -145,8 +123,7 @@ spec:
 			annotations: map[string]string{
 				pipelinesascode.GroupName + "/task": "[pas/la]",
 			},
-			runinfo: &webvcs.RunInfo{},
-			wantErr: "404",
+			wantErr: "could not find",
 		},
 		{
 			name:        "test-get-from-hub-latest",
@@ -186,18 +163,21 @@ spec:
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			httpTestClient := httptesthelper.MakeHTTPTestClient(t, tt.remoteURLS)
-			cs := &cli.Clients{
-				HTTPClient: *httpTestClient,
-				GithubClient: webvcs.GithubVCS{
-					Client: fakeGHclient,
+			cs := &params.Run{
+				Clients: clients.Clients{
+					HTTP: *httpTestClient,
 				},
+				Info: info.Info{Event: &tt.runevent},
 			}
 			ctx, _ := rtesting.SetupFakeContext(t)
 			rt := RemoteTasks{
-				Clients: cs,
-				Runinfo: tt.runinfo,
+				Run: cs,
+			}
+
+			vcsint := webvcs.TestWebVCSImp{
+				FilesInsideRepo: tt.filesInsideRepo,
 			}
-			got, err := rt.GetTaskFromAnnotations(ctx, tt.annotations)
+			got, err := rt.GetTaskFromAnnotations(ctx, vcsint, tt.annotations)
 			if tt.wantErr != "" {
 				assert.ErrorContains(t, err, tt.wantErr, "We should have get an error with %v but we didn't", tt.wantErr)
 				return
diff --git a/pkg/config/repo_runinfo_matcher_test.go b/pkg/matcher/repo_runinfo_matcher_test.go
similarity index 79%
rename from pkg/config/repo_runinfo_matcher_test.go
rename to pkg/matcher/repo_runinfo_matcher_test.go
index 42a8e88e..35e68a1b 100644
--- a/pkg/config/repo_runinfo_matcher_test.go
+++ b/pkg/matcher/repo_runinfo_matcher_test.go
@@ -1,13 +1,14 @@
-package config
+package matcher
 
 import (
 	"testing"
 
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
 	testnewrepo "github.com/openshift-pipelines/pipelines-as-code/pkg/test/repository"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	"go.uber.org/zap"
 	zapobserver "go.uber.org/zap/zaptest/observer"
 	"gotest.tools/v3/assert"
@@ -22,8 +23,8 @@ const (
 
 func Test_getRepoByCR(t *testing.T) {
 	type args struct {
-		data    testclient.Data
-		runinfo *webvcs.RunInfo
+		data     testclient.Data
+		runevent info.Event
 	}
 	tests := []struct {
 		name         string
@@ -39,7 +40,7 @@ func Test_getRepoByCR(t *testing.T) {
 						testnewrepo.NewRepo("test-good", targetURL, mainBranch, targetNamespace, targetNamespace, "pull_request"),
 					},
 				},
-				runinfo: &webvcs.RunInfo{URL: targetURL, BaseBranch: mainBranch, EventType: "pull_request"},
+				runevent: info.Event{URL: targetURL, BaseBranch: mainBranch, EventType: "pull_request"},
 			},
 			wantTargetNS: targetNamespace,
 			wantErr:      false,
@@ -52,7 +53,7 @@ func Test_getRepoByCR(t *testing.T) {
 						testnewrepo.NewRepo("test-good", targetURL, mainBranch, "paslebonns", targetNamespace, "pull_request"),
 					},
 				},
-				runinfo: &webvcs.RunInfo{URL: targetURL, BaseBranch: mainBranch, EventType: "pull_request"},
+				runevent: info.Event{URL: targetURL, BaseBranch: mainBranch, EventType: "pull_request"},
 			},
 			wantTargetNS: "",
 			wantErr:      true,
@@ -65,7 +66,7 @@ func Test_getRepoByCR(t *testing.T) {
 						testnewrepo.NewRepo("test-good", targetURL, mainBranch, targetNamespace, targetNamespace, "pull_request"),
 					},
 				},
-				runinfo: &webvcs.RunInfo{URL: targetURL, BaseBranch: mainBranch, EventType: "push"},
+				runevent: info.Event{URL: targetURL, BaseBranch: mainBranch, EventType: "push"},
 			},
 			wantTargetNS: "",
 			wantErr:      false,
@@ -78,7 +79,7 @@ func Test_getRepoByCR(t *testing.T) {
 						testnewrepo.NewRepo("test-good", targetURL, mainBranch, targetNamespace, targetNamespace, "pull_request"),
 					},
 				},
-				runinfo: &webvcs.RunInfo{URL: targetURL, BaseBranch: "anotherBaseBranch", EventType: "pull_request"},
+				runevent: info.Event{URL: targetURL, BaseBranch: "anotherBaseBranch", EventType: "pull_request"},
 			},
 			wantTargetNS: "",
 			wantErr:      false,
@@ -92,7 +93,7 @@ func Test_getRepoByCR(t *testing.T) {
 							targetNamespace, targetNamespace, "pull_request"),
 					},
 				},
-				runinfo: &webvcs.RunInfo{URL: targetURL, BaseBranch: mainBranch, EventType: "pull_request"},
+				runevent: info.Event{URL: targetURL, BaseBranch: mainBranch, EventType: "pull_request"},
 			},
 			wantTargetNS: "",
 			wantErr:      false,
@@ -106,7 +107,7 @@ func Test_getRepoByCR(t *testing.T) {
 							targetNamespace, targetNamespace, "pull_request"),
 					},
 				},
-				runinfo: &webvcs.RunInfo{
+				runevent: info.Event{
 					URL: targetURL, BaseBranch: "refs/heads/mainBranch",
 					EventType: "pull_request",
 				},
@@ -123,7 +124,7 @@ func Test_getRepoByCR(t *testing.T) {
 							targetNamespace, targetNamespace, "pull_request"),
 					},
 				},
-				runinfo: &webvcs.RunInfo{
+				runevent: info.Event{
 					URL:        targetURL,
 					BaseBranch: "refs/tags/1.0",
 					EventType:  "pull_request",
@@ -139,8 +140,13 @@ func Test_getRepoByCR(t *testing.T) {
 			cs, _ := testclient.SeedTestData(t, ctx, tt.args.data)
 			observer, _ := zapobserver.New(zap.InfoLevel)
 			logger := zap.New(observer).Sugar()
-			client := &cli.Clients{PipelineAsCode: cs.PipelineAsCode, Log: logger}
-			got, err := GetRepoByCR(ctx, client, "", tt.args.runinfo)
+			client := &params.Run{
+				Clients: clients.Clients{PipelineAsCode: cs.PipelineAsCode, Log: logger},
+				Info: info.Info{
+					Event: &tt.args.runevent,
+				},
+			}
+			got, err := GetRepoByCR(ctx, client, "")
 			if err == nil && tt.wantErr {
 				assert.NilError(t, err, "GetRepoByCR() error = %v, wantErr %v", err, tt.wantErr)
 			}
diff --git a/pkg/pipelineascode/pipelineascode_test.go b/pkg/pipelineascode/pipelineascode_test.go
index 4dead511..857dbaaf 100644
--- a/pkg/pipelineascode/pipelineascode_test.go
+++ b/pkg/pipelineascode/pipelineascode_test.go
@@ -11,16 +11,18 @@ import (
 	"strings"
 	"testing"
 
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	testDynamic "github.com/openshift-pipelines/pipelines-as-code/pkg/test/dynamic"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/test/repository"
 
 	"github.com/google/go-github/v35/github"
 	"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
 	ghtesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/github"
 	kitesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/kubernetestint"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	githubintf "github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs/github"
 	"go.uber.org/zap"
 	zapobserver "go.uber.org/zap/zaptest/observer"
 	"gotest.tools/v3/assert"
@@ -35,7 +37,7 @@ func replyString(mux *http.ServeMux, url, body string) {
 	})
 }
 
-func testSetupTektonDir(mux *http.ServeMux, runinfo *webvcs.RunInfo, directory string) {
+func testSetupTektonDir(mux *http.ServeMux, runevent info.Event, directory string) {
 	var tektonDirContent string
 	_ = filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
 		basename := filepath.Base(path)
@@ -50,7 +52,7 @@ func testSetupTektonDir(mux *http.ServeMux, runinfo *webvcs.RunInfo, directory s
 
 		contentB, _ := ioutil.ReadFile(path)
 		replyString(mux,
-			fmt.Sprintf("/repos/%s/%s/git/blobs/shaof%s", runinfo.Owner, runinfo.Repository, trimmed),
+			fmt.Sprintf("/repos/%s/%s/git/blobs/shaof%s", runevent.Owner, runevent.Repository, trimmed),
 			fmt.Sprintf(`{"encoding": "base64","content": "%s"}`,
 				base64.StdEncoding.EncodeToString(contentB)))
 
@@ -58,28 +60,28 @@ func testSetupTektonDir(mux *http.ServeMux, runinfo *webvcs.RunInfo, directory s
 	})
 
 	replyString(mux,
-		fmt.Sprintf("/repos/%s/%s/contents/.tekton", runinfo.Owner, runinfo.Repository),
+		fmt.Sprintf("/repos/%s/%s/contents/.tekton", runevent.Owner, runevent.Repository),
 		fmt.Sprintf("[%s]", strings.TrimSuffix(tektonDirContent, ",")))
 }
 
-func testSetupCommonGhReplies(t *testing.T, mux *http.ServeMux, runinfo *webvcs.RunInfo, finalStatus, finalStatusText string,
+func testSetupCommonGhReplies(t *testing.T, mux *http.ServeMux, runevent info.Event, finalStatus, finalStatusText string,
 	noReplyOrgPublicMembers bool) {
 	// Take a directory and generate replies as Github for it
 	replyString(mux,
-		fmt.Sprintf("/repos/%s/%s/contents/internal/task", runinfo.Owner, runinfo.Repository),
+		fmt.Sprintf("/repos/%s/%s/contents/internal/task", runevent.Owner, runevent.Repository),
 		`{"sha": "internaltasksha"}`)
 
 	if !noReplyOrgPublicMembers {
-		mux.HandleFunc("/orgs/"+runinfo.Owner+"/public_members", func(rw http.ResponseWriter, r *http.Request) {
-			fmt.Fprintf(rw, `[{"login": "%s"}]`, runinfo.Sender)
+		mux.HandleFunc("/orgs/"+runevent.Owner+"/public_members", func(rw http.ResponseWriter, r *http.Request) {
+			fmt.Fprintf(rw, `[{"login": "%s"}]`, runevent.Sender)
 		})
 	}
 
 	replyString(mux,
-		fmt.Sprintf("/repos/%s/%s/check-runs", runinfo.Owner, runinfo.Repository),
+		fmt.Sprintf("/repos/%s/%s/check-runs", runevent.Owner, runevent.Repository),
 		`{"id": 26}`)
 
-	mux.HandleFunc(fmt.Sprintf("/repos/%s/%s/check-runs/26", runinfo.Owner, runinfo.Repository),
+	mux.HandleFunc(fmt.Sprintf("/repos/%s/%s/check-runs/26", runevent.Owner, runevent.Repository),
 		func(w http.ResponseWriter, r *http.Request) {
 			body, _ := ioutil.ReadAll(r.Body)
 			created := github.CreateCheckRunOptions{}
@@ -99,7 +101,7 @@ func TestRun(t *testing.T) {
 	logger := zap.New(observer).Sugar()
 	tests := []struct {
 		name                         string
-		runinfo                      *webvcs.RunInfo
+		runevent                     info.Event
 		tektondir                    string
 		wantErr                      string
 		finalStatus                  string
@@ -110,16 +112,15 @@ func TestRun(t *testing.T) {
 	}{
 		{
 			name: "pull request",
-			runinfo: &webvcs.RunInfo{
-				SHA:                "principale",
-				Owner:              "organizationes",
-				Repository:         "lagaffe",
-				URL:                "https://service/documentation",
-				HeadBranch:         "press",
-				BaseBranch:         "main",
-				Sender:             "fantasio",
-				EventType:          "pull_request",
-				SecretAutoCreation: true,
+			runevent: info.Event{
+				SHA:        "principale",
+				Owner:      "organizationes",
+				Repository: "lagaffe",
+				URL:        "https://service/documentation",
+				HeadBranch: "press",
+				BaseBranch: "main",
+				Sender:     "fantasio",
+				EventType:  "pull_request",
 			},
 			tektondir:    "testdata/pull_request",
 			finalStatus:  "neutral",
@@ -128,7 +129,7 @@ func TestRun(t *testing.T) {
 
 		{
 			name: "No match",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -144,7 +145,7 @@ func TestRun(t *testing.T) {
 		},
 		{
 			name: "Push/branch",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -159,7 +160,7 @@ func TestRun(t *testing.T) {
 		},
 		{
 			name: "Push/tags",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -176,7 +177,7 @@ func TestRun(t *testing.T) {
 		// Skipped
 		{
 			name: "Skipped/Test no tekton dir",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -193,7 +194,7 @@ func TestRun(t *testing.T) {
 		// Skipped
 		{
 			name: "Skipped/Test on check_run",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:           "principale",
 				Owner:         "organizationes",
 				Repository:    "lagaffe",
@@ -210,7 +211,7 @@ func TestRun(t *testing.T) {
 		},
 		{
 			name: "Skipped/Test no repositories match on different event_type",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -231,7 +232,7 @@ func TestRun(t *testing.T) {
 
 		{
 			name: "Skipped/Test no repositories match",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -252,7 +253,7 @@ func TestRun(t *testing.T) {
 
 		{
 			name: "Skipped/User is not allowed",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -269,7 +270,7 @@ func TestRun(t *testing.T) {
 		},
 		{
 			name: "Keep max number of pipelineruns",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				SHA:        "principale",
 				Owner:      "organizationes",
 				Repository: "lagaffe",
@@ -290,7 +291,7 @@ func TestRun(t *testing.T) {
 			ctx, _ := rtesting.SetupFakeContext(t)
 			if tt.repositories == nil {
 				tt.repositories = []*v1alpha1.Repository{
-					repository.NewRepo("test-run", tt.runinfo.URL, tt.runinfo.BaseBranch, "namespace", "namespace", tt.runinfo.EventType),
+					repository.NewRepo("test-run", tt.runevent.URL, tt.runevent.BaseBranch, "namespace", "namespace", tt.runevent.EventType),
 				}
 			}
 			tdata := testclient.Data{
@@ -306,30 +307,38 @@ func TestRun(t *testing.T) {
 
 			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
 			defer teardown()
-
-			testSetupCommonGhReplies(t, mux, tt.runinfo, tt.finalStatus, tt.finalLogText, tt.skipReplyingOrgPublicMembers)
+			testSetupCommonGhReplies(t, mux, tt.runevent, tt.finalStatus, tt.finalLogText, tt.skipReplyingOrgPublicMembers)
 			if tt.tektondir != "" {
-				testSetupTektonDir(mux, tt.runinfo, tt.tektondir)
+				testSetupTektonDir(mux, tt.runevent, tt.tektondir)
 			}
 
 			stdata, _ := testclient.SeedTestData(t, ctx, tdata)
 			tdc := testDynamic.Options{}
 			dc, _ := tdc.Client()
-			cs := &cli.Clients{
-				GithubClient: webvcs.GithubVCS{
-					Client: fakeclient,
+			cs := &params.Run{
+				Clients: clients.Clients{
+					PipelineAsCode: stdata.PipelineAsCode,
+					Log:            logger,
+					Kube:           stdata.Kube,
+					Tekton:         stdata.Pipeline,
+					Dynamic:        dc,
+				},
+				Info: info.Info{
+					Event: &tt.runevent,
+					Pac: info.PacOpts{
+						SecretAutoCreation: true,
+					},
 				},
-				PipelineAsCode: stdata.PipelineAsCode,
-				Log:            logger,
-				Kube:           stdata.Kube,
-				Tekton:         stdata.Pipeline,
-				Dynamic:        dc,
 			}
 			k8int := &kitesthelper.KinterfaceTest{
 				ConsoleURL:               "https://console.url",
 				ExpectedNumberofCleanups: tt.expectedNumberofCleanups,
 			}
-			err := Run(ctx, cs, k8int, tt.runinfo)
+
+			vcsintf := githubintf.VCS{
+				Client: fakeclient,
+			}
+			err := Run(ctx, cs, vcsintf, k8int)
 
 			if tt.wantErr != "" {
 				assert.ErrorContains(t, err, tt.wantErr)
diff --git a/pkg/resolve/resolve_test.go b/pkg/resolve/resolve_test.go
index 16a5f017..811a9ff8 100644
--- a/pkg/resolve/resolve_test.go
+++ b/pkg/resolve/resolve_test.go
@@ -7,8 +7,10 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	testwebvcs "github.com/openshift-pipelines/pipelines-as-code/pkg/test/webvcs"
 	tektonv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	"go.uber.org/zap"
 	zapobserver "go.uber.org/zap/zaptest/observer"
@@ -39,15 +41,18 @@ func readTDfile(t *testing.T, testname string, generateName bool) (*tektonv1beta
 	}
 	observer, log := zapobserver.New(zap.InfoLevel)
 	logger := zap.New(observer).Sugar()
-	cs := &cli.Clients{
-		Log: logger,
+	cs := &params.Run{
+		Clients: clients.Clients{
+			Log: logger,
+		},
+		Info: info.Info{},
 	}
-	runinfo := &webvcs.RunInfo{}
 	ropt := &Opts{
 		GenerateName: generateName,
 		RemoteTasks:  true,
 	}
-	resolved, err := Resolve(ctx, cs, runinfo, string(data), ropt)
+	tvcs := testwebvcs.TestWebVCSImp{}
+	resolved, err := Resolve(ctx, cs, tvcs, string(data), ropt)
 	if err != nil {
 		return &tektonv1beta1.PipelineRun{}, nil, err
 	}
diff --git a/pkg/resolve/testdata/empty-spaces.yaml b/pkg/resolve/testdata/empty-spaces.yaml
index 0d42d767..ab57517b 100644
--- a/pkg/resolve/testdata/empty-spaces.yaml
+++ b/pkg/resolve/testdata/empty-spaces.yaml
@@ -20,76 +20,76 @@ spec:
     container registry.
 
   params:
-  - name: IMAGE
-    description: Reference of the image buildah will produce.
-    default: image-registry.openshift-image-registry.svc:5000/$(context.pipelineRun.namespace)/$(context.pipeline.name)
-  - name: BUILDER_IMAGE
-    description: The location of the buildah builder image.
-    default: quay.io/buildah/stable:v1.17.0
-  - name: STORAGE_DRIVER
-    description: Set buildah storage driver
-    default: vfs
-  - name: DOCKERFILE
-    description: Path to the Dockerfile to build.
-    default: ./Dockerfile
-  - name: CONTEXT
-    description: Path to the directory to use as context.
-    default: .
-  - name: TLSVERIFY
-    description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)
-    default: "true"
-  - name: FORMAT
-    description: The format of the built container, oci or docker
-    default: "oci"
-  - name: BUILD_EXTRA_ARGS
-    description: Extra parameters passed for the build command when building images.
-    default: ""
-  - name: PUSH_EXTRA_ARGS
-    description: Extra parameters passed for the push command when pushing images.
-    type: string
-    default: ""
+    - name: IMAGE
+      description: Reference of the image buildah will produce.
+      default: image-registry.openshift-image-registry.svc:5000/$(context.pipelineRun.namespace)/$(context.pipeline.name)
+    - name: BUILDER_IMAGE
+      description: The location of the buildah builder image.
+      default: quay.io/buildah/stable:v1.17.0
+    - name: STORAGE_DRIVER
+      description: Set buildah storage driver
+      default: vfs
+    - name: DOCKERFILE
+      description: Path to the Dockerfile to build.
+      default: ./Dockerfile
+    - name: CONTEXT
+      description: Path to the directory to use as context.
+      default: .
+    - name: TLSVERIFY
+      description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)
+      default: "true"
+    - name: FORMAT
+      description: The format of the built container, oci or docker
+      default: "oci"
+    - name: BUILD_EXTRA_ARGS
+      description: Extra parameters passed for the build command when building images.
+      default: ""
+    - name: PUSH_EXTRA_ARGS
+      description: Extra parameters passed for the push command when pushing images.
+      type: string
+      default: ""
   workspaces:
-  - name: source
-  - name: sslcertdir
-    optional: true
+    - name: source
+    - name: sslcertdir
+      optional: true
   results:
-  - name: IMAGE_DIGEST
-    description: Digest of the image just built.
+    - name: IMAGE_DIGEST
+      description: Digest of the image just built.
   steps:
-  - name: build
-    image: $(params.BUILDER_IMAGE)
-    workingDir: $(workspaces.source.path)
-    script: |
-      sleep 1000
-      [[ "$(workspaces.sslcertdir.bound)" == "true" ]] && CERT_DIR_FLAG="--cert-dir $(workspaces.sslcertdir.path)"
-      buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) bud \
-        $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) \
-        --tls-verify=$(params.TLSVERIFY) --no-cache \
-        -f $(params.DOCKERFILE) -t $(params.IMAGE) $(params.CONTEXT)
-    volumeMounts:
-    - name: varlibcontainers
-      mountPath: /var/lib/containers
+    - name: build
+      image: $(params.BUILDER_IMAGE)
+      workingDir: $(workspaces.source.path)
+      script: |
+        sleep 1000
+        [["$(workspaces.sslcertdir.bound)" == "true"]] && CERT_DIR_FLAG="--cert-dir $(workspaces.sslcertdir.path)"
+        buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) bud \
+          $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) \
+          --tls-verify=$(params.TLSVERIFY) --no-cache \
+          -f $(params.DOCKERFILE) -t $(params.IMAGE) $(params.CONTEXT)
+      volumeMounts:
+        - name: varlibcontainers
+          mountPath: /var/lib/containers
 
-  - name: push
-    image: $(params.BUILDER_IMAGE)
-    workingDir: $(workspaces.source.path)
-    script: |
-      [[ "$(workspaces.sslcertdir.bound)" == "true" ]] && CERT_DIR_FLAG="--cert-dir $(workspaces.sslcertdir.path)"
-      buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) push \
-        $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \
-        --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \
-        docker://$(params.IMAGE)
-    volumeMounts:
-    - name: varlibcontainers
-      mountPath: /var/lib/containers
+    - name: push
+      image: $(params.BUILDER_IMAGE)
+      workingDir: $(workspaces.source.path)
+      script: |
+        [["$(workspaces.sslcertdir.bound)" == "true"]] && CERT_DIR_FLAG="--cert-dir $(workspaces.sslcertdir.path)"
+        buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) push \
+          $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \
+          --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \
+          docker://$(params.IMAGE)
+      volumeMounts:
+        - name: varlibcontainers
+          mountPath: /var/lib/containers
 
-  - name: digest-to-results
-    image: $(params.BUILDER_IMAGE)
-    script: cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST
+    - name: digest-to-results
+      image: $(params.BUILDER_IMAGE)
+      script: cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST
 
   volumes:
-  - name: varlibcontainers
-    emptyDir: {}
+    - name: varlibcontainers
+      emptyDir: {}
 
 ---
 apiVersion: tekton.dev/v1beta1
@@ -184,7 +184,7 @@ spec:
         #!/bin/sh
         set -eu -o pipefail
 
-        if [[ "$(params.verbose)" == "true" ]] ; then
+        if [["$(params.verbose)" == "true"]] ; then
           set -x
         fi
 
@@ -195,7 +195,7 @@ spec:
           #
           # We don't just "rm -rf $CHECKOUT_DIR" because $CHECKOUT_DIR might be "/"
           # or the root of a mounted volume.
-          if [[ -d "$CHECKOUT_DIR" ]] ; then
+          if [[-d "$CHECKOUT_DIR"]] ; then
             # Delete non-hidden files and directories
             rm -rf "$CHECKOUT_DIR"/*
             # Delete files and directories starting with . but excluding ..
@@ -205,7 +205,7 @@ spec:
           fi
         }
 
-        if [[ "$(params.deleteExisting)" == "true" ]] ; then
+        if [["$(params.deleteExisting)" == "true"]] ; then
           cleandir
         fi
 
@@ -225,7 +225,7 @@ spec:
         cd "$CHECKOUT_DIR"
         RESULT_SHA="$(git rev-parse HEAD)"
         EXIT_CODE="$?"
-        if [ "$EXIT_CODE" != 0 ] ; then
+        if ["$EXIT_CODE" != 0] ; then
           exit $EXIT_CODE
         fi
         # ensure we don't add a trailing newline to the result
@@ -241,9 +241,9 @@ spec:
     # This is the pod template
     spec:
       containers:
-      - name: hello
-        image: busybox
-        command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
+        - name: hello
+          image: busybox
+          command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
       restartPolicy: OnFailure
 ---
 apiVersion: tekton.dev/v1beta1
@@ -255,7 +255,7 @@ spec:
     - name: repo_url
     - name: revision
   workspaces:
-  - name: source
+    - name: source
   tasks:
     - name: fetch
       taskRef:
@@ -266,8 +266,8 @@ spec:
         - name: revision
           value: $(params.revision)
       workspaces:
-      - name: output
-        workspace: source
+        - name: output
+          workspace: source
     - name: buildah
       taskRef:
         name: buildah
@@ -289,7 +289,7 @@ spec:
           - name: flags
           - name: version
         workspaces:
-        - name: source
+          - name: source
         steps:
           - name: lint
             # we get bumped out when usingh the official image with docker.io
@@ -326,11 +326,11 @@ spec:
     - name: revision
       value: simple
   workspaces:
-  - name: source
-    volumeClaimTemplate:
-      spec:
-        accessModes:
-          - ReadWriteOnce
-        resources:
-          requests:
-            storage: 1Gi
+    - name: source
+      volumeClaimTemplate:
+        spec:
+          accessModes:
+            - ReadWriteOnce
+          resources:
+            requests:
+              storage: 1Gi
diff --git a/pkg/test/kubernetestint/kubernetesint.go b/pkg/test/kubernetestint/kubernetesint.go
index dc3cd9f0..158b0674 100644
--- a/pkg/test/kubernetestint/kubernetesint.go
+++ b/pkg/test/kubernetestint/kubernetesint.go
@@ -6,22 +6,26 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
 	tektonv1beta1client "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/typed/pipeline/v1beta1"
 )
 
 type KinterfaceTest struct {
 	ConsoleURL               string
+	ConsoleURLErorring       bool
 	NamespaceError           bool
 	ExpectedNumberofCleanups int
 }
 
 func (k *KinterfaceTest) GetConsoleUI(ctx context.Context, ns string, pr string) (string, error) {
+	if k.ConsoleURLErorring {
+		return "", fmt.Errorf("i want you to errit")
+	}
 	return k.ConsoleURL, nil
 }
 
-func (k *KinterfaceTest) CreateBasicAuthSecret(ctx context.Context, runinfo webvcs.RunInfo, ns string) error {
+func (k *KinterfaceTest) CreateBasicAuthSecret(ctx context.Context, runevent *info.Event, pacopts info.PacOpts, targetNamespace string) error {
 	return nil
 }
 
diff --git a/pkg/test/params/params.go b/pkg/test/params/params.go
deleted file mode 100644
index 99e061bc..00000000
--- a/pkg/test/params/params.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package params
-
-import (
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"k8s.io/client-go/kubernetes"
-)
-
-type FakeParams struct {
-	Fakeclients *cli.Clients
-	ns          string
-}
-
-func (p FakeParams) GetNamespace() string {
-	return p.ns
-}
-
-// SetKubeConfigPath uses the kubeconfig path to instantiate tekton
-// returned by Clientset function
-func (p FakeParams) SetKubeConfigPath(string) {
-}
-
-// SetGitHubToken Set github token TODO: rename to a generic vcs
-func (p FakeParams) SetGitHubToken(string) {
-}
-
-// SetGitHubAPIURL Set github token TODO: rename to a generic vcs
-func (p FakeParams) SetGitHubAPIURL(string) {
-}
-
-func (p FakeParams) Clients() (*cli.Clients, error) {
-	return p.Fakeclients, nil
-}
-
-func (p FakeParams) KubeClient() (kubernetes.Interface, error) {
-	return nil, nil
-}
diff --git a/pkg/test/webvcs/testwebvcs.go b/pkg/test/webvcs/testwebvcs.go
new file mode 100644
index 00000000..63c25309
--- /dev/null
+++ b/pkg/test/webvcs/testwebvcs.go
@@ -0,0 +1,49 @@
+package webvcs
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"go.uber.org/zap"
+)
+
+type TestWebVCSImp struct {
+	AllowIT              bool
+	Event                *info.Event
+	TektonDirTemplate    string
+	CreateStatusErorring bool
+	FilesInsideRepo      map[string]string
+}
+
+func (v TestWebVCSImp) ParsePayload(ctx context.Context, logger *zap.SugaredLogger, event *info.Event,
+	s string) (*info.Event, error) {
+	return v.Event, nil
+}
+
+func (v TestWebVCSImp) IsAllowed(ctx context.Context, event *info.Event) (bool, error) {
+	if v.AllowIT {
+		return true, nil
+	}
+	return false, nil
+}
+
+func (v TestWebVCSImp) CreateStatus(ctx context.Context, event *info.Event, opts info.PacOpts,
+	opts2 webvcs.StatusOpts) error {
+	if v.CreateStatusErorring {
+		return fmt.Errorf("you want me to error I error for you")
+	}
+	return nil
+}
+
+func (v TestWebVCSImp) GetTektonDir(ctx context.Context, event *info.Event, s string) (string, error) {
+	return v.TektonDirTemplate, nil
+}
+
+func (v TestWebVCSImp) GetFileInsideRepo(ctx context.Context, event *info.Event, s string, b bool) (string, error) {
+	if val, ok := v.FilesInsideRepo[s]; ok {
+		return val, nil
+	}
+	return "", fmt.Errorf("could not find %s in tests", s)
+}
diff --git a/pkg/pipelineascode/acl_test.go b/pkg/webvcs/github/acl_test.go
similarity index 83%
rename from pkg/pipelineascode/acl_test.go
rename to pkg/webvcs/github/acl_test.go
index 5fc394a9..f4d11902 100644
--- a/pkg/pipelineascode/acl_test.go
+++ b/pkg/webvcs/github/acl_test.go
@@ -1,4 +1,4 @@
-package pipelineascode
+package github
 
 import (
 	"encoding/base64"
@@ -7,9 +7,8 @@ import (
 	"testing"
 
 	"github.com/google/go-github/v35/github"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	ghtesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/github"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
 	rtesting "knative.dev/pkg/reconciler/testing"
 )
 
@@ -17,14 +16,14 @@ func TestOkToTestComment(t *testing.T) {
 	tests := []struct {
 		name          string
 		commentsReply string
-		runinfo       *webvcs.RunInfo
+		runevent      info.Event
 		allowed       bool
 		wantErr       bool
 	}{
 		{
 			name:          "good",
 			commentsReply: `[{"body": "/ok-to-test", "user": {"login": "owner"}}]`,
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:     "owner",
 				Sender:    "nonowner",
 				EventType: "issue_comment",
@@ -35,7 +34,7 @@ func TestOkToTestComment(t *testing.T) {
 		{
 			name:          "no-ok-to-test",
 			commentsReply: `[{"body": "Foo Bar", "user": {"login": "owner"}}]`,
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:     "owner",
 				Sender:    "nonowner",
 				EventType: "issue_comment",
@@ -46,7 +45,7 @@ func TestOkToTestComment(t *testing.T) {
 		{
 			name:          "ok-to-test-not-from-owner",
 			commentsReply: `[{"body": "/ok-to-test", "user": {"login": "notowner"}}]`,
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:     "owner",
 				Sender:    "nonowner",
 				EventType: "issue_comment",
@@ -58,26 +57,25 @@ func TestOkToTestComment(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			repoOwnerURL := "http://url.com/owner/repo/1"
-			tt.runinfo.Event = &github.IssueCommentEvent{
+			tt.runevent.Event = &github.IssueCommentEvent{
 				Issue: &github.Issue{
 					PullRequestLinks: &github.PullRequestLinks{
 						HTMLURL: &repoOwnerURL,
 					},
 				},
 			}
-			tt.runinfo.TriggerTarget = "ok-to-test-comment"
+			tt.runevent.TriggerTarget = "ok-to-test-comment"
 			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
 			defer teardown()
 			mux.HandleFunc("/repos/owner/issues/1/comments", func(rw http.ResponseWriter, r *http.Request) {
 				fmt.Fprint(rw, tt.commentsReply)
 			})
 			ctx, _ := rtesting.SetupFakeContext(t)
-			cs := &cli.Clients{
-				GithubClient: webvcs.GithubVCS{
-					Client: fakeclient,
-				},
+			gvcs := VCS{
+				Client: fakeclient,
 			}
-			got, err := aclCheck(ctx, cs, tt.runinfo)
+
+			got, err := gvcs.IsAllowed(ctx, &tt.runevent)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("aclCheck() error = %v, wantErr %v", err, tt.wantErr)
 				return
@@ -124,19 +122,19 @@ func TestAclCheckAll(t *testing.T) {
 	})
 
 	ctx, _ := rtesting.SetupFakeContext(t)
-	gvcs := webvcs.GithubVCS{
+	gvcs := VCS{
 		Client: fakeclient,
 	}
 
 	tests := []struct {
-		name    string
-		runinfo *webvcs.RunInfo
-		allowed bool
-		wantErr bool
+		name     string
+		runevent info.Event
+		allowed  bool
+		wantErr  bool
 	}{
 		{
 			name: "sender allowed in org",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:  orgallowed,
 				Sender: "login_allowed",
 			},
@@ -145,7 +143,7 @@ func TestAclCheckAll(t *testing.T) {
 		},
 		{
 			name: "sender allowed from owner file",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:  repoOwnerFileAllowed,
 				Sender: "approved",
 			},
@@ -154,7 +152,7 @@ func TestAclCheckAll(t *testing.T) {
 		},
 		{
 			name: "owner is sender is allowed",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:  orgallowed,
 				Sender: "allowed",
 			},
@@ -163,7 +161,7 @@ func TestAclCheckAll(t *testing.T) {
 		},
 		{
 			name: "sender not allowed in org",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:  orgdenied,
 				Sender: "notallowed",
 			},
@@ -172,7 +170,7 @@ func TestAclCheckAll(t *testing.T) {
 		},
 		{
 			name: "err it",
-			runinfo: &webvcs.RunInfo{
+			runevent: info.Event{
 				Owner:  errit,
 				Sender: "error",
 			},
@@ -182,11 +180,7 @@ func TestAclCheckAll(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			cs := cli.Clients{
-				GithubClient: gvcs,
-			}
-
-			got, err := aclCheckAll(ctx, &cs, tt.runinfo)
+			got, err := gvcs.IsAllowed(ctx, &tt.runevent)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("aclCheckAll() error = %v, wantErr %v", err, tt.wantErr)
 				return
diff --git a/pkg/webvcs/github/events_test.go b/pkg/webvcs/github/events_test.go
new file mode 100644
index 00000000..3bacec9e
--- /dev/null
+++ b/pkg/webvcs/github/events_test.go
@@ -0,0 +1,273 @@
+package github
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+	"testing"
+
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	ghtesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/github"
+	"gotest.tools/v3/assert"
+	rtesting "knative.dev/pkg/reconciler/testing"
+)
+
+func TestPayLoadFix(t *testing.T) {
+	b, err := ioutil.ReadFile("testdata/pull_request_with_newlines.json")
+	assert.NilError(t, err)
+	ctx, _ := rtesting.SetupFakeContext(t)
+	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+	defer teardown()
+	mux.HandleFunc("/repos/repo/owner/commits/SHA", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	mux.HandleFunc("/repos/repo/owner/git/commits/SHA", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+
+	gvcs := VCS{
+		Client: fakeclient,
+	}
+
+	logger, _ := getLogger()
+	_, err = gvcs.ParsePayload(ctx, logger, &info.Event{
+		EventType:     "pull_request",
+		TriggerTarget: "pull_request",
+	}, string(b))
+
+	// would bomb out on "assertion failed: error is not nil: invalid character
+	// '\n' in string literal" if we don't fix the payload
+	assert.NilError(t, err)
+}
+
+func TestParsePayloadRerequestFromPullRequest(t *testing.T) {
+	checkrunSender := "jean-pierre"
+	prOwner := "owner"
+	repoName := "repo"
+	prNumber := "123"
+	sha := "ParsePayloadRerequestFromPullRequestSHA"
+	checkrunEvent := fmt.Sprintf(`{"action": "rerequested",
+	"sender": {"login": "%s"},
+	"check_run": {"check_suite": {"pull_requests": [{"number": %s}]}},
+	"repository": {"name": "%s", "owner": {"login": "%s"}}}`,
+		checkrunSender, prNumber, repoName, prOwner)
+	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+	defer teardown()
+	mux.HandleFunc("/repos/"+prOwner+"/"+repoName+"/pulls/"+prNumber, func(rw http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprintf(rw, `{"head": {"sha": "%s", "ref": "123"}, "user": {"login": "%s"}}`, sha, prOwner)
+	})
+	mux.HandleFunc("/repos/owner/repo/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	mux.HandleFunc("/repos/owner/repo/git/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gvcs := VCS{
+		Client: fakeclient,
+	}
+	logger, observer := getLogger()
+	r := &info.Event{
+		EventType:     "check_run",
+		TriggerTarget: "issue-recheck",
+	}
+	runinfo, err := gvcs.ParsePayload(ctx, logger, r, checkrunEvent)
+	assert.NilError(t, err)
+
+	assert.Equal(t, prOwner, runinfo.Owner)
+	assert.Equal(t, repoName, runinfo.Repository)
+	assert.Assert(t, checkrunSender != runinfo.Sender)
+	assert.Equal(t, runinfo.EventType, "pull_request")
+	assert.Assert(t, strings.Contains(observer.TakeAll()[0].Message, "Recheck of PR"))
+}
+
+func TestParsePayloadRerequestFromPush(t *testing.T) {
+	sender := "jean-pierre"
+	headBranch := "tartonpion"
+	headSHA := "TestParsePayloadRerequestFromPushSHA"
+	owner := "owner"
+	repository := "repo"
+	url := fmt.Sprintf("https://github.com/%s/%s", owner, repository)
+	checkrunEvent := fmt.Sprintf(`{
+  "action": "rerequested",
+  "check_run": {
+    "check_suite": {
+      "head_branch": "%s",
+      "head_sha": "%s",
+      "pull_requests": []
+    }
+  },
+  "repository": {
+    "default_branch": "main",
+    "html_url": "%s",
+    "name": "%s",
+    "owner": {
+      "login": "%s"
+    }
+  },
+  "sender": {
+    "login": "%s"
+  }
+}`,
+		headBranch, headSHA, url, repository, owner, sender)
+	ctx, _ := rtesting.SetupFakeContext(t)
+	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+	defer teardown()
+	gvcs := VCS{
+		Client: fakeclient,
+	}
+	mux.HandleFunc("/repos/owner/repo/commits/"+headSHA, func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	mux.HandleFunc("/repos/owner/repo/git/commits/"+headSHA, func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+
+	r := &info.Event{
+		EventType:     "check_run",
+		TriggerTarget: "issue-recheck",
+	}
+	logger, _ := getLogger()
+	runinfo, err := gvcs.ParsePayload(ctx, logger, r, checkrunEvent)
+	assert.NilError(t, err)
+
+	assert.Equal(t, runinfo.EventType, "push")
+	assert.Equal(t, runinfo.HeadBranch, headBranch)
+	assert.Equal(t, runinfo.Owner, owner)
+	assert.Equal(t, runinfo.Repository, repository)
+	assert.Equal(t, runinfo.URL, url)
+	assert.Assert(t, sender == runinfo.Sender) // TODO: should it be set to the push sender?
+}
+
+func TestParsePayLoadRetest(t *testing.T) {
+	issueSender := "tartanpion"
+	prOwner := "user1"
+	repoOwner := "openshift"
+	repoName := "pipelines"
+	prNumber := "123"
+	sha := "TestParsePayLoadRetestSHA"
+
+	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+	defer teardown()
+	mux.HandleFunc("/repos/"+prOwner+"/"+repoName+"/pulls/"+prNumber, func(rw http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprintf(rw, `{"head": {"sha": "%s", "ref": "123"}, "user": {"login": "%s"}}`, sha, prOwner)
+	})
+	mux.HandleFunc("/repos/user1/pipelines/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	mux.HandleFunc("/repos/user1/pipelines/git/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	issueEvent := fmt.Sprintf(`{
+  "sender": {
+	"login": "%s"
+  },
+  "repository": {
+	"name": "%s",
+	"owner": {
+	  "login": "%s"
+	}
+  },
+  "issue": {
+	"pull_request": {
+	  "html_url": "https://github.com/%s/%s/pull/%s"
+	}
+  }
+}`, issueSender, repoName, prOwner, repoName, repoOwner, prNumber)
+
+	ctx, _ := rtesting.SetupFakeContext(t)
+	logger, observer := getLogger()
+	gvcs := VCS{
+		Client: fakeclient,
+	}
+
+	// TODO
+	r := &info.Event{
+		EventType:     "issue_comment",
+		TriggerTarget: "issue_comment",
+	}
+	runinfo, err := gvcs.ParsePayload(ctx, logger, r, issueEvent)
+	assert.NilError(t, err)
+	assert.Equal(t, prOwner, runinfo.Owner)
+	// Make sure the PR owner is the runinfo.Owner and not the issueSender
+	assert.Assert(t, issueSender != runinfo.Owner)
+	firstObservedMessage := observer.TakeAll()[0].Message
+	assert.Assert(t, strings.Contains(firstObservedMessage, "recheck"))
+	assert.Equal(t, runinfo.EventType, "pull_request")
+}
+
+func TestParsePayload(t *testing.T) {
+	b, err := ioutil.ReadFile("testdata/pull_request.json")
+	assert.NilError(t, err)
+	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+	defer teardown()
+	mux.HandleFunc("/repos/chmouel/scratchpad/commits/cc8334de8e056317d18bd00c2588c3f7c95af294", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	mux.HandleFunc("/repos/chmouel/scratchpad/git/commits/cc8334de8e056317d18bd00c2588c3f7c95af294", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
+	})
+	gvcs := VCS{
+		Client: fakeclient,
+	}
+	ctx, _ := rtesting.SetupFakeContext(t)
+	logger, _ := getLogger()
+
+	r := &info.Event{
+		EventType:     "pull_request",
+		TriggerTarget: "pull_request",
+	}
+	runinfo, err := gvcs.ParsePayload(ctx, logger, r, string(b))
+	assert.NilError(t, err)
+	assert.Assert(t, runinfo.BaseBranch == "master")
+	assert.Assert(t, runinfo.Owner == "chmouel")
+	assert.Assert(t, runinfo.Repository == "scratchpad")
+	assert.Equal(t, runinfo.EventType, "pull_request")
+	assert.Assert(t, runinfo.URL == "https://github.com/chmouel/scratchpad")
+}
+
+func TestParsePayloadInvalid(t *testing.T) {
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gvcs := NewGithubVCS(ctx, info.PacOpts{
+		VCSToken:  "none",
+		VCSAPIURL: "nothing",
+	})
+	logger, _ := getLogger()
+	r := &info.Event{
+		EventType:     "pull_request",
+		TriggerTarget: "pull_request",
+	}
+	_, err := gvcs.ParsePayload(ctx, logger, r, "hello moto")
+	assert.ErrorContains(t, err, "invalid character")
+}
+
+func TestParsePayloadUnkownEvent(t *testing.T) {
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gvcs := NewGithubVCS(ctx, info.PacOpts{
+		VCSToken:  "none",
+		VCSAPIURL: "",
+	})
+	logger, _ := getLogger()
+	r := &info.Event{
+		EventType:     "foo",
+		TriggerTarget: "foo",
+	}
+	_, err := gvcs.ParsePayload(ctx, logger, r, "{\"hello\": \"moto\"}")
+	assert.ErrorContains(t, err, "unknown X-Github-Event")
+}
+
+func TestParsePayCannotParse(t *testing.T) {
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gvcs := NewGithubVCS(ctx, info.PacOpts{
+		VCSToken:  "none",
+		VCSAPIURL: "",
+	})
+	logger, _ := getLogger()
+	r := &info.Event{
+		EventType:     "gollum",
+		TriggerTarget: "gollum",
+	}
+	_, err := gvcs.ParsePayload(ctx, logger, r, "{}")
+	assert.Error(t, err, "this event is not supported")
+}
diff --git a/pkg/webvcs/github/github_test.go b/pkg/webvcs/github/github_test.go
new file mode 100644
index 00000000..7f9f12ab
--- /dev/null
+++ b/pkg/webvcs/github/github_test.go
@@ -0,0 +1,545 @@
+package github
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"path/filepath"
+	"strings"
+	"testing"
+
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	ghtesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/github"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	rtesting "knative.dev/pkg/reconciler/testing"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-github/v35/github"
+	"go.uber.org/zap"
+	zapobserver "go.uber.org/zap/zaptest/observer"
+	"gotest.tools/v3/assert"
+)
+
+func getLogger() (*zap.SugaredLogger, *zapobserver.ObservedLogs) {
+	observer, logobserver := zapobserver.New(zap.InfoLevel)
+	logger := zap.New(observer).Sugar()
+	return logger, logobserver
+}
+
+func setupFakesURLS() (client VCS, teardown func()) {
+	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+
+	mux.HandleFunc("/repos/check/info/check-runs", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"id": 555}`)
+	})
+
+	mux.HandleFunc("/repos/check/info/check-runs/2026", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{"id": 666}`)
+	})
+
+	mux.HandleFunc("/repos/foo/bar/contents/README.md", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{
+"name": "README.md",
+"sha": "readmemdsha",
+"type": "file"
+}`)
+	})
+
+	mux.HandleFunc("/repos/foo/bar/git/blobs/readmemdsha", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{
+"name": "README.md",
+"content": "aGVsbG8gbW90bwo=",
+"encoding": "base64"
+}`)
+	})
+
+	mux.HandleFunc("/repos/tekton/dir/git/blobs/pipelineyaml", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{
+"name": "README.md",
+"content": "aGVsbG8gcGlwZWxpbmV5YW1s",
+"encoding": "base64"
+}`)
+	})
+
+	mux.HandleFunc("/repos/tekton/dir/git/blobs/runyaml", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{
+"name": "README.md",
+"content": "aGVsbG8gcnVueWFtbA==",
+"encoding": "base64"
+}`)
+	})
+
+	mux.HandleFunc("/repos/tekton/dir/git/blobs/tektonyaml", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{
+"name": "README.md",
+"content": "aGVsbG8gdGVrdG9ueWFtbA==",
+"encoding": "base64"
+}`)
+	})
+
+	mux.HandleFunc("/repos/tekton/dir/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `[{
+
+				  "name": "pipeline.yaml",
+				  "path": ".tekton/pipeline.yaml",
+				  "sha": "pipelineyaml",
+				  "type": "file"
+				},
+				{
+				  "name": "run.yaml",
+				  "path": ".tekton/run.yaml",
+				  "sha": "runyaml",
+				  "type": "file"
+				}]`)
+	})
+	mux.HandleFunc("/repos/throw/error/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, "ERRROR")
+	})
+
+	mux.HandleFunc("/repos/its/afile/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
+		_, _ = fmt.Fprint(w, `{
+"name": ".tekton",
+"sha": "decfae2653959f7c6c25f21f026c3819bea41ecf",
+"type": "file",
+"content": "WyFbQ29udGFpbmVyIFJlcG9zaXRvcnkgb24gUXVheV0oaHR0cHM6Ly9xdWF5\nLmlvL3JlcG9zaXRvcnkvY2htb3VlbC90ZWt0b24tYXNhLWNvZGUvc3RhdHVz"}`)
+	})
+	mux.HandleFunc("/repos/pas/la/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusNotFound)
+	})
+
+	gcvs := VCS{
+		Client: fakeclient,
+	}
+	return gcvs, teardown
+}
+
+func TestGetFileInsideRepo(t *testing.T) {
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gcvs, teardown := setupFakesURLS()
+	defer teardown()
+	type args struct {
+		path      string
+		runevent  info.Event
+		assertion func(t *testing.T, got string, err error)
+	}
+
+	testGetTektonDir := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "testgood",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.NilError(t, err)
+				},
+				path: "README.md",
+				runevent: info.Event{
+					Owner:      "foo",
+					Repository: "bar",
+				},
+			},
+		},
+		{
+			name: "notfound",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.ErrorContains(t, err, "404")
+				},
+				path: ".tekton",
+				runevent: info.Event{
+					Owner:      "pas",
+					Repository: "la",
+				},
+			},
+		},
+		{
+			name: "file_should_be_a_dir",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.ErrorContains(t, err, "is a directory")
+				},
+				path: ".tekton",
+				runevent: info.Event{
+					Owner:      "tekton",
+					Repository: "dir",
+				},
+			},
+		},
+		{
+			name: "throwerror",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.ErrorContains(t, err, "invalid character")
+				},
+				path: ".tekton",
+				runevent: info.Event{
+					Owner:      "throw",
+					Repository: "error",
+				},
+			},
+		},
+	}
+	for _, tt := range testGetTektonDir {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := gcvs.GetFileInsideRepo(ctx, &tt.args.runevent, tt.args.path, false)
+			tt.args.assertion(t, got, err)
+		})
+	}
+}
+
+func TestGetTektonDir(t *testing.T) {
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gcvs, teardown := setupFakesURLS()
+	defer teardown()
+
+	type args struct {
+		path      string
+		runevent  info.Event
+		assertion func(t *testing.T, got string, err error)
+	}
+
+	testGetTektonDir := []struct {
+		name string
+		args args
+	}{
+		{
+			name: "testgood",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.NilError(t, err)
+					assert.Assert(t, got != "")
+				},
+				path: ".tekton",
+				runevent: info.Event{
+					Owner:      "tekton",
+					Repository: "dir",
+				},
+			},
+		},
+		{
+			name: "notfound",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.NilError(t, err)
+					assert.Assert(t, got == "")
+				},
+				path: ".tekton",
+				runevent: info.Event{
+					Owner:      "pas",
+					Repository: "la",
+				},
+			},
+		},
+		{
+			name: "tektondirisafile",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.Error(t, err, "the object .tekton is a file instead of a directory")
+					assert.Assert(t, got == "")
+				},
+				path: ".tekton",
+				runevent: info.Event{
+					Owner:      "its",
+					Repository: "afile",
+				},
+			},
+		},
+		{
+			name: "throwerror",
+			args: args{
+				assertion: func(t *testing.T, got string, err error) {
+					assert.ErrorContains(t, err, "invalid character")
+					assert.Assert(t, got == "")
+				},
+				path: ".tekton",
+				runevent: info.Event{
+					Owner:      "throw",
+					Repository: "error",
+				},
+			},
+		},
+	}
+	for _, tt := range testGetTektonDir {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := gcvs.GetTektonDir(ctx, &tt.args.runevent, tt.args.path)
+			tt.args.assertion(t, got, err)
+		})
+	}
+}
+
+func TestGetTektonDirTemplate(t *testing.T) {
+	const expected = `
+hello pipelineyaml
+---
+hello runyaml
+`
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gcvs, teardown := setupFakesURLS()
+	defer teardown()
+	runevent := &info.Event{
+		Owner:      "tekton",
+		Repository: "dir",
+	}
+
+	got, err := gcvs.GetTektonDir(ctx, runevent, ".tekton")
+	assert.NilError(t, err)
+	if d := cmp.Diff(got, expected); d != "" {
+		t.Fatalf("-got, +want: %v", d)
+	}
+}
+
+func TestGithubVCS_CreateCheckRun(t *testing.T) {
+	ctx, _ := rtesting.SetupFakeContext(t)
+	gcvs, teardown := setupFakesURLS()
+	defer teardown()
+	event := &info.Event{
+		Owner:      "check",
+		Repository: "info",
+	}
+	cr, err := gcvs.createCheckRun(ctx, "hello moto", event, info.PacOpts{LogURL: "http://nowhere"})
+	assert.NilError(t, err)
+	assert.Equal(t, cr.GetID(), int64(555))
+}
+
+func TestCheckSenderOrgMembership(t *testing.T) {
+	tests := []struct {
+		name      string
+		apiReturn string
+		allowed   bool
+		wantErr   bool
+		runevent  info.Event
+	}{
+		{
+			name: "Check Sender Org Membership",
+			runevent: info.Event{
+				Owner:  "organization",
+				Sender: "me",
+			},
+			apiReturn: `[{"login": "me"}]`,
+			allowed:   true,
+			wantErr:   false,
+		},
+		{
+			name: "Check Sender not in Org Membership",
+			runevent: info.Event{
+				Owner:  "organization",
+				Sender: "me",
+			},
+			apiReturn: `[{"login": "not"}]`,
+			allowed:   false,
+		},
+		{
+			name: "Not found on organization",
+			runevent: info.Event{
+				Owner:  "notfound",
+				Sender: "me",
+			},
+			allowed: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+			defer teardown()
+			ctx, _ := rtesting.SetupFakeContext(t)
+			gvcs := VCS{
+				Client: fakeclient,
+			}
+			mux.HandleFunc(fmt.Sprintf("/orgs/%s/public_members", tt.runevent.Owner), func(rw http.ResponseWriter, r *http.Request) {
+				fmt.Fprint(rw, tt.apiReturn)
+			})
+
+			allowed, err := gvcs.checkSenderOrgMembership(ctx, &tt.runevent)
+			if tt.wantErr && err == nil {
+				t.Error("We didn't get an error when we wanted one")
+			}
+			if !tt.wantErr && err != nil {
+				t.Errorf("We got an error when we didn't want it: %s", err)
+			}
+			assert.Equal(t, tt.allowed, allowed)
+		})
+	}
+}
+
+func TestGetStringPullRequestComment(t *testing.T) {
+	regexp := `(^|\n)/retest(\r\n|$)`
+	tests := []struct {
+		name, apiReturn string
+		wantErr         bool
+		runevent        info.Event
+		wantRet         bool
+	}{
+		{
+			name:      "Get String from comments",
+			runevent:  info.Event{URL: "http://1"},
+			apiReturn: `[{"body": "/retest"}]`,
+			wantRet:   true,
+		},
+		{
+			name:      "Not matching string in comments",
+			runevent:  info.Event{URL: "http://1"},
+			apiReturn: `[{"body": ""}]`,
+			wantRet:   false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+			defer teardown()
+			ctx, _ := rtesting.SetupFakeContext(t)
+			gvcs := VCS{
+				Client: fakeclient,
+			}
+			mux.HandleFunc(fmt.Sprintf("/repos/issues/%s/comments", filepath.Base(tt.runevent.URL)), func(rw http.ResponseWriter, r *http.Request) {
+				fmt.Fprint(rw, tt.apiReturn)
+			})
+
+			ret, err := gvcs.GetStringPullRequestComment(ctx, &tt.runevent, regexp)
+			if tt.wantErr && err == nil {
+				t.Error("We didn't get an error when we wanted one")
+			}
+			if !tt.wantErr && err != nil {
+				t.Errorf("We got an error when we didn't want it: %s", err)
+			}
+
+			if tt.wantRet {
+				assert.Assert(t, ret != nil)
+			}
+		})
+	}
+}
+
+func TestGithubVCS_CreateStatus(t *testing.T) {
+	checkrunid := int64(2026)
+	resultid := int64(666)
+	runEvent := info.Event{Owner: "check", Repository: "run", CheckRunID: &checkrunid}
+
+	type args struct {
+		runevent           info.Event
+		status             string
+		conclusion         string
+		text               string
+		detailsURL         string
+		titleSubstr        string
+		nilCompletedAtDate bool
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *github.CheckRun
+		wantErr bool
+	}{
+		{
+			name: "success",
+			args: args{
+				runevent:    runEvent,
+				status:      "completed",
+				conclusion:  "success",
+				text:        "Yay",
+				detailsURL:  "https://cireport.com",
+				titleSubstr: "Success",
+			},
+			want:    &github.CheckRun{ID: &resultid},
+			wantErr: false,
+		},
+		{
+			name: "in_progress",
+			args: args{
+				runevent:           runEvent,
+				status:             "in_progress",
+				conclusion:         "",
+				text:               "Yay",
+				detailsURL:         "https://cireport.com",
+				nilCompletedAtDate: true,
+			},
+			want:    &github.CheckRun{ID: &resultid},
+			wantErr: false,
+		},
+		{
+			name: "failure",
+			args: args{
+				runevent:    runEvent,
+				status:      "completed",
+				conclusion:  "failure",
+				text:        "Nay",
+				detailsURL:  "https://cireport.com",
+				titleSubstr: "Failed",
+			},
+			want:    &github.CheckRun{ID: &resultid},
+			wantErr: false,
+		},
+		{
+			name: "skipped",
+			args: args{
+				runevent:    runEvent,
+				status:      "completed",
+				conclusion:  "skipped",
+				text:        "Skipit",
+				detailsURL:  "https://cireport.com",
+				titleSubstr: "Skipped",
+			},
+			want:    &github.CheckRun{ID: &resultid},
+			wantErr: false,
+		},
+		{
+			name: "unknown",
+			args: args{
+				runevent:    runEvent,
+				status:      "completed",
+				conclusion:  "neutral",
+				text:        "Je sais pas ce qui se passe wesh",
+				detailsURL:  "https://cireport.com",
+				titleSubstr: "Unknown",
+			},
+			want:    &github.CheckRun{ID: &resultid},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
+			defer teardown()
+
+			ctx, _ := rtesting.SetupFakeContext(t)
+			gcvs := VCS{
+				Client: fakeclient,
+			}
+			mux.HandleFunc(fmt.Sprintf("/repos/check/run/check-runs/%d", checkrunid), func(rw http.ResponseWriter, r *http.Request) {
+				bit, _ := ioutil.ReadAll(r.Body)
+				checkRun := &github.CheckRun{}
+				err := json.Unmarshal(bit, checkRun)
+				assert.NilError(t, err)
+
+				if tt.args.nilCompletedAtDate {
+					// I guess that's the way you check for an undefined year,
+					// or maybe i don't understand fully how go works😅
+					assert.Assert(t, checkRun.GetCompletedAt().Year() == 0o001)
+				}
+				assert.Equal(t, checkRun.GetStatus(), tt.args.status)
+				assert.Equal(t, checkRun.GetConclusion(), tt.args.conclusion)
+				assert.Equal(t, checkRun.Output.GetText(), tt.args.text)
+				assert.Equal(t, checkRun.GetDetailsURL(), tt.args.detailsURL)
+				assert.Assert(t, strings.Contains(checkRun.Output.GetTitle(), tt.args.titleSubstr))
+				_, err = fmt.Fprintf(rw, `{"id": %d}`, resultid)
+				assert.NilError(t, err)
+			})
+
+			status := webvcs.StatusOpts{
+				Status:     tt.args.status,
+				Conclusion: tt.args.conclusion,
+				Text:       tt.args.text,
+				DetailsURL: tt.args.detailsURL,
+			}
+			pacopts := info.PacOpts{
+				LogURL: "https://log",
+			}
+			err := gcvs.CreateStatus(ctx, &tt.args.runevent, pacopts, status)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("GithubVCS.CreateStatus() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+		})
+	}
+}
diff --git a/pkg/webvcs/testdata/pull_request-scratch-my-back-1.json b/pkg/webvcs/github/testdata/pull_request-scratch-my-back-1.json
similarity index 99%
rename from pkg/webvcs/testdata/pull_request-scratch-my-back-1.json
rename to pkg/webvcs/github/testdata/pull_request-scratch-my-back-1.json
index 3f7230da..c8964f01 100644
--- a/pkg/webvcs/testdata/pull_request-scratch-my-back-1.json
+++ b/pkg/webvcs/github/testdata/pull_request-scratch-my-back-1.json
@@ -41,16 +41,12 @@
     "merge_commit_sha": "15cafa89d1cd13ea20fa771c0389924b7c3da724",
     "assignee": null,
     "assignees": [
-
     ],
     "requested_reviewers": [
-
     ],
     "requested_teams": [
-
     ],
     "labels": [
-
     ],
     "milestone": null,
     "draft": false,
diff --git a/pkg/webvcs/testdata/pull_request-scratch-my-back-failure.json b/pkg/webvcs/github/testdata/pull_request-scratch-my-back-failure.json
similarity index 99%
rename from pkg/webvcs/testdata/pull_request-scratch-my-back-failure.json
rename to pkg/webvcs/github/testdata/pull_request-scratch-my-back-failure.json
index ce5c1ab1..54ceb1cd 100644
--- a/pkg/webvcs/testdata/pull_request-scratch-my-back-failure.json
+++ b/pkg/webvcs/github/testdata/pull_request-scratch-my-back-failure.json
@@ -41,16 +41,12 @@
     "merge_commit_sha": "03ebbe73122dfa36fb3b25a9da3d93b81cdca650",
     "assignee": null,
     "assignees": [
-
     ],
     "requested_reviewers": [
-
     ],
     "requested_teams": [
-
     ],
     "labels": [
-
     ],
     "milestone": null,
     "draft": false,
diff --git a/pkg/webvcs/testdata/pull_request.json b/pkg/webvcs/github/testdata/pull_request.json
similarity index 100%
rename from pkg/webvcs/testdata/pull_request.json
rename to pkg/webvcs/github/testdata/pull_request.json
diff --git a/pkg/webvcs/testdata/pull_request_reopened.json b/pkg/webvcs/github/testdata/pull_request_reopened.json
similarity index 99%
rename from pkg/webvcs/testdata/pull_request_reopened.json
rename to pkg/webvcs/github/testdata/pull_request_reopened.json
index 2cff4052..118fb8e8 100644
--- a/pkg/webvcs/testdata/pull_request_reopened.json
+++ b/pkg/webvcs/github/testdata/pull_request_reopened.json
@@ -41,16 +41,12 @@
     "merge_commit_sha": "0c58ce5339052d980ee0baa38951db21f7200845",
     "assignee": null,
     "assignees": [
-
     ],
     "requested_reviewers": [
-
     ],
     "requested_teams": [
-
     ],
     "labels": [
-
     ],
     "milestone": null,
     "draft": false,
diff --git a/pkg/webvcs/github/testdata/pull_request_with_newlines.json b/pkg/webvcs/github/testdata/pull_request_with_newlines.json
new file mode 100644
index 00000000..760c8332
--- /dev/null
+++ b/pkg/webvcs/github/testdata/pull_request_with_newlines.json
@@ -0,0 +1,201 @@
+{
+  "action": "opened",
+  "installation": {
+    "id": 16557439,
+    "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTY1NTc0Mzk="
+  },
+  "number": 3,
+  "organization": {
+    "avatar_url": "https://avatars.githubusercontent.com/u/57996262?v=4",
+    "description": "",
+    "events_url": "https://api.github.com/orgs/repo/events",
+    "hooks_url": "https://api.github.com/orgs/repo/hooks",
+    "id": 57996262,
+    "issues_url": "https://api.github.com/orgs/repo/issues",
+    "login": "repo",
+    "members_url": "https://api.github.com/orgs/repo/members{/member}",
+    "node_id": "MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy",
+    "public_members_url": "https://api.github.com/orgs/repo/public_members{/member}",
+    "repos_url": "https://api.github.com/orgs/repo/repos",
+    "url": "https://api.github.com/orgs/repo"
+  },
+  "pull_request": {
+    "_links": {
+      "comments": {
+        "href": "https://api.github.com/repos/repo/owner/issues/3/comments"
+      },
+      "commits": {
+        "href": "https://api.github.com/repos/repo/owner/pulls/3/commits"
+      },
+      "html": {
+        "href": "https://github.com/repo/owner/pull/3"
+      },
+      "issue": {
+        "href": "https://api.github.com/repos/repo/owner/issues/3"
+      },
+      "review_comment": {
+        "href": "https://api.github.com/repos/repo/owner/pulls/comments{/number}"
+      },
+      "review_comments": {
+        "href": "https://api.github.com/repos/repo/owner/pulls/3/comments"
+      },
+      "self": {
+        "href": "https://api.github.com/repos/repo/owner/pulls/3"
+      },
+      "statuses": {
+        "href": "https://api.github.com/repos/repo/owner/statuses/SHA"
+      }
+    },
+    "active_lock_reason": null,
+    "additions": 38,
+    "assignee": null,
+    "assignees": [],
+    "author_association": "MEMBER",
+    "auto_merge": null,
+    "base": {
+      "label": "repo:main",
+      "ref": "main",
+      "repo": {
+        "allow_merge_commit": true,
+        "allow_rebase_merge": true,
+        "allow_squash_merge": true,
+        "archive_url": "https://api.github.com/repos/repo/owner/{archive_format}{/ref}",
+        "archived": false,
+        "assignees_url": "https://api.github.com/repos/repo/owner/assignees{/user}",
+        "blobs_url": "https://api.github.com/repos/repo/owner/git/blobs{/sha}",
+        "branches_url": "https://api.github.com/repos/repo/owner/branches{/branch}",
+        "clone_url": "https://github.com/repo/owner.git",
+        "collaborators_url": "https://api.github.com/repos/repo/owner/collaborators{/collaborator}",
+        "comments_url": "https://api.github.com/repos/repo/owner/comments{/number}",
+        "commits_url": "https://api.github.com/repos/repo/owner/commits{/sha}",
+        "compare_url": "https://api.github.com/repos/repo/owner/compare/{base}...{head}",
+        "contents_url": "https://api.github.com/repos/repo/owner/contents/{+path}",
+        "contributors_url": "https://api.github.com/repos/repo/owner/contributors",
+        "created_at": "2021-04-06T13:26:01Z",
+        "default_branch": "main",
+        "delete_branch_on_merge": false,
+        "deployments_url": "https://api.github.com/repos/repo/owner/deployments",
+        "description": "Pipelines as Code",
+        "disabled": false,
+        "downloads_url": "https://api.github.com/repos/repo/owner/downloads",
+        "events_url": "https://api.github.com/repos/repo/owner/events",
+        "fork": false,
+        "forks": 3,
+        "forks_count": 3,
+        "forks_url": "https://api.github.com/repos/repo/owner/forks",
+        "full_name": "repo/owner",
+        "git_commits_url": "https://api.github.com/repos/repo/owner/git/commits{/sha}",
+        "git_refs_url": "https://api.github.com/repos/repo/owner/git/refs{/sha}",
+        "git_tags_url": "https://api.github.com/repos/repo/owner/git/tags{/sha}",
+        "git_url": "git://github.com/repo/owner.git",
+        "has_downloads": true,
+        "has_issues": true,
+        "has_pages": false,
+        "has_projects": true,
+        "has_wiki": true,
+        "homepage": null,
+        "hooks_url": "https://api.github.com/repos/repo/owner/hooks",
+        "html_url": "https://github.com/repo/owner",
+        "id": 355197825,
+        "issue_comment_url": "https://api.github.com/repos/repo/owner/issues/comments{/number}",
+        "issue_events_url": "https://api.github.com/repos/repo/owner/issues/events{/number}",
+        "issues_url": "https://api.github.com/repos/repo/owner/issues{/number}",
+        "keys_url": "https://api.github.com/repos/repo/owner/keys{/key_id}",
+        "labels_url": "https://api.github.com/repos/repo/owner/labels{/name}",
+        "language": "Go",
+        "languages_url": "https://api.github.com/repos/repo/owner/languages",
+        "license": {
+          "key": "apache-2.0",
+          "name": "Apache License 2.0",
+          "node_id": "MDc6TGljZW5zZTI=",
+          "spdx_id": "Apache-2.0",
+          "url": "https://api.github.com/licenses/apache-2.0"
+        },
+        "merges_url": "https://api.github.com/repos/repo/owner/merges",
+        "milestones_url": "https://api.github.com/repos/repo/owner/milestones{/number}",
+        "mirror_url": null,
+        "name": "owner",
+        "node_id": "MDEwOlJlcG9zaXRvcnkzNTUxOTc4MjU=",
+        "notifications_url": "https://api.github.com/repos/repo/owner/notifications{?since,all,participating}",
+        "open_issues": 1,
+        "open_issues_count": 1,
+        "owner": {
+          "avatar_url": "https://avatars.githubusercontent.com/u/57996262?v=4",
+          "events_url": "https://api.github.com/users/repo/events{/privacy}",
+          "followers_url": "https://api.github.com/users/repo/followers",
+          "following_url": "https://api.github.com/users/repo/following{/other_user}",
+          "gists_url": "https://api.github.com/users/repo/gists{/gist_id}",
+          "gravatar_id": "",
+          "html_url": "https://github.com/repo",
+          "id": 57996262,
+          "login": "repo",
+          "node_id": "MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy",
+          "organizations_url": "https://api.github.com/users/repo/orgs",
+          "received_events_url": "https://api.github.com/users/repo/received_events",
+          "repos_url": "https://api.github.com/users/repo/repos",
+          "site_admin": false,
+          "starred_url": "https://api.github.com/users/repo/starred{/owner}{/repo}",
+          "subscriptions_url": "https://api.github.com/users/repo/subscriptions",
+          "type": "Organization",
+          "url": "https://api.github.com/users/repo"
+        },
+        "private": false,
+        "pulls_url": "https://api.github.com/repos/repo/owner/pulls{/number}",
+        "pushed_at": "2021-04-27T16:10:20Z",
+        "releases_url": "https://api.github.com/repos/repo/owner/releases{/id}",
+        "size": 9122,
+        "ssh_url": "git@github.com:repo/owner.git",
+        "stargazers_count": 1,
+        "stargazers_url": "https://api.github.com/repos/repo/owner/stargazers",
+        "statuses_url": "https://api.github.com/repos/repo/owner/statuses/{sha}",
+        "subscribers_url": "https://api.github.com/repos/repo/owner/subscribers",
+        "subscription_url": "https://api.github.com/repos/repo/owner/subscription",
+        "svn_url": "https://github.com/repo/owner",
+        "tags_url": "https://api.github.com/repos/repo/owner/tags",
+        "teams_url": "https://api.github.com/repos/repo/owner/teams",
+        "trees_url": "https://api.github.com/repos/repo/owner/git/trees{/sha}",
+        "updated_at": "2021-04-27T16:10:24Z",
+        "url": "https://api.github.com/repos/repo/owner",
+        "watchers": 1,
+        "watchers_count": 1
+      },
+      "sha": "SHA",
+      "user": {
+        "avatar_url": "https://avatars.githubusercontent.com/u/57996262?v=4",
+        "events_url": "https://api.github.com/users/repo/events{/privacy}",
+        "followers_url": "https://api.github.com/users/repo/followers",
+        "following_url": "https://api.github.com/users/repo/following{/other_user}",
+        "gists_url": "https://api.github.com/users/repo/gists{/gist_id}",
+        "gravatar_id": "",
+        "html_url": "https://github.com/repo",
+        "id": 57996262,
+        "login": "repo",
+        "node_id": "MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy",
+        "organizations_url": "https://api.github.com/users/repo/orgs",
+        "received_events_url": "https://api.github.com/users/repo/received_events",
+        "repos_url": "https://api.github.com/users/repo/repos",
+        "site_admin": false,
+        "starred_url": "https://api.github.com/users/repo/starred{/owner}{/repo}",
+        "subscriptions_url": "https://api.github.com/users/repo/subscriptions",
+        "type": "Organization",
+        "url": "https://api.github.com/users/repo"
+      }
+    },
+    "body": "- Fix linting error  in payload Replace
+    -
+    Resolve
+    pipelinespec
+    embedded
+    in
+    PipelineRun
+    too
+    ","
+    changed_files
+    ":3,"
+    closed_at
+    ":null,"
+    comments
+    ":0,"
+    comments_url
+    ":"
+    https://api.github.com/repos/repo/owner/issues/3/comments","commits":2,"commits_url":"https://api.github.com/repos/repo/owner/pulls/3/commits","created_at":"2021-04-27T19:26:47Z","deletions":26,"diff_url":"https://github.com/repo/owner/pull/3.diff","draft":false,"head":{"label":"chmouel:fix-resolve-pipelinespec","ref":"fix-resolve-pipelinespec","repo":{"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_url":"https://api.github.com/repos/chmouel/owner/{archive_format}{/ref}","archived":false,"assignees_url":"https://api.github.com/repos/chmouel/owner/assignees{/user}","blobs_url":"https://api.github.com/repos/chmouel/owner/git/blobs{/sha}","branches_url":"https://api.github.com/repos/chmouel/owner/branches{/branch}","clone_url":"https://github.com/chmouel/owner.git","collaborators_url":"https://api.github.com/repos/chmouel/owner/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/chmouel/owner/comments{/number}","commits_url":"https://api.github.com/repos/chmouel/owner/commits{/sha}","compare_url":"https://api.github.com/repos/chmouel/owner/compare/{base}...{head}","contents_url":"https://api.github.com/repos/chmouel/owner/contents/{+path}","contributors_url":"https://api.github.com/repos/chmouel/owner/contributors","created_at":"2021-04-06T13:26:51Z","default_branch":"main","delete_branch_on_merge":false,"deployments_url":"https://api.github.com/repos/chmouel/owner/deployments","description":"Pipelines as Code","disabled":false,"downloads_url":"https://api.github.com/repos/chmouel/owner/downloads","events_url":"https://api.github.com/repos/chmouel/owner/events","fork":true,"forks":0,"forks_count":0,"forks_url":"https://api.github.com/repos/chmouel/owner/forks","full_name":"chmouel/owner","git_commits_url":"https://api.github.com/repos/chmouel/owner/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/chmouel/owner/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/chmouel/owner/git/tags{/sha}","git_url":"git://github.com/chmouel/owner.git","has_downloads":true,"has_issues":false,"has_pages":false,"has_projects":true,"has_wiki":true,"homepage":null,"hooks_url":"https://api.github.com/repos/chmouel/owner/hooks","html_url":"https://github.com/chmouel/owner","id":355198074,"issue_comment_url":"https://api.github.com/repos/chmouel/owner/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/chmouel/owner/issues/events{/number}","issues_url":"https://api.github.com/repos/chmouel/owner/issues{/number}","keys_url":"https://api.github.com/repos/chmouel/owner/keys{/key_id}","labels_url":"https://api.github.com/repos/chmouel/owner/labels{/name}","language":null,"languages_url":"https://api.github.com/repos/chmouel/owner/languages","license":{"key":"apache-2.0","name":"Apache License 2.0","node_id":"MDc6TGljZW5zZTI=","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"merges_url":"https://api.github.com/repos/chmouel/owner/merges","milestones_url":"https://api.github.com/repos/chmouel/owner/milestones{/number}","mirror_url":null,"name":"owner","node_id":"MDEwOlJlcG9zaXRvcnkzNTUxOTgwNzQ=","notifications_url":"https://api.github.com/repos/chmouel/owner/notifications{?since,all,participating}","open_issues":0,"open_issues_count":0,"owner":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"},"private":false,"pulls_url":"https://api.github.com/repos/chmouel/owner/pulls{/number}","pushed_at":"2021-04-27T19:26:46Z","releases_url":"https://api.github.com/repos/chmouel/owner/releases{/id}","size":5,"ssh_url":"git@github.com:chmouel/owner.git","stargazers_count":0,"stargazers_url":"https://api.github.com/repos/chmouel/owner/stargazers","statuses_url":"https://api.github.com/repos/chmouel/owner/statuses/{sha}","subscribers_url":"https://api.github.com/repos/chmouel/owner/subscribers","subscription_url":"https://api.github.com/repos/chmouel/owner/subscription","svn_url":"https://github.com/chmouel/owner","tags_url":"https://api.github.com/repos/chmouel/owner/tags","teams_url":"https://api.github.com/repos/chmouel/owner/teams","trees_url":"https://api.github.com/repos/chmouel/owner/git/trees{/sha}","updated_at":"2021-04-06T15:19:15Z","url":"https://api.github.com/repos/chmouel/owner","watchers":0,"watchers_count":0},"sha":"SHA","user":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"}},"html_url":"https://github.com/repo/owner/pull/3","id":624596967,"issue_url":"https://api.github.com/repos/repo/owner/issues/3","labels":[],"locked":false,"maintainer_can_modify":true,"merge_commit_sha":null,"mergeable":null,"mergeable_state":"unknown","merged":false,"merged_at":null,"merged_by":null,"milestone":null,"node_id":"MDExOlB1bGxSZXF1ZXN0NjI0NTk2OTY3","number":3,"patch_url":"https://github.com/repo/owner/pull/3.patch","rebaseable":null,"requested_reviewers":[],"requested_teams":[],"review_comment_url":"https://api.github.com/repos/repo/owner/pulls/comments{/number}","review_comments":0,"review_comments_url":"https://api.github.com/repos/repo/owner/pulls/3/comments","state":"open","statuses_url":"https://api.github.com/repos/repo/owner/statuses/SHA","title":"fix resolve pipelinespec","updated_at":"2021-04-27T19:26:47Z","url":"https://api.github.com/repos/repo/owner/pulls/3","user":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"}},"repository":{"archive_url":"https://api.github.com/repos/repo/owner/{archive_format}{/ref}","archived":false,"assignees_url":"https://api.github.com/repos/repo/owner/assignees{/user}","blobs_url":"https://api.github.com/repos/repo/owner/git/blobs{/sha}","branches_url":"https://api.github.com/repos/repo/owner/branches{/branch}","clone_url":"https://github.com/repo/owner.git","collaborators_url":"https://api.github.com/repos/repo/owner/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/repo/owner/comments{/number}","commits_url":"https://api.github.com/repos/repo/owner/commits{/sha}","compare_url":"https://api.github.com/repos/repo/owner/compare/{base}...{head}","contents_url":"https://api.github.com/repos/repo/owner/contents/{+path}","contributors_url":"https://api.github.com/repos/repo/owner/contributors","created_at":"2021-04-06T13:26:01Z","default_branch":"main","deployments_url":"https://api.github.com/repos/repo/owner/deployments","description":"Pipelines as Code","disabled":false,"downloads_url":"https://api.github.com/repos/repo/owner/downloads","events_url":"https://api.github.com/repos/repo/owner/events","fork":false,"forks":3,"forks_count":3,"forks_url":"https://api.github.com/repos/repo/owner/forks","full_name":"repo/owner","git_commits_url":"https://api.github.com/repos/repo/owner/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/repo/owner/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/repo/owner/git/tags{/sha}","git_url":"git://github.com/repo/owner.git","has_downloads":true,"has_issues":true,"has_pages":false,"has_projects":true,"has_wiki":true,"homepage":null,"hooks_url":"https://api.github.com/repos/repo/owner/hooks","html_url":"https://github.com/repo/owner","id":355197825,"issue_comment_url":"https://api.github.com/repos/repo/owner/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/repo/owner/issues/events{/number}","issues_url":"https://api.github.com/repos/repo/owner/issues{/number}","keys_url":"https://api.github.com/repos/repo/owner/keys{/key_id}","labels_url":"https://api.github.com/repos/repo/owner/labels{/name}","language":"Go","languages_url":"https://api.github.com/repos/repo/owner/languages","license":{"key":"apache-2.0","name":"Apache License 2.0","node_id":"MDc6TGljZW5zZTI=","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"merges_url":"https://api.github.com/repos/repo/owner/merges","milestones_url":"https://api.github.com/repos/repo/owner/milestones{/number}","mirror_url":null,"name":"owner","node_id":"MDEwOlJlcG9zaXRvcnkzNTUxOTc4MjU=","notifications_url":"https://api.github.com/repos/repo/owner/notifications{?since,all,participating}","open_issues":1,"open_issues_count":1,"owner":{"avatar_url":"https://avatars.githubusercontent.com/u/57996262?v=4","events_url":"https://api.github.com/users/repo/events{/privacy}","followers_url":"https://api.github.com/users/repo/followers","following_url":"https://api.github.com/users/repo/following{/other_user}","gists_url":"https://api.github.com/users/repo/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/repo","id":57996262,"login":"repo","node_id":"MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy","organizations_url":"https://api.github.com/users/repo/orgs","received_events_url":"https://api.github.com/users/repo/received_events","repos_url":"https://api.github.com/users/repo/repos","site_admin":false,"starred_url":"https://api.github.com/users/repo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/repo/subscriptions","type":"Organization","url":"https://api.github.com/users/repo"},"private":false,"pulls_url":"https://api.github.com/repos/repo/owner/pulls{/number}","pushed_at":"2021-04-27T16:10:20Z","releases_url":"https://api.github.com/repos/repo/owner/releases{/id}","size":9122,"ssh_url":"git@github.com:repo/owner.git","stargazers_count":1,"stargazers_url":"https://api.github.com/repos/repo/owner/stargazers","statuses_url":"https://api.github.com/repos/repo/owner/statuses/{sha}","subscribers_url":"https://api.github.com/repos/repo/owner/subscribers","subscription_url":"https://api.github.com/repos/repo/owner/subscription","svn_url":"https://github.com/repo/owner","tags_url":"https://api.github.com/repos/repo/owner/tags","teams_url":"https://api.github.com/repos/repo/owner/teams","trees_url":"https://api.github.com/repos/repo/owner/git/trees{/sha}","updated_at":"2021-04-27T16:10:24Z","url":"https://api.github.com/repos/repo/owner","watchers":1,"watchers_count":1},"sender":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"}}
diff --git a/pkg/webvcs/github_test.go b/pkg/webvcs/github_test.go
deleted file mode 100644
index 988fe902..00000000
--- a/pkg/webvcs/github_test.go
+++ /dev/null
@@ -1,848 +0,0 @@
-package webvcs
-
-import (
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"path/filepath"
-	"reflect"
-	"strings"
-	"testing"
-
-	ghtesthelper "github.com/openshift-pipelines/pipelines-as-code/pkg/test/github"
-	rtesting "knative.dev/pkg/reconciler/testing"
-
-	"github.com/google/go-cmp/cmp"
-	"github.com/google/go-github/v35/github"
-	"go.uber.org/zap"
-	zapobserver "go.uber.org/zap/zaptest/observer"
-	"gotest.tools/v3/assert"
-)
-
-func getLogger() (*zap.SugaredLogger, *zapobserver.ObservedLogs) {
-	observer, logobserver := zapobserver.New(zap.InfoLevel)
-	logger := zap.New(observer).Sugar()
-	return logger, logobserver
-}
-
-func setupFakesURLS() (client GithubVCS, teardown func()) {
-	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-
-	mux.HandleFunc("/repos/check/run/check-runs", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"id": 555}`)
-	})
-
-	mux.HandleFunc("/repos/check/run/check-runs/2026", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"id": 666}`)
-	})
-
-	mux.HandleFunc("/repos/foo/bar/contents/README.md", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{
-"name": "README.md",
-"sha": "readmemdsha",
-"type": "file"
-}`)
-	})
-
-	mux.HandleFunc("/repos/foo/bar/git/blobs/readmemdsha", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{
-"name": "README.md",
-"content": "aGVsbG8gbW90bwo=",
-"encoding": "base64"
-}`)
-	})
-
-	mux.HandleFunc("/repos/tekton/dir/git/blobs/pipelineyaml", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{
-"name": "README.md",
-"content": "aGVsbG8gcGlwZWxpbmV5YW1s",
-"encoding": "base64"
-}`)
-	})
-
-	mux.HandleFunc("/repos/tekton/dir/git/blobs/runyaml", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{
-"name": "README.md",
-"content": "aGVsbG8gcnVueWFtbA==",
-"encoding": "base64"
-}`)
-	})
-
-	mux.HandleFunc("/repos/tekton/dir/git/blobs/tektonyaml", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{
-"name": "README.md",
-"content": "aGVsbG8gdGVrdG9ueWFtbA==",
-"encoding": "base64"
-}`)
-	})
-
-	mux.HandleFunc("/repos/tekton/dir/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `[{
-
-				  "name": "pipeline.yaml",
-				  "path": ".tekton/pipeline.yaml",
-				  "sha": "pipelineyaml",
-				  "type": "file"
-				},
-				{
-				  "name": "run.yaml",
-				  "path": ".tekton/run.yaml",
-				  "sha": "runyaml",
-				  "type": "file"
-				}]`)
-	})
-	mux.HandleFunc("/repos/throw/error/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, "ERRROR")
-	})
-
-	mux.HandleFunc("/repos/its/afile/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{
-"name": ".tekton",
-"sha": "decfae2653959f7c6c25f21f026c3819bea41ecf",
-"type": "file",
-"content": "WyFbQ29udGFpbmVyIFJlcG9zaXRvcnkgb24gUXVheV0oaHR0cHM6Ly9xdWF5\nLmlvL3JlcG9zaXRvcnkvY2htb3VlbC90ZWt0b24tYXNhLWNvZGUvc3RhdHVz"}`)
-	})
-	mux.HandleFunc("/repos/pas/la/contents/.tekton", func(w http.ResponseWriter, r *http.Request) {
-		w.WriteHeader(http.StatusNotFound)
-	})
-
-	gcvs := GithubVCS{
-		Client: fakeclient,
-	}
-	return gcvs, teardown
-}
-
-func TestPayLoadFix(t *testing.T) {
-	b, err := ioutil.ReadFile("testdata/pull_request_with_newlines.json")
-	assert.NilError(t, err)
-	ctx, _ := rtesting.SetupFakeContext(t)
-	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-	defer teardown()
-	mux.HandleFunc("/repos/repo/owner/commits/SHA", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc("/repos/repo/owner/git/commits/SHA", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-
-	gvcs := GithubVCS{
-		Client: fakeclient,
-	}
-
-	logger, _ := getLogger()
-	r := RunInfo{
-		EventType:     "pull_request",
-		TriggerTarget: "pull_request",
-	}
-	_, err = gvcs.ParsePayload(ctx, logger, r, string(b))
-	// would bomb out on "assertion failed: error is not nil: invalid character
-	// '\n' in string literal" if we don't fix the payload
-	assert.NilError(t, err)
-}
-
-func TestParsePayloadRerequestFromPullRequest(t *testing.T) {
-	checkrunSender := "jean-pierre"
-	prOwner := "owner"
-	repoName := "repo"
-	prNumber := "123"
-	sha := "ParsePayloadRerequestFromPullRequestSHA"
-	checkrunEvent := fmt.Sprintf(`{"action": "rerequested",
-	"sender": {"login": "%s"},
-	"check_run": {"check_suite": {"pull_requests": [{"number": %s}]}},
-	"repository": {"name": "%s", "owner": {"login": "%s"}}}`,
-		checkrunSender, prNumber, repoName, prOwner)
-	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-	defer teardown()
-	mux.HandleFunc("/repos/"+prOwner+"/"+repoName+"/pulls/"+prNumber, func(rw http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprintf(rw, `{"head": {"sha": "%s", "ref": "123"}, "user": {"login": "%s"}}`, sha, prOwner)
-	})
-	mux.HandleFunc("/repos/owner/repo/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc("/repos/owner/repo/git/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	ctx, _ := rtesting.SetupFakeContext(t)
-	gvcs := GithubVCS{
-		Client: fakeclient,
-	}
-	logger, observer := getLogger()
-	r := RunInfo{
-		EventType:     "check_run",
-		TriggerTarget: "issue-recheck",
-	}
-	runinfo, err := gvcs.ParsePayload(ctx, logger, r, checkrunEvent)
-	assert.NilError(t, err)
-
-	assert.Equal(t, prOwner, runinfo.Owner)
-	assert.Equal(t, repoName, runinfo.Repository)
-	assert.Assert(t, checkrunSender != runinfo.Sender)
-	assert.Equal(t, runinfo.EventType, "pull_request")
-	assert.Assert(t, strings.Contains(observer.TakeAll()[0].Message, "Recheck of PR"))
-}
-
-func TestParsePayloadRerequestFromPush(t *testing.T) {
-	sender := "jean-pierre"
-	headBranch := "tartonpion"
-	headSHA := "TestParsePayloadRerequestFromPushSHA"
-	owner := "owner"
-	repository := "repo"
-	url := fmt.Sprintf("https://github.com/%s/%s", owner, repository)
-	checkrunEvent := fmt.Sprintf(`{
-  "action": "rerequested",
-  "check_run": {
-    "check_suite": {
-      "head_branch": "%s",
-      "head_sha": "%s",
-      "pull_requests": []
-    }
-  },
-  "repository": {
-    "default_branch": "main",
-    "html_url": "%s",
-    "name": "%s",
-    "owner": {
-      "login": "%s"
-    }
-  },
-  "sender": {
-    "login": "%s"
-  }
-}`,
-		headBranch, headSHA, url, repository, owner, sender)
-	ctx, _ := rtesting.SetupFakeContext(t)
-	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-	defer teardown()
-	gvcs := GithubVCS{
-		Client: fakeclient,
-	}
-	mux.HandleFunc("/repos/owner/repo/commits/"+headSHA, func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc("/repos/owner/repo/git/commits/"+headSHA, func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-
-	r := RunInfo{
-		EventType:     "check_run",
-		TriggerTarget: "issue-recheck",
-	}
-	logger, _ := getLogger()
-	runinfo, err := gvcs.ParsePayload(ctx, logger, r, checkrunEvent)
-	assert.NilError(t, err)
-
-	assert.Equal(t, runinfo.EventType, "push")
-	assert.Equal(t, runinfo.HeadBranch, headBranch)
-	assert.Equal(t, runinfo.Owner, owner)
-	assert.Equal(t, runinfo.Repository, repository)
-	assert.Equal(t, runinfo.URL, url)
-	assert.Assert(t, sender == runinfo.Sender) // TODO: should it be set to the push sender?
-}
-
-func TestParsePayLoadRetest(t *testing.T) {
-	issueSender := "tartanpion"
-	prOwner := "user1"
-	repoOwner := "openshift"
-	repoName := "pipelines"
-	prNumber := "123"
-	sha := "TestParsePayLoadRetestSHA"
-
-	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-	defer teardown()
-	mux.HandleFunc("/repos/"+prOwner+"/"+repoName+"/pulls/"+prNumber, func(rw http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprintf(rw, `{"head": {"sha": "%s", "ref": "123"}, "user": {"login": "%s"}}`, sha, prOwner)
-	})
-	mux.HandleFunc("/repos/user1/pipelines/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc("/repos/user1/pipelines/git/commits/"+sha, func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	issueEvent := fmt.Sprintf(`{
-  "sender": {
-	"login": "%s"
-  },
-  "repository": {
-	"name": "%s",
-	"owner": {
-	  "login": "%s"
-	}
-  },
-  "issue": {
-	"pull_request": {
-	  "html_url": "https://github.com/%s/%s/pull/%s"
-	}
-  }
-}`, issueSender, repoName, prOwner, repoName, repoOwner, prNumber)
-
-	ctx, _ := rtesting.SetupFakeContext(t)
-	logger, observer := getLogger()
-	gvcs := GithubVCS{
-		Client: fakeclient,
-	}
-
-	// TODO
-	r := RunInfo{
-		EventType:     "issue_comment",
-		TriggerTarget: "issue_comment",
-	}
-	runinfo, err := gvcs.ParsePayload(ctx, logger, r, issueEvent)
-	assert.NilError(t, err)
-	assert.Equal(t, prOwner, runinfo.Owner)
-	// Make sure the PR owner is the runinfo.Owner and not the issueSender
-	assert.Assert(t, issueSender != runinfo.Owner)
-	firstObservedMessage := observer.TakeAll()[0].Message
-	assert.Assert(t, strings.Contains(firstObservedMessage, "recheck"))
-	assert.Equal(t, runinfo.EventType, "pull_request")
-}
-
-func TestParsePayload(t *testing.T) {
-	b, err := ioutil.ReadFile("testdata/pull_request.json")
-	assert.NilError(t, err)
-	fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-	defer teardown()
-	mux.HandleFunc("/repos/chmouel/scratchpad/commits/cc8334de8e056317d18bd00c2588c3f7c95af294", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	mux.HandleFunc("/repos/chmouel/scratchpad/git/commits/cc8334de8e056317d18bd00c2588c3f7c95af294", func(w http.ResponseWriter, r *http.Request) {
-		_, _ = fmt.Fprint(w, `{"commit": {"message": "HELLO"}}`)
-	})
-	gvcs := GithubVCS{
-		Client: fakeclient,
-	}
-	ctx, _ := rtesting.SetupFakeContext(t)
-	logger, _ := getLogger()
-
-	r := RunInfo{
-		EventType:     "pull_request",
-		TriggerTarget: "pull_request",
-	}
-	runinfo, err := gvcs.ParsePayload(ctx, logger, r, string(b))
-	assert.NilError(t, err)
-	assert.Assert(t, runinfo.BaseBranch == "master")
-	assert.Assert(t, runinfo.Owner == "chmouel")
-	assert.Assert(t, runinfo.Repository == "scratchpad")
-	assert.Equal(t, runinfo.EventType, "pull_request")
-	assert.Assert(t, runinfo.URL == "https://github.com/chmouel/scratchpad")
-}
-
-func TestParsePayloadInvalid(t *testing.T) {
-	ctx, _ := rtesting.SetupFakeContext(t)
-	gvcs := NewGithubVCS("none", "")
-	logger, _ := getLogger()
-	r := RunInfo{
-		EventType:     "pull_request",
-		TriggerTarget: "pull_request",
-	}
-	_, err := gvcs.ParsePayload(ctx, logger, r, "hello moto")
-	assert.ErrorContains(t, err, "invalid character")
-}
-
-func TestParsePayloadUnkownEvent(t *testing.T) {
-	ctx, _ := rtesting.SetupFakeContext(t)
-	gvcs := NewGithubVCS("none", "")
-	logger, _ := getLogger()
-	r := RunInfo{
-		EventType:     "foo",
-		TriggerTarget: "foo",
-	}
-	_, err := gvcs.ParsePayload(ctx, logger, r, "{\"hello\": \"moto\"}")
-	assert.ErrorContains(t, err, "unknown X-Github-Event")
-}
-
-func TestParsePayCannotParse(t *testing.T) {
-	gvcs := NewGithubVCS("none", "")
-	ctx, _ := rtesting.SetupFakeContext(t)
-	logger, _ := getLogger()
-	r := RunInfo{
-		EventType:     "gollum",
-		TriggerTarget: "gollum",
-	}
-	_, err := gvcs.ParsePayload(ctx, logger, r, "{}")
-	assert.Error(t, err, "this event is not supported")
-}
-
-func TestGetFileInsideRepo(t *testing.T) {
-	ctx, _ := rtesting.SetupFakeContext(t)
-	gcvs, teardown := setupFakesURLS()
-	defer teardown()
-	type args struct {
-		path      string
-		runinfo   *RunInfo
-		assertion func(t *testing.T, got string, err error)
-	}
-
-	testGetTektonDir := []struct {
-		name string
-		args args
-	}{
-		{
-			name: "testgood",
-			args: args{
-				assertion: func(t *testing.T, got string, err error) {
-					assert.NilError(t, err)
-				},
-				path: "README.md",
-				runinfo: &RunInfo{
-					Owner:      "foo",
-					Repository: "bar",
-				},
-			},
-		},
-		{
-			name: "notfound",
-			args: args{
-				assertion: func(t *testing.T, got string, err error) {
-					assert.ErrorContains(t, err, "404")
-				},
-				path: ".tekton",
-				runinfo: &RunInfo{
-					Owner:      "pas",
-					Repository: "la",
-				},
-			},
-		},
-		{
-			name: "file_should_be_a_dir",
-			args: args{
-				assertion: func(t *testing.T, got string, err error) {
-					assert.ErrorContains(t, err, "is a directory")
-				},
-				path: ".tekton",
-				runinfo: &RunInfo{
-					Owner:      "tekton",
-					Repository: "dir",
-				},
-			},
-		},
-		{
-			name: "throwerror",
-			args: args{
-				assertion: func(t *testing.T, got string, err error) {
-					assert.ErrorContains(t, err, "invalid character")
-				},
-				path: ".tekton",
-				runinfo: &RunInfo{
-					Owner:      "throw",
-					Repository: "error",
-				},
-			},
-		},
-	}
-	for _, tt := range testGetTektonDir {
-		t.Run(tt.name, func(t *testing.T) {
-			got, err := gcvs.GetFileInsideRepo(ctx, tt.args.path, false, tt.args.runinfo)
-			tt.args.assertion(t, got, err)
-		})
-	}
-}
-
-func TestGetTektonDir(t *testing.T) {
-	ctx, _ := rtesting.SetupFakeContext(t)
-	gcvs, teardown := setupFakesURLS()
-	defer teardown()
-
-	type args struct {
-		path      string
-		runinfo   *RunInfo
-		assertion func(t *testing.T, got []*github.RepositoryContent, err error)
-	}
-
-	testGetTektonDir := []struct {
-		name string
-		args args
-	}{
-		{
-			name: "testgood",
-			args: args{
-				assertion: func(t *testing.T, got []*github.RepositoryContent, err error) {
-					assert.NilError(t, err)
-					assert.Assert(t, got != nil)
-				},
-				path: ".tekton",
-				runinfo: &RunInfo{
-					Owner:      "tekton",
-					Repository: "dir",
-				},
-			},
-		},
-		{
-			name: "notfound",
-			args: args{
-				assertion: func(t *testing.T, got []*github.RepositoryContent, err error) {
-					assert.NilError(t, err)
-					assert.Assert(t, got == nil)
-				},
-				path: ".tekton",
-				runinfo: &RunInfo{
-					Owner:      "pas",
-					Repository: "la",
-				},
-			},
-		},
-		{
-			name: "tektondirisafile",
-			args: args{
-				assertion: func(t *testing.T, got []*github.RepositoryContent, err error) {
-					assert.Error(t, err, "the object .tekton is a file instead of a directory")
-					assert.Assert(t, got == nil)
-				},
-				path: ".tekton",
-				runinfo: &RunInfo{
-					Owner:      "its",
-					Repository: "afile",
-				},
-			},
-		},
-		{
-			name: "throwerror",
-			args: args{
-				assertion: func(t *testing.T, got []*github.RepositoryContent, err error) {
-					assert.ErrorContains(t, err, "invalid character")
-					assert.Assert(t, got == nil)
-				},
-				path: ".tekton",
-				runinfo: &RunInfo{
-					Owner:      "throw",
-					Repository: "error",
-				},
-			},
-		},
-	}
-	for _, tt := range testGetTektonDir {
-		t.Run(tt.name, func(t *testing.T) {
-			got, err := gcvs.GetTektonDir(ctx, tt.args.path, tt.args.runinfo)
-			tt.args.assertion(t, got, err)
-		})
-	}
-}
-
-func TestGetTektonDirTemplate(t *testing.T) {
-	const expected = `
-hello pipelineyaml
----
-hello runyaml
-`
-	ctx, _ := rtesting.SetupFakeContext(t)
-	gcvs, teardown := setupFakesURLS()
-	defer teardown()
-	runinfo := &RunInfo{
-		Owner:      "tekton",
-		Repository: "dir",
-	}
-
-	ghr, err := gcvs.GetTektonDir(ctx, ".tekton", runinfo)
-	assert.NilError(t, err)
-
-	got, err := gcvs.ConcatAllYamlFiles(ctx, ghr, runinfo)
-	assert.NilError(t, err)
-	if d := cmp.Diff(got, expected); d != "" {
-		t.Fatalf("-got, +want: %v", d)
-	}
-}
-
-func TestGithubVCS_CreateCheckRun(t *testing.T) {
-	ctx, _ := rtesting.SetupFakeContext(t)
-	gcvs, teardown := setupFakesURLS()
-	defer teardown()
-	runinfo := &RunInfo{
-		Owner:      "check",
-		Repository: "run",
-	}
-	cr, err := gcvs.CreateCheckRun(ctx, "hello moto", runinfo)
-	assert.NilError(t, err)
-	assert.Equal(t, cr.GetID(), int64(555))
-}
-
-func TestCheckSenderOrgMembership(t *testing.T) {
-	tests := []struct {
-		name, apiReturn  string
-		allowed, wantErr bool
-		runinfo          *RunInfo
-	}{
-		{
-			name: "Check Sender Org Membership",
-			runinfo: &RunInfo{
-				Owner:  "organization",
-				Sender: "me",
-			},
-			apiReturn: `[{"login": "me"}]`,
-			allowed:   true,
-			wantErr:   false,
-		},
-		{
-			name: "Check Sender not in Org Membership",
-			runinfo: &RunInfo{
-				Owner:  "organization",
-				Sender: "me",
-			},
-			apiReturn: `[{"login": "not"}]`,
-			allowed:   false,
-		},
-		{
-			name: "Not found on organization",
-			runinfo: &RunInfo{
-				Owner:  "notfound",
-				Sender: "me",
-			},
-			allowed: false,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-			defer teardown()
-			ctx, _ := rtesting.SetupFakeContext(t)
-			gvcs := GithubVCS{
-				Client: fakeclient,
-			}
-			mux.HandleFunc(fmt.Sprintf("/orgs/%s/public_members", tt.runinfo.Owner), func(rw http.ResponseWriter, r *http.Request) {
-				fmt.Fprint(rw, tt.apiReturn)
-			})
-
-			allowed, err := gvcs.CheckSenderOrgMembership(ctx, tt.runinfo)
-			if tt.wantErr && err == nil {
-				t.Error("We didn't get an error when we wanted one")
-			}
-			if !tt.wantErr && err != nil {
-				t.Errorf("We got an error when we didn't want it: %s", err)
-			}
-			assert.Equal(t, tt.allowed, allowed)
-		})
-	}
-}
-
-func TestGetStringPullRequestComment(t *testing.T) {
-	regexp := `(^|\n)/retest(\r\n|$)`
-	tests := []struct {
-		name, apiReturn string
-		wantErr         bool
-		runinfo         *RunInfo
-		wantRet         bool
-	}{
-		{
-			name:      "Get String from comments",
-			runinfo:   &RunInfo{URL: "http://1"},
-			apiReturn: `[{"body": "/retest"}]`,
-			wantRet:   true,
-		},
-		{
-			name:      "Not matching string in comments",
-			runinfo:   &RunInfo{URL: "http://1"},
-			apiReturn: `[{"body": ""}]`,
-			wantRet:   false,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-			defer teardown()
-			ctx, _ := rtesting.SetupFakeContext(t)
-			gvcs := GithubVCS{
-				Client: fakeclient,
-			}
-			mux.HandleFunc(fmt.Sprintf("/repos/issues/%s/comments", filepath.Base(tt.runinfo.URL)), func(rw http.ResponseWriter, r *http.Request) {
-				fmt.Fprint(rw, tt.apiReturn)
-			})
-
-			ret, err := gvcs.GetStringPullRequestComment(ctx, tt.runinfo, regexp)
-			if tt.wantErr && err == nil {
-				t.Error("We didn't get an error when we wanted one")
-			}
-			if !tt.wantErr && err != nil {
-				t.Errorf("We got an error when we didn't want it: %s", err)
-			}
-
-			if tt.wantRet {
-				assert.Assert(t, ret != nil)
-			}
-		})
-	}
-}
-
-func TestRunInfoCheck(t *testing.T) {
-	type fields struct {
-		Owner         string
-		Repository    string
-		DefaultBranch string
-		SHA           string
-		URL           string
-		Sender        string
-		CheckRunID    *int64
-		BaseBranch    string
-		HeadBranch    string
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		wantErr bool
-	}{
-		{
-			name:    "testerr",
-			fields:  fields{Owner: "hello"},
-			wantErr: true,
-		},
-		{
-			name: "testgood",
-			fields: fields{
-				Owner:         "hello",
-				Repository:    "moto",
-				DefaultBranch: "default",
-				SHA:           "1d1",
-				URL:           "https://anywhere",
-				BaseBranch:    "main",
-				Sender:        "beeboo",
-				HeadBranch:    "pr",
-			},
-			wantErr: false,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			r := RunInfo{
-				Owner:         tt.fields.Owner,
-				Repository:    tt.fields.Repository,
-				DefaultBranch: tt.fields.DefaultBranch,
-				SHA:           tt.fields.SHA,
-				URL:           tt.fields.URL,
-				BaseBranch:    tt.fields.BaseBranch,
-				HeadBranch:    tt.fields.HeadBranch,
-				CheckRunID:    tt.fields.CheckRunID,
-				Sender:        tt.fields.Sender,
-				EventType:     "pull_request",
-				TriggerTarget: "pull_request",
-			}
-			if err := r.Check(); (err != nil) != tt.wantErr {
-				t.Errorf("RunInfo.Check() error = %v, wantErr %v", err, tt.wantErr)
-			}
-		})
-	}
-}
-
-func TestGithubVCS_CreateStatus(t *testing.T) {
-	checkrunid := int64(2026)
-	resultid := int64(666)
-	runinfo := &RunInfo{Owner: "check", Repository: "run", CheckRunID: &checkrunid}
-
-	type args struct {
-		runinfo            *RunInfo
-		status             string
-		conclusion         string
-		text               string
-		detailsURL         string
-		titleSubstr        string
-		nilCompletedAtDate bool
-	}
-	tests := []struct {
-		name    string
-		args    args
-		want    *github.CheckRun
-		wantErr bool
-	}{
-		{
-			name: "success",
-			args: args{
-				runinfo:     runinfo,
-				status:      "completed",
-				conclusion:  "success",
-				text:        "Yay",
-				detailsURL:  "https://cireport.com",
-				titleSubstr: "Success",
-			},
-			want:    &github.CheckRun{ID: &resultid},
-			wantErr: false,
-		},
-		{
-			name: "in_progress",
-			args: args{
-				runinfo:            runinfo,
-				status:             "in_progress",
-				conclusion:         "",
-				text:               "Yay",
-				detailsURL:         "https://cireport.com",
-				nilCompletedAtDate: true,
-			},
-			want:    &github.CheckRun{ID: &resultid},
-			wantErr: false,
-		},
-		{
-			name: "failure",
-			args: args{
-				runinfo:     runinfo,
-				status:      "completed",
-				conclusion:  "failure",
-				text:        "Nay",
-				detailsURL:  "https://cireport.com",
-				titleSubstr: "Failed",
-			},
-			want:    &github.CheckRun{ID: &resultid},
-			wantErr: false,
-		},
-		{
-			name: "skipped",
-			args: args{
-				runinfo:     runinfo,
-				status:      "completed",
-				conclusion:  "skipped",
-				text:        "Skipit",
-				detailsURL:  "https://cireport.com",
-				titleSubstr: "Skipped",
-			},
-			want:    &github.CheckRun{ID: &resultid},
-			wantErr: false,
-		},
-		{
-			name: "unknown",
-			args: args{
-				runinfo:     runinfo,
-				status:      "completed",
-				conclusion:  "neutral",
-				text:        "Je sais pas ce qui se passe wesh",
-				detailsURL:  "https://cireport.com",
-				titleSubstr: "Unknown",
-			},
-			want:    &github.CheckRun{ID: &resultid},
-			wantErr: false,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			fakeclient, mux, _, teardown := ghtesthelper.SetupGH()
-			defer teardown()
-
-			ctx, _ := rtesting.SetupFakeContext(t)
-			gcvs := GithubVCS{
-				Client: fakeclient,
-			}
-			mux.HandleFunc(fmt.Sprintf("/repos/check/run/check-runs/%d", checkrunid), func(rw http.ResponseWriter, r *http.Request) {
-				bit, _ := ioutil.ReadAll(r.Body)
-				checkRun := &github.CheckRun{}
-				err := json.Unmarshal(bit, checkRun)
-				assert.NilError(t, err)
-
-				if tt.args.nilCompletedAtDate {
-					// I guess that's the way you check for an undefined year,
-					// or maybe i don't understand fully how go works😅
-					assert.Assert(t, checkRun.GetCompletedAt().Year() == 0o001)
-				}
-				assert.Equal(t, checkRun.GetStatus(), tt.args.status)
-				assert.Equal(t, checkRun.GetConclusion(), tt.args.conclusion)
-				assert.Equal(t, checkRun.Output.GetText(), tt.args.text)
-				assert.Equal(t, checkRun.GetDetailsURL(), tt.args.detailsURL)
-				assert.Assert(t, strings.Contains(checkRun.Output.GetTitle(), tt.args.titleSubstr))
-				_, err = fmt.Fprintf(rw, `{"id": %d}`, resultid)
-				assert.NilError(t, err)
-			})
-
-			got, err := gcvs.CreateStatus(ctx, tt.args.runinfo, tt.args.status, tt.args.conclusion, tt.args.text, tt.args.detailsURL)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("GithubVCS.CreateStatus() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("GithubVCS.CreateStatus() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
diff --git a/pkg/webvcs/testdata/pull_request_with_newlines.json b/pkg/webvcs/testdata/pull_request_with_newlines.json
deleted file mode 100644
index 0423c295..00000000
--- a/pkg/webvcs/testdata/pull_request_with_newlines.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{"action":"opened","installation":{"id":16557439,"node_id":"MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTY1NTc0Mzk="},"number":3,"organization":{"avatar_url":"https://avatars.githubusercontent.com/u/57996262?v=4","description":"","events_url":"https://api.github.com/orgs/repo/events","hooks_url":"https://api.github.com/orgs/repo/hooks","id":57996262,"issues_url":"https://api.github.com/orgs/repo/issues","login":"repo","members_url":"https://api.github.com/orgs/repo/members{/member}","node_id":"MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy","public_members_url":"https://api.github.com/orgs/repo/public_members{/member}","repos_url":"https://api.github.com/orgs/repo/repos","url":"https://api.github.com/orgs/repo"},"pull_request":{"_links":{"comments":{"href":"https://api.github.com/repos/repo/owner/issues/3/comments"},"commits":{"href":"https://api.github.com/repos/repo/owner/pulls/3/commits"},"html":{"href":"https://github.com/repo/owner/pull/3"},"issue":{"href":"https://api.github.com/repos/repo/owner/issues/3"},"review_comment":{"href":"https://api.github.com/repos/repo/owner/pulls/comments{/number}"},"review_comments":{"href":"https://api.github.com/repos/repo/owner/pulls/3/comments"},"self":{"href":"https://api.github.com/repos/repo/owner/pulls/3"},"statuses":{"href":"https://api.github.com/repos/repo/owner/statuses/SHA"}},"active_lock_reason":null,"additions":38,"assignee":null,"assignees":[],"author_association":"MEMBER","auto_merge":null,"base":{"label":"repo:main","ref":"main","repo":{"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_url":"https://api.github.com/repos/repo/owner/{archive_format}{/ref}","archived":false,"assignees_url":"https://api.github.com/repos/repo/owner/assignees{/user}","blobs_url":"https://api.github.com/repos/repo/owner/git/blobs{/sha}","branches_url":"https://api.github.com/repos/repo/owner/branches{/branch}","clone_url":"https://github.com/repo/owner.git","collaborators_url":"https://api.github.com/repos/repo/owner/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/repo/owner/comments{/number}","commits_url":"https://api.github.com/repos/repo/owner/commits{/sha}","compare_url":"https://api.github.com/repos/repo/owner/compare/{base}...{head}","contents_url":"https://api.github.com/repos/repo/owner/contents/{+path}","contributors_url":"https://api.github.com/repos/repo/owner/contributors","created_at":"2021-04-06T13:26:01Z","default_branch":"main","delete_branch_on_merge":false,"deployments_url":"https://api.github.com/repos/repo/owner/deployments","description":"Pipelines as Code","disabled":false,"downloads_url":"https://api.github.com/repos/repo/owner/downloads","events_url":"https://api.github.com/repos/repo/owner/events","fork":false,"forks":3,"forks_count":3,"forks_url":"https://api.github.com/repos/repo/owner/forks","full_name":"repo/owner","git_commits_url":"https://api.github.com/repos/repo/owner/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/repo/owner/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/repo/owner/git/tags{/sha}","git_url":"git://github.com/repo/owner.git","has_downloads":true,"has_issues":true,"has_pages":false,"has_projects":true,"has_wiki":true,"homepage":null,"hooks_url":"https://api.github.com/repos/repo/owner/hooks","html_url":"https://github.com/repo/owner","id":355197825,"issue_comment_url":"https://api.github.com/repos/repo/owner/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/repo/owner/issues/events{/number}","issues_url":"https://api.github.com/repos/repo/owner/issues{/number}","keys_url":"https://api.github.com/repos/repo/owner/keys{/key_id}","labels_url":"https://api.github.com/repos/repo/owner/labels{/name}","language":"Go","languages_url":"https://api.github.com/repos/repo/owner/languages","license":{"key":"apache-2.0","name":"Apache License 2.0","node_id":"MDc6TGljZW5zZTI=","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"merges_url":"https://api.github.com/repos/repo/owner/merges","milestones_url":"https://api.github.com/repos/repo/owner/milestones{/number}","mirror_url":null,"name":"owner","node_id":"MDEwOlJlcG9zaXRvcnkzNTUxOTc4MjU=","notifications_url":"https://api.github.com/repos/repo/owner/notifications{?since,all,participating}","open_issues":1,"open_issues_count":1,"owner":{"avatar_url":"https://avatars.githubusercontent.com/u/57996262?v=4","events_url":"https://api.github.com/users/repo/events{/privacy}","followers_url":"https://api.github.com/users/repo/followers","following_url":"https://api.github.com/users/repo/following{/other_user}","gists_url":"https://api.github.com/users/repo/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/repo","id":57996262,"login":"repo","node_id":"MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy","organizations_url":"https://api.github.com/users/repo/orgs","received_events_url":"https://api.github.com/users/repo/received_events","repos_url":"https://api.github.com/users/repo/repos","site_admin":false,"starred_url":"https://api.github.com/users/repo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/repo/subscriptions","type":"Organization","url":"https://api.github.com/users/repo"},"private":false,"pulls_url":"https://api.github.com/repos/repo/owner/pulls{/number}","pushed_at":"2021-04-27T16:10:20Z","releases_url":"https://api.github.com/repos/repo/owner/releases{/id}","size":9122,"ssh_url":"git@github.com:repo/owner.git","stargazers_count":1,"stargazers_url":"https://api.github.com/repos/repo/owner/stargazers","statuses_url":"https://api.github.com/repos/repo/owner/statuses/{sha}","subscribers_url":"https://api.github.com/repos/repo/owner/subscribers","subscription_url":"https://api.github.com/repos/repo/owner/subscription","svn_url":"https://github.com/repo/owner","tags_url":"https://api.github.com/repos/repo/owner/tags","teams_url":"https://api.github.com/repos/repo/owner/teams","trees_url":"https://api.github.com/repos/repo/owner/git/trees{/sha}","updated_at":"2021-04-27T16:10:24Z","url":"https://api.github.com/repos/repo/owner","watchers":1,"watchers_count":1},"sha":"SHA","user":{"avatar_url":"https://avatars.githubusercontent.com/u/57996262?v=4","events_url":"https://api.github.com/users/repo/events{/privacy}","followers_url":"https://api.github.com/users/repo/followers","following_url":"https://api.github.com/users/repo/following{/other_user}","gists_url":"https://api.github.com/users/repo/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/repo","id":57996262,"login":"repo","node_id":"MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy","organizations_url":"https://api.github.com/users/repo/orgs","received_events_url":"https://api.github.com/users/repo/received_events","repos_url":"https://api.github.com/users/repo/repos","site_admin":false,"starred_url":"https://api.github.com/users/repo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/repo/subscriptions","type":"Organization","url":"https://api.github.com/users/repo"}},"body":"- Fix linting error  in payload Replace
-- Resolve pipelinespec embedded in PipelineRun too
-","changed_files":3,"closed_at":null,"comments":0,"comments_url":"https://api.github.com/repos/repo/owner/issues/3/comments","commits":2,"commits_url":"https://api.github.com/repos/repo/owner/pulls/3/commits","created_at":"2021-04-27T19:26:47Z","deletions":26,"diff_url":"https://github.com/repo/owner/pull/3.diff","draft":false,"head":{"label":"chmouel:fix-resolve-pipelinespec","ref":"fix-resolve-pipelinespec","repo":{"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_url":"https://api.github.com/repos/chmouel/owner/{archive_format}{/ref}","archived":false,"assignees_url":"https://api.github.com/repos/chmouel/owner/assignees{/user}","blobs_url":"https://api.github.com/repos/chmouel/owner/git/blobs{/sha}","branches_url":"https://api.github.com/repos/chmouel/owner/branches{/branch}","clone_url":"https://github.com/chmouel/owner.git","collaborators_url":"https://api.github.com/repos/chmouel/owner/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/chmouel/owner/comments{/number}","commits_url":"https://api.github.com/repos/chmouel/owner/commits{/sha}","compare_url":"https://api.github.com/repos/chmouel/owner/compare/{base}...{head}","contents_url":"https://api.github.com/repos/chmouel/owner/contents/{+path}","contributors_url":"https://api.github.com/repos/chmouel/owner/contributors","created_at":"2021-04-06T13:26:51Z","default_branch":"main","delete_branch_on_merge":false,"deployments_url":"https://api.github.com/repos/chmouel/owner/deployments","description":"Pipelines as Code","disabled":false,"downloads_url":"https://api.github.com/repos/chmouel/owner/downloads","events_url":"https://api.github.com/repos/chmouel/owner/events","fork":true,"forks":0,"forks_count":0,"forks_url":"https://api.github.com/repos/chmouel/owner/forks","full_name":"chmouel/owner","git_commits_url":"https://api.github.com/repos/chmouel/owner/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/chmouel/owner/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/chmouel/owner/git/tags{/sha}","git_url":"git://github.com/chmouel/owner.git","has_downloads":true,"has_issues":false,"has_pages":false,"has_projects":true,"has_wiki":true,"homepage":null,"hooks_url":"https://api.github.com/repos/chmouel/owner/hooks","html_url":"https://github.com/chmouel/owner","id":355198074,"issue_comment_url":"https://api.github.com/repos/chmouel/owner/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/chmouel/owner/issues/events{/number}","issues_url":"https://api.github.com/repos/chmouel/owner/issues{/number}","keys_url":"https://api.github.com/repos/chmouel/owner/keys{/key_id}","labels_url":"https://api.github.com/repos/chmouel/owner/labels{/name}","language":null,"languages_url":"https://api.github.com/repos/chmouel/owner/languages","license":{"key":"apache-2.0","name":"Apache License 2.0","node_id":"MDc6TGljZW5zZTI=","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"merges_url":"https://api.github.com/repos/chmouel/owner/merges","milestones_url":"https://api.github.com/repos/chmouel/owner/milestones{/number}","mirror_url":null,"name":"owner","node_id":"MDEwOlJlcG9zaXRvcnkzNTUxOTgwNzQ=","notifications_url":"https://api.github.com/repos/chmouel/owner/notifications{?since,all,participating}","open_issues":0,"open_issues_count":0,"owner":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"},"private":false,"pulls_url":"https://api.github.com/repos/chmouel/owner/pulls{/number}","pushed_at":"2021-04-27T19:26:46Z","releases_url":"https://api.github.com/repos/chmouel/owner/releases{/id}","size":5,"ssh_url":"git@github.com:chmouel/owner.git","stargazers_count":0,"stargazers_url":"https://api.github.com/repos/chmouel/owner/stargazers","statuses_url":"https://api.github.com/repos/chmouel/owner/statuses/{sha}","subscribers_url":"https://api.github.com/repos/chmouel/owner/subscribers","subscription_url":"https://api.github.com/repos/chmouel/owner/subscription","svn_url":"https://github.com/chmouel/owner","tags_url":"https://api.github.com/repos/chmouel/owner/tags","teams_url":"https://api.github.com/repos/chmouel/owner/teams","trees_url":"https://api.github.com/repos/chmouel/owner/git/trees{/sha}","updated_at":"2021-04-06T15:19:15Z","url":"https://api.github.com/repos/chmouel/owner","watchers":0,"watchers_count":0},"sha":"SHA","user":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"}},"html_url":"https://github.com/repo/owner/pull/3","id":624596967,"issue_url":"https://api.github.com/repos/repo/owner/issues/3","labels":[],"locked":false,"maintainer_can_modify":true,"merge_commit_sha":null,"mergeable":null,"mergeable_state":"unknown","merged":false,"merged_at":null,"merged_by":null,"milestone":null,"node_id":"MDExOlB1bGxSZXF1ZXN0NjI0NTk2OTY3","number":3,"patch_url":"https://github.com/repo/owner/pull/3.patch","rebaseable":null,"requested_reviewers":[],"requested_teams":[],"review_comment_url":"https://api.github.com/repos/repo/owner/pulls/comments{/number}","review_comments":0,"review_comments_url":"https://api.github.com/repos/repo/owner/pulls/3/comments","state":"open","statuses_url":"https://api.github.com/repos/repo/owner/statuses/SHA","title":"fix resolve pipelinespec","updated_at":"2021-04-27T19:26:47Z","url":"https://api.github.com/repos/repo/owner/pulls/3","user":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"}},"repository":{"archive_url":"https://api.github.com/repos/repo/owner/{archive_format}{/ref}","archived":false,"assignees_url":"https://api.github.com/repos/repo/owner/assignees{/user}","blobs_url":"https://api.github.com/repos/repo/owner/git/blobs{/sha}","branches_url":"https://api.github.com/repos/repo/owner/branches{/branch}","clone_url":"https://github.com/repo/owner.git","collaborators_url":"https://api.github.com/repos/repo/owner/collaborators{/collaborator}","comments_url":"https://api.github.com/repos/repo/owner/comments{/number}","commits_url":"https://api.github.com/repos/repo/owner/commits{/sha}","compare_url":"https://api.github.com/repos/repo/owner/compare/{base}...{head}","contents_url":"https://api.github.com/repos/repo/owner/contents/{+path}","contributors_url":"https://api.github.com/repos/repo/owner/contributors","created_at":"2021-04-06T13:26:01Z","default_branch":"main","deployments_url":"https://api.github.com/repos/repo/owner/deployments","description":"Pipelines as Code","disabled":false,"downloads_url":"https://api.github.com/repos/repo/owner/downloads","events_url":"https://api.github.com/repos/repo/owner/events","fork":false,"forks":3,"forks_count":3,"forks_url":"https://api.github.com/repos/repo/owner/forks","full_name":"repo/owner","git_commits_url":"https://api.github.com/repos/repo/owner/git/commits{/sha}","git_refs_url":"https://api.github.com/repos/repo/owner/git/refs{/sha}","git_tags_url":"https://api.github.com/repos/repo/owner/git/tags{/sha}","git_url":"git://github.com/repo/owner.git","has_downloads":true,"has_issues":true,"has_pages":false,"has_projects":true,"has_wiki":true,"homepage":null,"hooks_url":"https://api.github.com/repos/repo/owner/hooks","html_url":"https://github.com/repo/owner","id":355197825,"issue_comment_url":"https://api.github.com/repos/repo/owner/issues/comments{/number}","issue_events_url":"https://api.github.com/repos/repo/owner/issues/events{/number}","issues_url":"https://api.github.com/repos/repo/owner/issues{/number}","keys_url":"https://api.github.com/repos/repo/owner/keys{/key_id}","labels_url":"https://api.github.com/repos/repo/owner/labels{/name}","language":"Go","languages_url":"https://api.github.com/repos/repo/owner/languages","license":{"key":"apache-2.0","name":"Apache License 2.0","node_id":"MDc6TGljZW5zZTI=","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"merges_url":"https://api.github.com/repos/repo/owner/merges","milestones_url":"https://api.github.com/repos/repo/owner/milestones{/number}","mirror_url":null,"name":"owner","node_id":"MDEwOlJlcG9zaXRvcnkzNTUxOTc4MjU=","notifications_url":"https://api.github.com/repos/repo/owner/notifications{?since,all,participating}","open_issues":1,"open_issues_count":1,"owner":{"avatar_url":"https://avatars.githubusercontent.com/u/57996262?v=4","events_url":"https://api.github.com/users/repo/events{/privacy}","followers_url":"https://api.github.com/users/repo/followers","following_url":"https://api.github.com/users/repo/following{/other_user}","gists_url":"https://api.github.com/users/repo/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/repo","id":57996262,"login":"repo","node_id":"MDEyOk9yZ2FuaXphdGlvbjU3OTk2MjYy","organizations_url":"https://api.github.com/users/repo/orgs","received_events_url":"https://api.github.com/users/repo/received_events","repos_url":"https://api.github.com/users/repo/repos","site_admin":false,"starred_url":"https://api.github.com/users/repo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/repo/subscriptions","type":"Organization","url":"https://api.github.com/users/repo"},"private":false,"pulls_url":"https://api.github.com/repos/repo/owner/pulls{/number}","pushed_at":"2021-04-27T16:10:20Z","releases_url":"https://api.github.com/repos/repo/owner/releases{/id}","size":9122,"ssh_url":"git@github.com:repo/owner.git","stargazers_count":1,"stargazers_url":"https://api.github.com/repos/repo/owner/stargazers","statuses_url":"https://api.github.com/repos/repo/owner/statuses/{sha}","subscribers_url":"https://api.github.com/repos/repo/owner/subscribers","subscription_url":"https://api.github.com/repos/repo/owner/subscription","svn_url":"https://github.com/repo/owner","tags_url":"https://api.github.com/repos/repo/owner/tags","teams_url":"https://api.github.com/repos/repo/owner/teams","trees_url":"https://api.github.com/repos/repo/owner/git/trees{/sha}","updated_at":"2021-04-27T16:10:24Z","url":"https://api.github.com/repos/repo/owner","watchers":1,"watchers_count":1},"sender":{"avatar_url":"https://avatars.githubusercontent.com/u/98980?v=4","events_url":"https://api.github.com/users/chmouel/events{/privacy}","followers_url":"https://api.github.com/users/chmouel/followers","following_url":"https://api.github.com/users/chmouel/following{/other_user}","gists_url":"https://api.github.com/users/chmouel/gists{/gist_id}","gravatar_id":"","html_url":"https://github.com/chmouel","id":98980,"login":"chmouel","node_id":"MDQ6VXNlcjk4OTgw","organizations_url":"https://api.github.com/users/chmouel/orgs","received_events_url":"https://api.github.com/users/chmouel/received_events","repos_url":"https://api.github.com/users/chmouel/repos","site_admin":false,"starred_url":"https://api.github.com/users/chmouel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chmouel/subscriptions","type":"User","url":"https://api.github.com/users/chmouel"}}
diff --git a/test/README.md b/test/README.md
index 8cfc9e90..efc4e4c6 100644
--- a/test/README.md
+++ b/test/README.md
@@ -1,7 +1,6 @@
 # E2E Tests
 
-The E2E Tests make sure we have the repositories getting updated if we have a
-repo with PAC installed on it.
+The E2E Tests make sure we have the repositories getting updated if we have a repo with PAC installed on it.
 
 It will checks if the repository have been updated at the end.
 
@@ -10,13 +9,11 @@ Most E2E tests has this basic flow :
 - Create a temporary Namespace
 - Create a Repository CR into it
 - Create a Branch on a GitHUB repo
-- Create a commmit with files like pipelinerun inside that branch, the
-  pipelinerun with have the namespace annotation to force the repository match
-  on the namespace we have created and not catching other CR that may matching
-  it.
+- Create a commmit with files like pipelinerun inside that branch, the pipelinerun with have the namespace annotation to
+  force the repository match on the namespace we have created and not catching other CR that may matching it.
 - Wait that the Repository is updated.
-- Some other stuff are done directly on the eventlistenner sink, bypassing a bit
-  the GitHUB apis and generating the webhook ourselves.
+- Some other stuff are done directly on the eventlistenner sink, bypassing a bit the GitHUB apis and generating the
+  webhook ourselves.
 
 ## Requirements
 
@@ -25,8 +22,8 @@ You need to have those env variable set :
 - `TEST_GITHUB_API_URL` -- GitHub Api URL, needs to be set
 - `TEST_GITHUB_TOKEN` -- Github token used to talk to the api url
 - `TEST_GITHUB_REPO_OWNER` - The repo and owner (i.e: organization/repo)
-- `TEST_GITHUB_REPO_INSTALLATION_ID` - The installation id when you have
-  installed the repo on the app. (get it from the webhook event on the console)
+- `TEST_GITHUB_REPO_INSTALLATION_ID` - The installation id when you have installed the repo on the app. (get it from the
+  webhook event on the console)
 - `TEST_EL_URL` - The eventlistenner public url, ingress or openshfit's route
 - `TEST_EL_WEBHOOK_SECRET` - The webhook secret.
 
diff --git a/test/config_maxkeepruns_test.go b/test/config_maxkeepruns_test.go
index 49b10bf7..b77256ff 100644
--- a/test/config_maxkeepruns_test.go
+++ b/test/config_maxkeepruns_test.go
@@ -23,11 +23,11 @@ import (
 func TestMaxKeepRuns(t *testing.T) {
 	targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
 	ctx := context.Background()
-	cs, opts, err := setup()
+	runcnx, opts, ghcnx, err := setup(ctx)
 	assert.NilError(t, err)
 	maxKepRuns := 1
 
-	repoinfo, resp, err := cs.GithubClient.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
+	repoinfo, resp, err := ghcnx.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
 	assert.NilError(t, err)
 	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
 		t.Errorf("Repository %s not found in %s", opts.Owner, opts.Repo)
@@ -44,12 +44,12 @@ func TestMaxKeepRuns(t *testing.T) {
 		},
 	}
 
-	err = trepo.CreateNSRepo(ctx, targetNS, cs, repository)
+	err = trepo.CreateNSRepo(ctx, targetNS, runcnx, repository)
 	assert.NilError(t, err)
 
 	for prRun := 1; prRun <= maxKepRuns+1; prRun++ {
 		entries := map[string]string{
-			".tekton/run.yaml": fmt.Sprintf(`---
+			".tekton/info.yaml": fmt.Sprintf(`---
 apiVersion: tekton.dev/v1beta1
 kind: PipelineRun
 metadata:
@@ -59,7 +59,7 @@ metadata:
     pipelinesascode.tekton.dev/on-target-branch: "[%s]"
     pipelinesascode.tekton.dev/on-event: "[%s]"
     pipelinesascode.tekton.dev/max-keep-runs: "%d"
-    pipelinesascode.tekton.dev/test-current-run: "%d"
+    pipelinesascode.tekton.dev/test-current-info: "%d"
 spec:
   pipelineSpec:
     tasks:
@@ -75,26 +75,26 @@ spec:
 		targetRefName := fmt.Sprintf("refs/heads/%s",
 			names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test"))
 
-		sha, err := tgithub.PushFilesToRef(ctx, cs.GithubClient.Client, "TestMaxKeepRuns - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
+		sha, err := tgithub.PushFilesToRef(ctx, ghcnx.Client, "TestMaxKeepRuns - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
 		assert.NilError(t, err)
-		cs.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
+		runcnx.Clients.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
 
 		title := "TestMaxKeepRuns - " + targetRefName
-		number, err := tgithub.PRCreate(ctx, cs, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
+		number, err := tgithub.PRCreate(ctx, runcnx, ghcnx, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
 		assert.NilError(t, err)
 
-		defer tearDown(ctx, t, cs, number, targetRefName, targetNS, opts)
+		defer tearDown(ctx, t, runcnx, ghcnx, number, targetRefName, targetNS, opts)
 
-		cs.Log.Infof("Waiting for Repository to be updated")
-		err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
+		runcnx.Clients.Log.Infof("Waiting for Repository to be updated")
+		err = twait.UntilRepositoryUpdated(ctx, runcnx.Clients.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
 		assert.NilError(t, err)
 	}
 
-	prs, err := cs.Tekton.TektonV1alpha1().PipelineRuns(targetNS).List(ctx, metav1.ListOptions{})
+	prs, err := runcnx.Clients.Tekton.TektonV1alpha1().PipelineRuns(targetNS).List(ctx, metav1.ListOptions{})
 	assert.NilError(t, err)
 	assert.Equal(t, len(prs.Items), maxKepRuns)
 }
 
 // Local Variables:
-// compile-command: "go test -tags=e2e -v -run TestMaxKeepRuns$ ."
+// compile-command: "go test -tags=e2e -v -info TestMaxKeepRuns$ ."
 // End:
diff --git a/test/fixtures/check_suite_rerequest_push.json b/test/fixtures/check_suite_rerequest_push.json
index 01ea711c..ea2d0232 100644
--- a/test/fixtures/check_suite_rerequest_push.json
+++ b/test/fixtures/check_suite_rerequest_push.json
@@ -31,7 +31,6 @@
       "before": "ef75c7db8a921a8c0adaabe2e309f2f9d7ce5bd4",
       "after": "510a0faaa7cc35c5bab224655b435eaac76ec5a7",
       "pull_requests": [
-
       ],
       "app": {
         "id": 112592,
@@ -135,7 +134,6 @@
       ]
     },
     "pull_requests": [
-
     ]
   },
   "repository": {
diff --git a/test/fixtures/issue_comment-retest.json b/test/fixtures/issue_comment-retest.json
index 29b7ad2a..798587a1 100644
--- a/test/fixtures/issue_comment-retest.json
+++ b/test/fixtures/issue_comment-retest.json
@@ -32,13 +32,11 @@
       "site_admin": false
     },
     "labels": [
-
     ],
     "state": "open",
     "locked": false,
     "assignee": null,
     "assignees": [
-
     ],
     "milestone": null,
     "comments": 1,
diff --git a/test/fixtures/issue_comment_ok-to-test.json b/test/fixtures/issue_comment_ok-to-test.json
index 615ed327..e3d632dc 100644
--- a/test/fixtures/issue_comment_ok-to-test.json
+++ b/test/fixtures/issue_comment_ok-to-test.json
@@ -32,13 +32,11 @@
       "site_admin": false
     },
     "labels": [
-
     ],
     "state": "open",
     "locked": false,
     "assignee": null,
     "assignees": [
-
     ],
     "milestone": null,
     "comments": 7,
diff --git a/test/fixtures/pr-as-non-owner.json b/test/fixtures/pr-as-non-owner.json
index c3e3994e..b86ab3ec 100644
--- a/test/fixtures/pr-as-non-owner.json
+++ b/test/fixtures/pr-as-non-owner.json
@@ -32,13 +32,11 @@
       "site_admin": false
     },
     "labels": [
-
     ],
     "state": "open",
     "locked": false,
     "assignee": null,
     "assignees": [
-
     ],
     "milestone": null,
     "comments": 4,
diff --git a/test/fixtures/pull-req.json b/test/fixtures/pull-req.json
index 809833f6..cec12bae 100644
--- a/test/fixtures/pull-req.json
+++ b/test/fixtures/pull-req.json
@@ -41,16 +41,12 @@
     "merge_commit_sha": null,
     "assignee": null,
     "assignees": [
-
     ],
     "requested_reviewers": [
-
     ],
     "requested_teams": [
-
     ],
     "labels": [
-
     ],
     "milestone": null,
     "draft": false,
diff --git a/test/fixtures/push-ref-main.json b/test/fixtures/push-ref-main.json
index e10a9d11..037c3198 100644
--- a/test/fixtures/push-ref-main.json
+++ b/test/fixtures/push-ref-main.json
@@ -158,10 +158,8 @@
         "username": "chmouel"
       },
       "added": [
-
       ],
       "removed": [
-
       ],
       "modified": [
         "OWNERS"
@@ -186,10 +184,8 @@
       "username": "chmouel"
     },
     "added": [
-
     ],
     "removed": [
-
     ],
     "modified": [
       "OWNERS"
diff --git a/test/fixtures/push-tag-0.2.json b/test/fixtures/push-tag-0.2.json
index ab4df755..d2d7bb97 100644
--- a/test/fixtures/push-tag-0.2.json
+++ b/test/fixtures/push-tag-0.2.json
@@ -161,10 +161,8 @@
         ".tekton/tag-release.yaml"
       ],
       "removed": [
-
       ],
       "modified": [
-
       ]
     }
   ],
@@ -189,10 +187,8 @@
       ".tekton/tag-release.yaml"
     ],
     "removed": [
-
     ],
     "modified": [
-
     ]
   }
 }
diff --git a/test/fixtures/push.json b/test/fixtures/push.json
index c2ae420b..db96726c 100644
--- a/test/fixtures/push.json
+++ b/test/fixtures/push.json
@@ -173,10 +173,8 @@
         "username": "chmouel"
       },
       "added": [
-
       ],
       "removed": [
-
       ],
       "modified": [
         "README.md"
@@ -200,10 +198,8 @@
         "username": "web-flow"
       },
       "added": [
-
       ],
       "removed": [
-
       ],
       "modified": [
         "README.md"
@@ -228,10 +224,8 @@
       "username": "web-flow"
     },
     "added": [
-
     ],
     "removed": [
-
     ],
     "modified": [
       "README.md"
diff --git a/test/init_test.go b/test/init_test.go
index 914adcd6..55d37878 100644
--- a/test/init_test.go
+++ b/test/init_test.go
@@ -12,9 +12,10 @@ import (
 	"testing"
 	"time"
 
-	"github.com/google/go-github/v35/github"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	ghlib "github.com/google/go-github/v35/github"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs/github"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -28,32 +29,33 @@ type E2EOptions struct {
 	Repo, Owner string
 }
 
-func tearDown(ctx context.Context, t *testing.T, cs *cli.Clients, prNumber int, ref string, targetNS string, opts E2EOptions) {
-	cs.Log.Infof("Closing PR %d", prNumber)
+func tearDown(ctx context.Context, t *testing.T, runcnx *params.Run, ghvcs github.VCS,
+	prNumber int, ref string, targetNS string, opts E2EOptions) {
+	runcnx.Clients.Log.Infof("Closing PR %d", prNumber)
 	if prNumber != -1 {
 		state := "closed"
-		_, _, err := cs.GithubClient.Client.PullRequests.Edit(ctx,
+		_, _, err := ghvcs.Client.PullRequests.Edit(ctx,
 			opts.Owner, opts.Repo, prNumber,
-			&github.PullRequest{State: &state})
+			&ghlib.PullRequest{State: &state})
 		if err != nil {
 			t.Fatal(err)
 		}
 	}
 
-	cs.Log.Infof("Deleting NS %s", targetNS)
-	err := cs.Kube.CoreV1().Namespaces().Delete(ctx, targetNS, metav1.DeleteOptions{})
+	runcnx.Clients.Log.Infof("Deleting NS %s", targetNS)
+	err := runcnx.Clients.Kube.CoreV1().Namespaces().Delete(ctx, targetNS, metav1.DeleteOptions{})
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	cs.Log.Infof("Deleting Ref %s", ref)
-	_, err = cs.GithubClient.Client.Git.DeleteRef(ctx, opts.Owner, opts.Repo, ref)
+	runcnx.Clients.Log.Infof("Deleting Ref %s", ref)
+	_, err = ghvcs.Client.Git.DeleteRef(ctx, opts.Owner, opts.Repo, ref)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
-func setup() (*cli.Clients, E2EOptions, error) {
+func setup(ctx context.Context) (*params.Run, E2EOptions, github.VCS, error) {
 	githubURL := os.Getenv("TEST_GITHUB_API_URL")
 	githubToken := os.Getenv("TEST_GITHUB_TOKEN")
 	githubRepoOwner := os.Getenv("TEST_GITHUB_REPO_OWNER")
@@ -63,24 +65,25 @@ func setup() (*cli.Clients, E2EOptions, error) {
 		"GITHUB_REPO_OWNER", "EL_WEBHOOK_SECRET",
 	} {
 		if env := os.Getenv("TEST_" + value); env == "" {
-			return nil, E2EOptions{}, fmt.Errorf("\"TEST_%s\" env variable is required, cannot continue", value)
+			return nil, E2EOptions{}, github.VCS{}, fmt.Errorf("\"TEST_%s\" env variable is required, cannot continue", value)
 		}
 	}
 
 	if githubURL == "" || githubToken == "" || githubRepoOwner == "" {
-		return nil, E2EOptions{}, fmt.Errorf("TEST_GITHUB_API_URL TEST_GITHUB_TOKEN TEST_GITHUB_REPO_OWNER need to be set")
+		return nil, E2EOptions{}, github.VCS{}, fmt.Errorf("TEST_GITHUB_API_URL TEST_GITHUB_TOKEN TEST_GITHUB_REPO_OWNER need to be set")
 	}
 
 	splitted := strings.Split(githubRepoOwner, "/")
-	webvcs := webvcs.NewGithubVCS(githubToken, githubURL)
-
-	p := cli.PacParams{}
-	cs, err := p.Clients()
-	if err != nil {
-		return nil, E2EOptions{}, err
+	run := &params.Run{}
+	if err := run.Clients.NewClients(&run.Info); err != nil {
+		return nil, E2EOptions{}, github.VCS{}, err
 	}
-	cs.GithubClient = webvcs
-	return cs, E2EOptions{Owner: splitted[0], Repo: splitted[1]}, nil
+	e2eoptions := E2EOptions{Owner: splitted[0], Repo: splitted[1]}
+	gvcs := github.NewGithubVCS(ctx, info.PacOpts{
+		VCSToken:  githubToken,
+		VCSAPIURL: githubURL,
+	})
+	return run, e2eoptions, gvcs, nil
 }
 
 func TestMain(m *testing.M) {
diff --git a/test/pkg/github/pr.go b/test/pkg/github/pr.go
index 3726f921..03661033 100644
--- a/test/pkg/github/pr.go
+++ b/test/pkg/github/pr.go
@@ -5,7 +5,8 @@ import (
 	"encoding/base64"
 
 	"github.com/google/go-github/v35/github"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
+	ghvcs "github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs/github"
 )
 
 func PushFilesToRef(ctx context.Context, client *github.Client, commitMessage, baseBranch, targetRef, owner, repo string, files map[string]string) (string, error) {
@@ -51,9 +52,11 @@ func PushFilesToRef(ctx context.Context, client *github.Client, commitMessage, b
 		},
 		Message: &commitMessage,
 		Tree:    tree,
-		Parents: []*github.Commit{{
-			SHA: &mainSha,
-		}},
+		Parents: []*github.Commit{
+			{
+				SHA: &mainSha,
+			},
+		},
 	})
 	if err != nil {
 		return "", err
@@ -73,8 +76,8 @@ func PushFilesToRef(ctx context.Context, client *github.Client, commitMessage, b
 	return commit.GetSHA(), nil
 }
 
-func PRCreate(ctx context.Context, cs *cli.Clients, owner, repo, targetRef, defaultBranch, title string) (int, error) {
-	pr, _, err := cs.GithubClient.Client.PullRequests.Create(ctx, owner, repo, &github.NewPullRequest{
+func PRCreate(ctx context.Context, cs *params.Run, ghcnx ghvcs.VCS, owner, repo, targetRef, defaultBranch, title string) (int, error) {
+	pr, _, err := ghcnx.Client.PullRequests.Create(ctx, owner, repo, &github.NewPullRequest{
 		Title: &title,
 		Head:  &targetRef,
 		Base:  &defaultBranch,
@@ -83,6 +86,6 @@ func PRCreate(ctx context.Context, cs *cli.Clients, owner, repo, targetRef, defa
 	if err != nil {
 		return -1, err
 	}
-	cs.Log.Infof("Pull request created: %s", pr.GetHTMLURL())
+	cs.Clients.Log.Infof("Pull request created: %s", pr.GetHTMLURL())
 	return pr.GetNumber(), nil
 }
diff --git a/test/pkg/payload/send.go b/test/pkg/payload/send.go
index efd0c0c8..8b249628 100644
--- a/test/pkg/payload/send.go
+++ b/test/pkg/payload/send.go
@@ -16,15 +16,15 @@ import (
 	"net/http"
 	"net/url"
 
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 )
 
-func Send(ctx context.Context, cs *cli.Clients, elURL, elWebHookSecret, githubURL, installationID string, event interface{}, eventType string) error {
+func Send(ctx context.Context, cs *params.Run, elURL, elWebHookSecret, githubURL, installationID string, event interface{}, eventType string) error {
 	jeez, err := json.Marshal(event)
 	if err != nil {
 		return err
 	}
-	cs.Log.Infof("Sending a payload directly to the EL on %s: %s", os.Getenv("TEST_EL_URL"), string(jeez))
+	cs.Clients.Log.Infof("Sending a payload directly to the EL on %s: %s", os.Getenv("TEST_EL_URL"), string(jeez))
 
 	mac := hmac.New(sha1.New, []byte(elWebHookSecret))
 	mac.Write(jeez)
diff --git a/test/pkg/repository/create.go b/test/pkg/repository/create.go
index b5e03d95..2ea0297f 100644
--- a/test/pkg/repository/create.go
+++ b/test/pkg/repository/create.go
@@ -4,22 +4,22 @@ import (
 	"context"
 
 	pacv1alpha1 "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-func CreateNSRepo(ctx context.Context, targetNS string, cs *cli.Clients,
+func CreateNSRepo(ctx context.Context, targetNS string, cs *params.Run,
 	repository *pacv1alpha1.Repository) error {
 	nsSpec := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: targetNS}}
-	_, err := cs.Kube.CoreV1().Namespaces().Create(ctx, nsSpec, metav1.CreateOptions{})
+	_, err := cs.Clients.Kube.CoreV1().Namespaces().Create(ctx, nsSpec, metav1.CreateOptions{})
 	if err != nil {
 		return err
 	}
-	repo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Create(ctx, repository, metav1.CreateOptions{})
+	repo, err := cs.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Create(ctx, repository, metav1.CreateOptions{})
 	if err != nil {
 		return err
 	}
-	cs.Log.Infof("Repository created in %s", repo.GetNamespace())
+	cs.Clients.Log.Infof("Repository created in %s", repo.GetNamespace())
 	return nil
 }
diff --git a/test/pullrequest_oktotest_test.go b/test/pullrequest_oktotest_test.go
index e90b3d63..87888660 100644
--- a/test/pullrequest_oktotest_test.go
+++ b/test/pullrequest_oktotest_test.go
@@ -13,7 +13,7 @@ import (
 
 	"github.com/google/go-github/v35/github"
 	pacv1alpha1 "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	tgithub "github.com/openshift-pipelines/pipelines-as-code/test/pkg/github"
 	"github.com/openshift-pipelines/pipelines-as-code/test/pkg/payload"
 	trepo "github.com/openshift-pipelines/pipelines-as-code/test/pkg/repository"
@@ -27,11 +27,11 @@ import (
 func TestPullRequestOkToTest(t *testing.T) {
 	targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
 	ctx := context.Background()
-	cs, opts, err := setup()
+	runcnx, opts, ghcnx, err := setup(ctx)
 	assert.NilError(t, err)
 
 	entries := map[string]string{
-		".tekton/run.yaml": fmt.Sprintf(`---
+		".tekton/info.yaml": fmt.Sprintf(`---
 apiVersion: tekton.dev/v1beta1
 kind: PipelineRun
 metadata:
@@ -52,7 +52,7 @@ spec:
 `, targetNS, mainBranch, pullRequestEvent),
 	}
 
-	repoinfo, resp, err := cs.GithubClient.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
+	repoinfo, resp, err := ghcnx.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
 	assert.NilError(t, err)
 	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
 		t.Errorf("Repository %s not found in %s", opts.Owner, opts.Repo)
@@ -70,31 +70,31 @@ spec:
 		},
 	}
 
-	err = trepo.CreateNSRepo(ctx, targetNS, cs, repository)
+	err = trepo.CreateNSRepo(ctx, targetNS, runcnx, repository)
 	assert.NilError(t, err)
 
 	targetRefName := fmt.Sprintf("refs/heads/%s",
 		names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test"))
 
-	sha, err := tgithub.PushFilesToRef(ctx, cs.GithubClient.Client,
+	sha, err := tgithub.PushFilesToRef(ctx, ghcnx.Client,
 		"TestPullRequest - "+targetRefName, repoinfo.GetDefaultBranch(),
 		targetRefName,
 		opts.Owner,
 		opts.Repo,
 		entries)
 	assert.NilError(t, err)
-	cs.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
+	runcnx.Clients.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
 	title := "TestPullRequestOkToTest on " + targetRefName
-	number, err := tgithub.PRCreate(ctx, cs, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
+	number, err := tgithub.PRCreate(ctx, runcnx, ghcnx, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
 	assert.NilError(t, err)
 
-	defer tearDown(ctx, t, cs, number, targetRefName, targetNS, opts)
+	defer tearDown(ctx, t, runcnx, ghcnx, number, targetRefName, targetNS, opts)
 
-	cs.Log.Infof("Waiting for Repository to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
+	runcnx.Clients.Log.Infof("Waiting for Repository to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, runcnx.Clients.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
 	assert.NilError(t, err)
 
-	runinfo := webvcs.RunInfo{
+	runevent := info.Event{
 		BaseBranch:    repoinfo.GetDefaultBranch(),
 		DefaultBranch: repoinfo.GetDefaultBranch(),
 		HeadBranch:    targetRefName,
@@ -124,18 +124,18 @@ spec:
 			},
 		},
 		Repo: &github.Repository{
-			DefaultBranch: &runinfo.DefaultBranch,
-			HTMLURL:       &runinfo.URL,
-			Name:          &runinfo.Repository,
-			Owner:         &github.User{Login: &runinfo.Owner},
+			DefaultBranch: &runevent.DefaultBranch,
+			HTMLURL:       &runevent.URL,
+			Name:          &runevent.Repository,
+			Owner:         &github.User{Login: &runevent.Owner},
 		},
 		Sender: &github.User{
-			Login: &runinfo.Sender,
+			Login: &runevent.Sender,
 		},
 	}
 
 	err = payload.Send(ctx,
-		cs,
+		runcnx,
 		os.Getenv("TEST_EL_URL"),
 		os.Getenv("TEST_EL_WEBHOOK_SECRET"),
 		os.Getenv("TEST_GITHUB_API_URL"),
@@ -145,12 +145,12 @@ spec:
 	)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Wait for the second repository update to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 1, defaultTimeout)
+	runcnx.Clients.Log.Infof("Wait for the second repository update to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, runcnx.Clients.PipelineAsCode, targetNS, targetNS, 1, defaultTimeout)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Check if we have the repository set as succeeded")
-	repo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
+	runcnx.Clients.Log.Infof("Check if we have the repository set as succeeded")
+	repo, err := runcnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
 	assert.NilError(t, err)
 	assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue)
 }
diff --git a/test/pullrequest_privaterepository_test.go b/test/pullrequest_privaterepository_test.go
index 358b3149..583b80f7 100644
--- a/test/pullrequest_privaterepository_test.go
+++ b/test/pullrequest_privaterepository_test.go
@@ -24,17 +24,17 @@ import (
 func TestPullRequestPrivateRepository(t *testing.T) {
 	targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
 	ctx := context.Background()
-	cs, opts, err := setup()
+	run, opts, ghcnx, err := setup(ctx)
 	assert.NilError(t, err)
 
 	prun, err := ioutil.ReadFile("testdata/pipelinerun_git_clone_private.yaml")
 	assert.NilError(t, err)
 
 	entries := map[string]string{
-		".tekton/run.yaml": fmt.Sprintf(string(prun), targetNS, mainBranch, pullRequestEvent),
+		".tekton/info.yaml": fmt.Sprintf(string(prun), targetNS, mainBranch, pullRequestEvent),
 	}
 
-	repoinfo, resp, err := cs.GithubClient.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
+	repoinfo, resp, err := ghcnx.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
 	assert.NilError(t, err)
 	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
 		t.Errorf("Repository %s not found in %s", opts.Owner, opts.Repo)
@@ -52,28 +52,28 @@ func TestPullRequestPrivateRepository(t *testing.T) {
 		},
 	}
 
-	err = trepo.CreateNSRepo(ctx, targetNS, cs, repository)
+	err = trepo.CreateNSRepo(ctx, targetNS, run, repository)
 	assert.NilError(t, err)
 
 	targetRefName := fmt.Sprintf("refs/heads/%s",
 		names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test"))
 
-	sha, err := tgithub.PushFilesToRef(ctx, cs.GithubClient.Client, "TestPullRequestPrivateRepository - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
+	sha, err := tgithub.PushFilesToRef(ctx, ghcnx.Client, "TestPullRequestPrivateRepository - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
 	assert.NilError(t, err)
-	cs.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
+	run.Clients.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
 
 	title := "TestPullRequestPrivateRepository - " + targetRefName
-	number, err := tgithub.PRCreate(ctx, cs, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
+	number, err := tgithub.PRCreate(ctx, run, ghcnx, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
 	assert.NilError(t, err)
 
-	defer tearDown(ctx, t, cs, number, targetRefName, targetNS, opts)
+	defer tearDown(ctx, t, run, ghcnx, number, targetRefName, targetNS, opts)
 
-	cs.Log.Infof("Waiting for Repository to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
+	run.Clients.Log.Infof("Waiting for Repository to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, run.Clients.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Check if we have the repository set as succeeded")
-	repo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
+	run.Clients.Log.Infof("Check if we have the repository set as succeeded")
+	repo, err := run.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
 	assert.NilError(t, err)
 	laststatus := repo.Status[len(repo.Status)-1]
 	assert.Equal(t, corev1.ConditionTrue, laststatus.Conditions[0].Status)
@@ -82,7 +82,7 @@ func TestPullRequestPrivateRepository(t *testing.T) {
 	assert.Equal(t, title, *laststatus.Title)
 	assert.Assert(t, *laststatus.LogURL != "")
 
-	pr, err := cs.Tekton.TektonV1alpha1().PipelineRuns(targetNS).Get(ctx, laststatus.PipelineRunName, metav1.GetOptions{})
+	pr, err := run.Clients.Tekton.TektonV1alpha1().PipelineRuns(targetNS).Get(ctx, laststatus.PipelineRunName, metav1.GetOptions{})
 	assert.NilError(t, err)
 
 	assert.Equal(t, "pull_request", pr.Labels["pipelinesascode.tekton.dev/event-type"])
@@ -97,5 +97,5 @@ func TestPullRequestPrivateRepository(t *testing.T) {
 }
 
 // Local Variables:
-// compile-command: "go test -tags=e2e -v -run TestPullRequestPrivateRepository$ ."
+// compile-command: "go test -tags=e2e -v -info TestPullRequestPrivateRepository$ ."
 // End:
diff --git a/test/pullrequest_rerequest_test.go b/test/pullrequest_rerequest_test.go
index 202a0076..c7952b90 100644
--- a/test/pullrequest_rerequest_test.go
+++ b/test/pullrequest_rerequest_test.go
@@ -13,7 +13,7 @@ import (
 
 	"github.com/google/go-github/v35/github"
 	pacv1alpha1 "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
-	"github.com/openshift-pipelines/pipelines-as-code/pkg/webvcs"
+	"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
 	tgithub "github.com/openshift-pipelines/pipelines-as-code/test/pkg/github"
 	"github.com/openshift-pipelines/pipelines-as-code/test/pkg/payload"
 	trepo "github.com/openshift-pipelines/pipelines-as-code/test/pkg/repository"
@@ -27,11 +27,11 @@ import (
 func TestPullRerequest(t *testing.T) {
 	targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
 	ctx := context.Background()
-	cs, opts, err := setup()
+	runcnx, opts, ghcnx, err := setup(ctx)
 	assert.NilError(t, err)
 
 	entries := map[string]string{
-		".tekton/run.yaml": fmt.Sprintf(`---
+		".tekton/info.yaml": fmt.Sprintf(`---
 apiVersion: tekton.dev/v1beta1
 kind: PipelineRun
 metadata:
@@ -52,7 +52,7 @@ spec:
 `, targetNS, mainBranch, pullRequestEvent),
 	}
 
-	repoinfo, resp, err := cs.GithubClient.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
+	repoinfo, resp, err := ghcnx.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
 	assert.NilError(t, err)
 	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
 		t.Errorf("Repository %s not found in %s", opts.Owner, opts.Repo)
@@ -70,31 +70,31 @@ spec:
 		},
 	}
 
-	err = trepo.CreateNSRepo(ctx, targetNS, cs, repository)
+	err = trepo.CreateNSRepo(ctx, targetNS, runcnx, repository)
 	assert.NilError(t, err)
 
 	targetRefName := fmt.Sprintf("refs/heads/%s",
 		names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test"))
 
-	sha, err := tgithub.PushFilesToRef(ctx, cs.GithubClient.Client,
+	sha, err := tgithub.PushFilesToRef(ctx, ghcnx.Client,
 		"TestPullRequest - "+targetRefName, repoinfo.GetDefaultBranch(),
 		targetRefName,
 		opts.Owner,
 		opts.Repo,
 		entries)
 	assert.NilError(t, err)
-	cs.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
+	runcnx.Clients.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
 	title := "TestPullRerequest on " + targetRefName
-	number, err := tgithub.PRCreate(ctx, cs, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
+	number, err := tgithub.PRCreate(ctx, runcnx, ghcnx, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
 	assert.NilError(t, err)
 
-	defer tearDown(ctx, t, cs, number, targetRefName, targetNS, opts)
+	defer tearDown(ctx, t, runcnx, ghcnx, number, targetRefName, targetNS, opts)
 
-	cs.Log.Infof("Waiting for Repository to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
+	runcnx.Clients.Log.Infof("Waiting for Repository to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, runcnx.Clients.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
 	assert.NilError(t, err)
 
-	runinfo := webvcs.RunInfo{
+	runinfo := info.Event{
 		BaseBranch:    repoinfo.GetDefaultBranch(),
 		DefaultBranch: repoinfo.GetDefaultBranch(),
 		HeadBranch:    targetRefName,
@@ -135,7 +135,7 @@ spec:
 	}
 
 	err = payload.Send(ctx,
-		cs,
+		runcnx,
 		os.Getenv("TEST_EL_URL"),
 		os.Getenv("TEST_EL_WEBHOOK_SECRET"),
 		os.Getenv("TEST_GITHUB_API_URL"),
@@ -145,12 +145,12 @@ spec:
 	)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Wait for the second repository update to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 1, defaultTimeout)
+	runcnx.Clients.Log.Infof("Wait for the second repository update to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, runcnx.Clients.PipelineAsCode, targetNS, targetNS, 1, defaultTimeout)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Check if we have the repository set as succeeded")
-	repo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
+	runcnx.Clients.Log.Infof("Check if we have the repository set as succeeded")
+	repo, err := runcnx.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
 	assert.NilError(t, err)
 	assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue)
 }
diff --git a/test/pullrequest_retest_test.go b/test/pullrequest_retest_test.go
index 4d87df1b..492eceff 100644
--- a/test/pullrequest_retest_test.go
+++ b/test/pullrequest_retest_test.go
@@ -23,11 +23,11 @@ import (
 func TestPullRequestRetest(t *testing.T) {
 	targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
 	ctx := context.Background()
-	cs, opts, err := setup()
+	run, opts, ghcnx, err := setup(ctx)
 	assert.NilError(t, err)
 
 	entries := map[string]string{
-		".tekton/run.yaml": fmt.Sprintf(`---
+		".tekton/info.yaml": fmt.Sprintf(`---
 apiVersion: tekton.dev/v1beta1
 kind: PipelineRun
 metadata:
@@ -48,7 +48,7 @@ spec:
 `, targetNS, mainBranch, pullRequestEvent),
 	}
 
-	repoinfo, resp, err := cs.GithubClient.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
+	repoinfo, resp, err := ghcnx.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
 	assert.NilError(t, err)
 	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
 		t.Errorf("Repository %s not found in %s", opts.Owner, opts.Repo)
@@ -66,39 +66,39 @@ spec:
 		},
 	}
 
-	err = trepo.CreateNSRepo(ctx, targetNS, cs, repository)
+	err = trepo.CreateNSRepo(ctx, targetNS, run, repository)
 	assert.NilError(t, err)
 
 	targetRefName := fmt.Sprintf("refs/heads/%s",
 		names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test"))
 
-	sha, err := tgithub.PushFilesToRef(ctx, cs.GithubClient.Client, "TestRetest - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
+	sha, err := tgithub.PushFilesToRef(ctx, ghcnx.Client, "TestRetest - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
 	assert.NilError(t, err)
-	cs.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
+	run.Clients.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
 	title := "TestPullRequestRetest on " + targetRefName
 
-	number, err := tgithub.PRCreate(ctx, cs, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
+	number, err := tgithub.PRCreate(ctx, run, ghcnx, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
 	assert.NilError(t, err)
 
-	defer tearDown(ctx, t, cs, number, targetRefName, targetNS, opts)
+	defer tearDown(ctx, t, run, ghcnx, number, targetRefName, targetNS, opts)
 
-	cs.Log.Infof("Waiting for Repository to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
+	run.Clients.Log.Infof("Waiting for Repository to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, run.Clients.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Creating /retest in PullRequest")
-	_, _, err = cs.GithubClient.Client.Issues.CreateComment(ctx,
+	run.Clients.Log.Infof("Creating /retest in PullRequest")
+	_, _, err = ghcnx.Client.Issues.CreateComment(ctx,
 		opts.Owner,
 		opts.Repo, number,
 		&github.IssueComment{Body: github.String("/retest")})
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Wait for the second repository update to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 1, defaultTimeout)
+	run.Clients.Log.Infof("Wait for the second repository update to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, run.Clients.PipelineAsCode, targetNS, targetNS, 1, defaultTimeout)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Check if we have the repository set as succeeded")
-	repo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
+	run.Clients.Log.Infof("Check if we have the repository set as succeeded")
+	repo, err := run.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
 	assert.NilError(t, err)
 	assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue)
 }
diff --git a/test/pullrequest_test.go b/test/pullrequest_test.go
index f60d60c3..040f3263 100644
--- a/test/pullrequest_test.go
+++ b/test/pullrequest_test.go
@@ -23,11 +23,11 @@ import (
 func TestPullRequest(t *testing.T) {
 	targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
 	ctx := context.Background()
-	cs, opts, err := setup()
+	run, opts, ghvcs, err := setup(ctx)
 	assert.NilError(t, err)
 
 	entries := map[string]string{
-		".tekton/run.yaml": fmt.Sprintf(`---
+		".tekton/info.yaml": fmt.Sprintf(`---
 apiVersion: tekton.dev/v1beta1
 kind: PipelineRun
 metadata:
@@ -48,7 +48,7 @@ spec:
 `, targetNS, mainBranch, pullRequestEvent),
 	}
 
-	repoinfo, resp, err := cs.GithubClient.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
+	repoinfo, resp, err := ghvcs.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
 	assert.NilError(t, err)
 	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
 		t.Errorf("Repository %s not found in %s", opts.Owner, opts.Repo)
@@ -66,28 +66,28 @@ spec:
 		},
 	}
 
-	err = trepo.CreateNSRepo(ctx, targetNS, cs, repository)
+	err = trepo.CreateNSRepo(ctx, targetNS, run, repository)
 	assert.NilError(t, err)
 
 	targetRefName := fmt.Sprintf("refs/heads/%s",
 		names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-test"))
 
-	sha, err := tgithub.PushFilesToRef(ctx, cs.GithubClient.Client, "TestPullRequest - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
+	sha, err := tgithub.PushFilesToRef(ctx, ghvcs.Client, "TestPullRequest - "+targetRefName, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
 	assert.NilError(t, err)
-	cs.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
+	run.Clients.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
 
 	title := "TestPullRequest - " + targetRefName
-	number, err := tgithub.PRCreate(ctx, cs, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
+	number, err := tgithub.PRCreate(ctx, run, ghvcs, opts.Owner, opts.Repo, targetRefName, repoinfo.GetDefaultBranch(), title)
 	assert.NilError(t, err)
 
-	defer tearDown(ctx, t, cs, number, targetRefName, targetNS, opts)
+	defer tearDown(ctx, t, run, ghvcs, number, targetRefName, targetNS, opts)
 
-	cs.Log.Infof("Waiting for Repository to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
+	run.Clients.Log.Infof("Waiting for Repository to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, run.Clients.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Check if we have the repository set as succeeded")
-	repo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
+	run.Clients.Log.Infof("Check if we have the repository set as succeeded")
+	repo, err := run.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
 	assert.NilError(t, err)
 	laststatus := repo.Status[len(repo.Status)-1]
 	assert.Equal(t, corev1.ConditionTrue, laststatus.Conditions[0].Status)
@@ -96,7 +96,7 @@ spec:
 	assert.Equal(t, title, *laststatus.Title)
 	assert.Assert(t, *laststatus.LogURL != "")
 
-	pr, err := cs.Tekton.TektonV1alpha1().PipelineRuns(targetNS).Get(ctx, laststatus.PipelineRunName, metav1.GetOptions{})
+	pr, err := run.Clients.Tekton.TektonV1alpha1().PipelineRuns(targetNS).Get(ctx, laststatus.PipelineRunName, metav1.GetOptions{})
 	assert.NilError(t, err)
 
 	assert.Equal(t, "pull_request", pr.Labels["pipelinesascode.tekton.dev/event-type"])
@@ -111,5 +111,5 @@ spec:
 }
 
 // Local Variables:
-// compile-command: "go test -tags=e2e -v -run TestPullRequest$ ."
+// compile-command: "go test -tags=e2e -v -info TestPullRequest$ ."
 // End:
diff --git a/test/push_test.go b/test/push_test.go
index 79049663..b5132812 100644
--- a/test/push_test.go
+++ b/test/push_test.go
@@ -25,10 +25,10 @@ func TestPush(t *testing.T) {
 	targetEvent := "push"
 
 	ctx := context.Background()
-	cs, opts, err := setup()
+	run, opts, gvcs, err := setup(ctx)
 	assert.NilError(t, err)
 
-	repoinfo, resp, err := cs.GithubClient.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
+	repoinfo, resp, err := gvcs.Client.Repositories.Get(ctx, opts.Owner, opts.Repo)
 	assert.NilError(t, err)
 	if resp != nil && resp.Response.StatusCode == http.StatusNotFound {
 		t.Errorf("Repository %s not found in %s", opts.Owner, opts.Repo)
@@ -46,11 +46,11 @@ func TestPush(t *testing.T) {
 		},
 	}
 
-	err = trepo.CreateNSRepo(ctx, targetNS, cs, repository)
+	err = trepo.CreateNSRepo(ctx, targetNS, run, repository)
 	assert.NilError(t, err)
 
 	entries := map[string]string{
-		".tekton/run.yaml": fmt.Sprintf(`---
+		".tekton/info.yaml": fmt.Sprintf(`---
 apiVersion: tekton.dev/v1beta1
 kind: PipelineRun
 metadata:
@@ -72,17 +72,17 @@ spec:
 	}
 
 	targetRefName := fmt.Sprintf("refs/heads/%s", targetBranch)
-	sha, err := tgithub.PushFilesToRef(ctx, cs.GithubClient.Client, "TestPush - "+targetBranch, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
-	cs.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
+	sha, err := tgithub.PushFilesToRef(ctx, gvcs.Client, "TestPush - "+targetBranch, repoinfo.GetDefaultBranch(), targetRefName, opts.Owner, opts.Repo, entries)
+	run.Clients.Log.Infof("Commit %s has been created and pushed to %s", sha, targetRefName)
 	assert.NilError(t, err)
-	defer tearDown(ctx, t, cs, -1, targetRefName, targetNS, opts)
+	defer tearDown(ctx, t, run, gvcs, -1, targetRefName, targetNS, opts)
 
-	cs.Log.Infof("Waiting for Repository to be updated")
-	err = twait.UntilRepositoryUpdated(ctx, cs.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
+	run.Clients.Log.Infof("Waiting for Repository to be updated")
+	err = twait.UntilRepositoryUpdated(ctx, run.Clients.PipelineAsCode, targetNS, targetNS, 0, defaultTimeout)
 	assert.NilError(t, err)
 
-	cs.Log.Infof("Check if we have the repository set as succeeded")
-	repo, err := cs.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
+	run.Clients.Log.Infof("Check if we have the repository set as succeeded")
+	repo, err := run.Clients.PipelineAsCode.PipelinesascodeV1alpha1().Repositories(targetNS).Get(ctx, targetNS, metav1.GetOptions{})
 	assert.NilError(t, err)
 	assert.Assert(t, repo.Status[len(repo.Status)-1].Conditions[0].Status == corev1.ConditionTrue)
 }